mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
JNI implementation for Java
Normal vs
This commit is contained in:
@@ -1,130 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tInstances;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author dtjones
|
||||
*/
|
||||
public class ADXL345_I2C extends SensorBase {
|
||||
|
||||
private static final byte kAddress = 0x3A;
|
||||
private static final byte kPowerCtlRegister = 0x2D;
|
||||
private static final byte kDataFormatRegister = 0x31;
|
||||
private static final byte kDataRegister = 0x32;
|
||||
private static final double kGsPerLSB = 0.00390625;
|
||||
private static final byte kPowerCtl_Link = 0x20, kPowerCtl_AutoSleep = 0x10, kPowerCtl_Measure = 0x08, kPowerCtl_Sleep = 0x04;
|
||||
private static final byte kDataFormat_SelfTest = (byte) 0x80, kDataFormat_SPI = 0x40, kDataFormat_IntInvert = 0x20, kDataFormat_FullRes = 0x08, kDataFormat_Justify = 0x04;
|
||||
|
||||
public static class DataFormat_Range {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final byte value;
|
||||
static final byte k2G_val = 0x00;
|
||||
static final byte k4G_val = 0x01;
|
||||
static final byte k8G_val = 0x02;
|
||||
static final byte k16G_val = 0x03;
|
||||
public static final DataFormat_Range k2G = new DataFormat_Range(k2G_val);
|
||||
public static final DataFormat_Range k4G = new DataFormat_Range(k4G_val);
|
||||
public static final DataFormat_Range k8G = new DataFormat_Range(k8G_val);
|
||||
public static final DataFormat_Range k16G = new DataFormat_Range(k16G_val);
|
||||
|
||||
private DataFormat_Range(byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Axes {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final byte value;
|
||||
static final byte kX_val = 0x00;
|
||||
static final byte kY_val = 0x02;
|
||||
static final byte kZ_val = 0x04;
|
||||
public static final Axes kX = new Axes(kX_val);
|
||||
public static final Axes kY = new Axes(kY_val);
|
||||
public static final Axes kZ = new Axes(kZ_val);
|
||||
|
||||
private Axes(byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AllAxes {
|
||||
|
||||
public double XAxis;
|
||||
public double YAxis;
|
||||
public double ZAxis;
|
||||
}
|
||||
private I2C m_i2c;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param module The slot of the digital module that the sensor is plugged into.
|
||||
* @param range The range (+ or -) that the accelerometer will measure.
|
||||
*/
|
||||
public ADXL345_I2C(int moduleNumber, DataFormat_Range range) {
|
||||
DigitalModule module = DigitalModule.getInstance(moduleNumber);
|
||||
m_i2c = module.getI2C(kAddress);
|
||||
|
||||
// Turn on the measurements
|
||||
m_i2c.write(kPowerCtlRegister, kPowerCtl_Measure);
|
||||
// Specify the data format to read
|
||||
m_i2c.write(kDataFormatRegister, kDataFormat_FullRes | range.value);
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_ADXL345, tInstances.kADXL345_I2C, moduleNumber-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the acceleration of one axis in Gs.
|
||||
*
|
||||
* @param axis The axis to read from.
|
||||
* @return Acceleration of the ADXL345 in Gs.
|
||||
*/
|
||||
public double getAcceleration(Axes axis) {
|
||||
byte[] rawAccel = new byte[2];
|
||||
m_i2c.read(kDataRegister + axis.value, rawAccel.length, rawAccel);
|
||||
|
||||
// Sensor is little endian... swap bytes
|
||||
return accelFromBytes(rawAccel[0], rawAccel[1]);
|
||||
}
|
||||
|
||||
private double accelFromBytes(byte first, byte second) {
|
||||
short tempLow = (short) (first & 0xff);
|
||||
short tempHigh = (short) ((second << 8) & 0xff00);
|
||||
return (tempLow | tempHigh) * kGsPerLSB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the acceleration of all axes in Gs.
|
||||
*
|
||||
* @return Acceleration measured on all axes of the ADXL345 in Gs.
|
||||
*/
|
||||
public AllAxes getAccelerations() {
|
||||
AllAxes data = new AllAxes();
|
||||
byte[] rawData = new byte[6];
|
||||
m_i2c.read(kDataRegister, rawData.length, rawData);
|
||||
|
||||
// Sensor is little endian... swap bytes
|
||||
data.XAxis = accelFromBytes(rawData[0], rawData[1]);
|
||||
data.YAxis = accelFromBytes(rawData[2], rawData[3]);
|
||||
data.ZAxis = accelFromBytes(rawData[4], rawData[5]);
|
||||
return data;
|
||||
}
|
||||
|
||||
// TODO: Support LiveWindow
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.ISensor;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
|
||||
/**
|
||||
* Handle operation of the accelerometer.
|
||||
* The accelerometer reads acceleration directly 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 Accelerometer extends SensorBase implements PIDSource, ISensor, LiveWindowSendable {
|
||||
|
||||
private AnalogChannel m_analogChannel;
|
||||
private double m_voltsPerG = 1.0;
|
||||
private double m_zeroGVoltage = 2.5;
|
||||
private boolean m_allocatedChannel;
|
||||
|
||||
/**
|
||||
* Common initialization
|
||||
*/
|
||||
private void initAccelerometer() {
|
||||
UsageReporting.report(tResourceType.kResourceType_Accelerometer, m_analogChannel.getChannel(), m_analogChannel.getModuleNumber()-1);
|
||||
LiveWindow.addSensor("Accelerometer", m_analogChannel.getModuleNumber(), m_analogChannel.getChannel(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of an accelerometer.
|
||||
*
|
||||
* The accelerometer is assumed to be in the first analog module in the given analog channel. The
|
||||
* constructor allocates desired analog channel.
|
||||
* @param channel the port that the accelerometer is on on the default module
|
||||
*/
|
||||
public Accelerometer(final int channel) {
|
||||
m_allocatedChannel = true;
|
||||
m_analogChannel = new AnalogChannel(channel);
|
||||
initAccelerometer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new instance of accelerometer.
|
||||
*
|
||||
* Make a new instance of the accelerometer given a module and channel. The constructor allocates
|
||||
* the desired analog channel from the specified module
|
||||
* @param slot the slot that the module is in
|
||||
* @param channel the port that the Accelerometer is on on the module
|
||||
*/
|
||||
public Accelerometer(final int slot, final int channel) {
|
||||
m_allocatedChannel = true;
|
||||
m_analogChannel = new AnalogChannel(slot, channel);
|
||||
initAccelerometer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of Accelerometer from an existing AnalogChannel.
|
||||
* Make a new instance of accelerometer given an AnalogChannel. This is particularly
|
||||
* useful if the port is going to be read as an analog channel as well as through
|
||||
* the Accelerometer class.
|
||||
* @param channel an already initialized analog channel
|
||||
*/
|
||||
public Accelerometer(AnalogChannel channel) {
|
||||
m_allocatedChannel = false;
|
||||
if (channel == null)
|
||||
throw new NullPointerException("Analog Channel given was null");
|
||||
m_analogChannel = channel;
|
||||
initAccelerometer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the analog components used for the accelerometer.
|
||||
*/
|
||||
public void free() {
|
||||
if (m_analogChannel != null && m_allocatedChannel) {
|
||||
m_analogChannel.free();
|
||||
}
|
||||
m_analogChannel = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the acceleration in Gs.
|
||||
*
|
||||
* The acceleration is returned units of Gs.
|
||||
*
|
||||
* @return The current acceleration of the sensor in Gs.
|
||||
*/
|
||||
public double getAcceleration() {
|
||||
return (m_analogChannel.getAverageVoltage() - m_zeroGVoltage) / m_voltsPerG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the accelerometer sensitivity.
|
||||
*
|
||||
* This sets the sensitivity of the accelerometer used for calculating the acceleration.
|
||||
* The sensitivity varys by accelerometer model. There are constants defined for various models.
|
||||
*
|
||||
* @param sensitivity The sensitivity of accelerometer in Volts per G.
|
||||
*/
|
||||
public void setSensitivity(double sensitivity) {
|
||||
m_voltsPerG = sensitivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the voltage that corresponds to 0 G.
|
||||
*
|
||||
* The zero G voltage varys by accelerometer model. There are constants defined for various models.
|
||||
*
|
||||
* @param zero The zero G voltage.
|
||||
*/
|
||||
public void setZero(double zero) {
|
||||
m_zeroGVoltage = zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Acceleration for the PID Source parent.
|
||||
*
|
||||
* @return The current acceleration in Gs.
|
||||
*/
|
||||
public double pidGet() {
|
||||
return getAcceleration();
|
||||
}
|
||||
|
||||
public String getSmartDashboardType() {
|
||||
return "Accelerometer";
|
||||
}
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getAcceleration());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when entering the LiveWindow.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when exiting the LiveWindow.
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
* Structure for holding the values stored in an accumulator
|
||||
* @author brad
|
||||
*/
|
||||
public class AccumulatorResult {
|
||||
|
||||
/**
|
||||
* The total value accumulated
|
||||
*/
|
||||
public long value;
|
||||
/**
|
||||
* The number of sample vaule was accumulated over
|
||||
*/
|
||||
public long count;
|
||||
}
|
||||
@@ -1,497 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
import java.nio.LongBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
|
||||
/**
|
||||
* Analog channel class.
|
||||
*
|
||||
* Each analog channel is read from hardware as a 12-bit number representing
|
||||
* -10V to 10V.
|
||||
*
|
||||
* Connected to each analog channel is an averaging and oversampling engine.
|
||||
* This engine accumulates the specified ( by setAverageBits() and
|
||||
* setOversampleBits() ) number of samples before returning a new value. This is
|
||||
* not a sliding window average. The only difference between the oversampled
|
||||
* samples and the averaged samples is that the oversampled samples are simply
|
||||
* 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 AnalogChannel extends SensorBase implements PIDSource,
|
||||
LiveWindowSendable {
|
||||
|
||||
private static final int kAccumulatorSlot = 1;
|
||||
private static Resource channels = new Resource(kAnalogModules
|
||||
* kAnalogChannels);
|
||||
private Pointer m_port;
|
||||
private int m_moduleNumber, m_channel;
|
||||
private static final int[] kAccumulatorChannels = { 1, 2 };
|
||||
private long m_accumulatorOffset;
|
||||
|
||||
/**
|
||||
* Construct an analog channel on the default module.
|
||||
*
|
||||
* @param channel
|
||||
* The channel number to represent.
|
||||
*/
|
||||
public AnalogChannel(final int channel) {
|
||||
this(getDefaultAnalogModule(), channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an analog channel on a specified module.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The digital module to use (1 or 2).
|
||||
* @param channel
|
||||
* The channel number to represent.
|
||||
*/
|
||||
public AnalogChannel(final int moduleNumber, final int channel) {
|
||||
System.out.println("Module Number: " + moduleNumber + " Channel: "
|
||||
+ channel);
|
||||
System.out.println(Thread.currentThread().getStackTrace());
|
||||
m_channel = channel;
|
||||
m_moduleNumber = moduleNumber;
|
||||
if (HALLibrary.checkAnalogModule((byte) moduleNumber) == 0) {
|
||||
throw new AllocationException("Analog channel " + m_channel
|
||||
+ " on module " + m_moduleNumber
|
||||
+ " cannot be allocated. Module is not present.");
|
||||
}
|
||||
if (HALLibrary.checkAnalogChannel(channel) == 0) {
|
||||
throw new AllocationException("Analog channel " + m_channel
|
||||
+ " on module " + m_moduleNumber
|
||||
+ " cannot be allocated. Channel is not present.");
|
||||
}
|
||||
try {
|
||||
channels.allocate((moduleNumber - 1) * kAnalogChannels + m_channel
|
||||
- 1);
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException("Analog channel " + m_channel
|
||||
+ " on module " + m_moduleNumber + " is already allocated");
|
||||
}
|
||||
|
||||
Pointer port_pointer = HALLibrary.getPortWithModule(
|
||||
(byte) moduleNumber, (byte) channel);
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
// XXX: Uncomment when Analog has been fixed
|
||||
m_port = HALLibrary.initializeAnalogPort(port_pointer, status);
|
||||
HALUtil.checkStatus(status);
|
||||
|
||||
LiveWindow.addSensor("Analog", moduleNumber, channel, this);
|
||||
UsageReporting.report(tResourceType.kResourceType_AnalogChannel,
|
||||
channel, m_moduleNumber - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel destructor.
|
||||
*/
|
||||
public void free() {
|
||||
channels.free(((m_moduleNumber - 1) * kAnalogChannels + m_channel - 1));
|
||||
m_channel = 0;
|
||||
m_moduleNumber = 0;
|
||||
m_accumulatorOffset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the analog module that this channel is on.
|
||||
*
|
||||
* @return The AnalogModule that this channel is on.
|
||||
*/
|
||||
public AnalogModule getModule() {
|
||||
return AnalogModule.getInstance(m_moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a sample straight from this channel on the module. The sample is a
|
||||
* 12-bit value representing the -10V to 10V range of the A/D converter in
|
||||
* the module. The units are in A/D converter codes. Use GetVoltage() to get
|
||||
* the analog value in calibrated units.
|
||||
*
|
||||
* @return A sample straight from this channel on the module.
|
||||
*/
|
||||
public int getValue() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogValue(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a sample from the output of the oversample and average engine for
|
||||
* this channel. The sample is 12-bit + the value configured in
|
||||
* SetOversampleBits(). The value configured in setAverageBits() will cause
|
||||
* this value to be averaged 2**bits number of samples. This is not a
|
||||
* sliding window. The sample will not change until 2**(OversamplBits +
|
||||
* AverageBits) samples have been acquired from the module on this channel.
|
||||
* Use getAverageVoltage() to get the analog value in calibrated units.
|
||||
*
|
||||
* @return A sample from the oversample and average engine for this channel.
|
||||
*/
|
||||
public int getAverageValue() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogAverageValue(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a scaled sample straight from this channel on the module. The value
|
||||
* is scaled to units of Volts using the calibrated scaling data from
|
||||
* getLSBWeight() and getOffset().
|
||||
*
|
||||
* @return A scaled sample straight from this channel on the module.
|
||||
*/
|
||||
public double getVoltage() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
double value = Float.intBitsToFloat(HALLibrary.getAnalogVoltageIntHack(m_port, status));
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a scaled sample from the output of the oversample and average engine
|
||||
* for this channel. The value is scaled to units of Volts using the
|
||||
* calibrated scaling data from getLSBWeight() and getOffset(). Using
|
||||
* oversampling will cause this value to be higher resolution, but it will
|
||||
* update more slowly. Using averaging will cause this value to be more
|
||||
* stable, but it will update more slowly.
|
||||
*
|
||||
* @return A scaled sample from the output of the oversample and average
|
||||
* engine for this channel.
|
||||
*/
|
||||
public double getAverageVoltage() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
double value = Float.intBitsToFloat(HALLibrary.getAnalogAverageVoltageIntHack(m_port, status));
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the factory scaling least significant bit weight constant. The least
|
||||
* significant bit weight constant for the channel that was calibrated in
|
||||
* manufacturing and stored in an eeprom in the module.
|
||||
*
|
||||
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
|
||||
*
|
||||
* @return Least significant bit weight.
|
||||
*/
|
||||
public long getLSBWeight() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
long value = HALLibrary.getAnalogLSBWeight(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the factory scaling offset constant. The offset constant for the
|
||||
* channel that was calibrated in manufacturing and stored in an eeprom in
|
||||
* the module.
|
||||
*
|
||||
* Volts = ((LSB_Weight * 1e-9) * raw) - (Offset * 1e-9)
|
||||
*
|
||||
* @return Offset constant.
|
||||
*/
|
||||
public int getOffset() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogOffset(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channel number.
|
||||
*
|
||||
* @return The channel number.
|
||||
*/
|
||||
public int getChannel() {
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of the analog module this channel is on.
|
||||
*
|
||||
* @return The module number of the analog module this channel is on.
|
||||
*/
|
||||
public int getModuleNumber() {
|
||||
return m_moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of averaging bits. This sets the number of averaging bits.
|
||||
* The actual number of averaged samples is 2**bits. The averaging is done
|
||||
* automatically in the FPGA.
|
||||
*
|
||||
* @param bits
|
||||
* The number of averaging bits.
|
||||
*/
|
||||
public void setAverageBits(final int bits) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogAverageBits(m_port, bits, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of averaging bits. This gets the number of averaging bits
|
||||
* from the FPGA. The actual number of averaged samples is 2**bits. The
|
||||
* averaging is done automatically in the FPGA.
|
||||
*
|
||||
* @return The number of averaging bits.
|
||||
*/
|
||||
public int getAverageBits() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogAverageBits(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of oversample bits. This sets the number of oversample
|
||||
* bits. The actual number of oversampled values is 2**bits. The
|
||||
* oversampling is done automatically in the FPGA.
|
||||
*
|
||||
* @param bits
|
||||
* The number of oversample bits.
|
||||
*/
|
||||
public void setOversampleBits(final int bits) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogOversampleBits(m_port, bits, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of oversample bits. This gets the number of oversample
|
||||
* bits from the FPGA. The actual number of oversampled values is 2**bits.
|
||||
* The oversampling is done automatically in the FPGA.
|
||||
*
|
||||
* @return The number of oversample bits.
|
||||
*/
|
||||
public int getOversampleBits() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogOversampleBits(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the accumulator.
|
||||
*/
|
||||
public void initAccumulator() {
|
||||
if (!isAccumulatorChannel()) {
|
||||
throw new AllocationException(
|
||||
"Accumulators are only available on slot "
|
||||
+ kAccumulatorSlot + " on channels "
|
||||
+ kAccumulatorChannels[0] + ","
|
||||
+ kAccumulatorChannels[1]);
|
||||
}
|
||||
m_accumulatorOffset = 0;
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.initAccumulator(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an inital value for the accumulator.
|
||||
*
|
||||
* This will be added to all values returned to the user.
|
||||
*
|
||||
* @param initialValue
|
||||
* The value that the accumulator should start from when reset.
|
||||
*/
|
||||
public void setAccumulatorInitialValue(long initialValue) {
|
||||
m_accumulatorOffset = initialValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the accumulator to the initial value.
|
||||
*/
|
||||
public void resetAccumulator() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.resetAccumulator(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the center value of the accumulator.
|
||||
*
|
||||
* The center value is subtracted from each A/D value before it is added to
|
||||
* the accumulator. This is used for the center value of devices like gyros
|
||||
* and accelerometers to make integration work and to take the device offset
|
||||
* into account when integrating.
|
||||
*
|
||||
* This center value is based on the output of the oversampled and averaged
|
||||
* source from channel 1. Because of this, any non-zero oversample bits will
|
||||
* affect the size of the value for this field.
|
||||
*/
|
||||
public void setAccumulatorCenter(int center) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAccumulatorCenter(m_port, center, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the accumulator's deadband.
|
||||
*/
|
||||
public void setAccumulatorDeadband(int deadband) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAccumulatorDeadband(m_port, deadband, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the accumulated value.
|
||||
*
|
||||
* Read the value that has been accumulating on channel 1. The accumulator
|
||||
* is attached after the oversample and average engine.
|
||||
*
|
||||
* @return The 64-bit value accumulated since the last Reset().
|
||||
*/
|
||||
public long getAccumulatorValue() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
long value = HALLibrary.getAccumulatorValue(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value + m_accumulatorOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the number of accumulated values.
|
||||
*
|
||||
* Read the count of the accumulated values since the accumulator was last
|
||||
* Reset().
|
||||
*
|
||||
* @return The number of times samples from the channel were accumulated.
|
||||
*/
|
||||
public long getAccumulatorCount() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
long value = HALLibrary.getAccumulatorCount(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the accumulated value and the number of accumulated values
|
||||
* atomically.
|
||||
*
|
||||
* This function reads the value and count from the FPGA atomically. This
|
||||
* can be used for averaging.
|
||||
*
|
||||
* @param result
|
||||
* AccumulatorResult object to store the results in.
|
||||
*/
|
||||
public void getAccumulatorOutput(AccumulatorResult result) {
|
||||
if (result == null) {
|
||||
throw new IllegalArgumentException("Null parameter `result'");
|
||||
}
|
||||
if (!isAccumulatorChannel()) {
|
||||
throw new IllegalArgumentException("Channel " + m_channel
|
||||
+ " on module " + m_moduleNumber
|
||||
+ " is not an accumulator channel.");
|
||||
}
|
||||
LongBuffer value = LongBuffer.allocate(1);
|
||||
IntBuffer count = IntBuffer.allocate(1);
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.getAccumulatorOutput(m_port, value, count, status);
|
||||
result.value = value.get(0) + m_accumulatorOffset;
|
||||
result.count = count.get(0);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the channel attached to an accumulator.
|
||||
*
|
||||
* @return The analog channel is attached to an accumulator.
|
||||
*/
|
||||
public boolean isAccumulatorChannel() {
|
||||
if (m_moduleNumber != kAccumulatorSlot) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < kAccumulatorChannels.length; i++) {
|
||||
if (m_channel == kAccumulatorChannels[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setSampleRate(final double samplesPerSecond) {
|
||||
// TODO: This will change when variable size scan lists are implemented.
|
||||
// TODO: Need float comparison with epsilon.
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogSampleRate((float) samplesPerSecond, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the average value for usee with PIDController
|
||||
*
|
||||
* @return the average value
|
||||
*/
|
||||
public double pidGet() {
|
||||
return getAverageValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Analog Input";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getAverageVoltage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when entering the
|
||||
* LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Analog Channels don't have to do anything special when exiting the
|
||||
* LiveWindow. {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
}
|
||||
@@ -1,289 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tModuleType;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
|
||||
/**
|
||||
* Analog Module class.
|
||||
* Each module can independently sample its channels at a configurable rate.
|
||||
* There is a 64-bit hardware accumulator associated with channel 1 on each module.
|
||||
* The accumulator is attached to the output of the oversample and average engine so that the center
|
||||
* value can be specified in higher resolution resulting in less error.
|
||||
*/
|
||||
public class AnalogModule extends Module {
|
||||
|
||||
/**
|
||||
* The time base used by the module
|
||||
*/
|
||||
public static final int kTimebase = 40000000;
|
||||
/**
|
||||
* The default number of Oversample bits to use
|
||||
*/
|
||||
public static final int kDefaultOversampleBits = 0;
|
||||
/**
|
||||
* The default number of averaging bits to use
|
||||
*/
|
||||
public static final int kDefaultAverageBits = 7;
|
||||
/**
|
||||
* The default sample rate
|
||||
*/
|
||||
public static final double kDefaultSampleRate = 50000.0;
|
||||
private Pointer[] m_ports;
|
||||
|
||||
/**
|
||||
* Get an instance of an Analog Module.
|
||||
*
|
||||
* Singleton analog module creation where a module is allocated on the first use
|
||||
* and the same module is returned on subsequent uses.
|
||||
*
|
||||
* @param moduleNumber The index of the analog module to get (1 or 2).
|
||||
* @return The AnalogModule.
|
||||
*/
|
||||
public static synchronized AnalogModule getInstance(final int moduleNumber) {
|
||||
checkAnalogModule(moduleNumber);
|
||||
return (AnalogModule) getModule(tModuleType.kModuleType_Analog, moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of an analog module.
|
||||
*
|
||||
* Create an instance of the analog module object. Initialize all the parameters
|
||||
* to reasonable values on start.
|
||||
* Setting a global value on an analog module can be done only once unless subsequent
|
||||
* values are set the previously set value.
|
||||
* Analog modules are a singleton, so the constructor is never called outside of this class.
|
||||
*
|
||||
* @param moduleNumber The index of the analog module to create (1 or 2).
|
||||
*/
|
||||
protected AnalogModule(final int moduleNumber) {
|
||||
super(tModuleType.kModuleType_Analog, moduleNumber);
|
||||
|
||||
m_ports = new Pointer[8];
|
||||
for (int i = 0; i < SensorBase.kAnalogChannels; i++) {
|
||||
Pointer port_pointer = HALLibrary.getPortWithModule((byte) moduleNumber, (byte) (i+1));
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
// XXX: Uncomment when analogchannel has been fixed
|
||||
// m_ports[i] = HALLibrary.initializeAnalogPort(port_pointer, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sample rate on the module.
|
||||
*
|
||||
* This is a global setting for the module and effects all channels.
|
||||
*
|
||||
* @param samplesPerSecond
|
||||
* The number of samples per channel per second.
|
||||
*/
|
||||
public void setSampleRate(final double samplesPerSecond) {
|
||||
// TODO: This will change when variable size scan lists are implemented.
|
||||
// TODO: Need float comparison with epsilon.
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogSampleRateWithModule((byte) m_moduleNumber, (float) samplesPerSecond, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current sample rate on the module.
|
||||
*
|
||||
* This assumes one entry in the scan list. This is a global setting for the
|
||||
* module and effects all channels.
|
||||
*
|
||||
* @return Sample rate.
|
||||
*/
|
||||
public double getSampleRate() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
double value = HALLibrary.getAnalogSampleRateWithModule((byte) m_moduleNumber, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of averaging bits.
|
||||
*
|
||||
* This sets the number of averaging bits. The actual number of averaged
|
||||
* samples is 2**bits. The averaging is done automatically in the FPGA.
|
||||
*
|
||||
* @param channel
|
||||
* Analog channel to configure.
|
||||
* @param bits
|
||||
* Number of bits to average.
|
||||
*/
|
||||
public void setAverageBits(final int channel, final int bits) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogAverageBits(m_ports[channel], bits, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of averaging bits.
|
||||
*
|
||||
* This gets the number of averaging bits from the FPGA. The actual number
|
||||
* of averaged samples is 2**bits. The averaging is done automatically in
|
||||
* the FPGA.
|
||||
*
|
||||
* @param channel Channel to address.
|
||||
* @return Bits to average.
|
||||
*/
|
||||
public int getAverageBits(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogAverageBits(m_ports[channel], status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of oversample bits.
|
||||
*
|
||||
* This sets the number of oversample bits. The actual number of oversampled values is 2**bits.
|
||||
* Use oversampling to improve the resolution of your measurements at the expense of sampling rate.
|
||||
* The oversampling is done automatically in the FPGA.
|
||||
*
|
||||
* @param channel Analog channel to configure.
|
||||
* @param bits Number of bits to oversample.
|
||||
*/
|
||||
public void setOversampleBits(final int channel, final int bits) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogOversampleBits(m_ports[channel], bits, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of oversample bits.
|
||||
*
|
||||
* This gets the number of oversample bits from the FPGA. The actual number
|
||||
* of oversampled values is 2**bits. The oversampling is done automatically
|
||||
* in the FPGA.
|
||||
*
|
||||
* @param channel Channel to address.
|
||||
* @return Bits to oversample.
|
||||
*/
|
||||
public int getOversampleBits(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogOversampleBits(m_ports[channel], status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw analog value.
|
||||
*
|
||||
* Get the analog value as it is returned from the D/A converter.
|
||||
*
|
||||
* @param channel Channel number to read.
|
||||
* @return Raw value.
|
||||
*/
|
||||
public int getValue(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogValue(m_ports[channel], status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw averaged and oversampled value.
|
||||
*
|
||||
* @param channel Channel number to read.
|
||||
* @return The averaged and oversampled raw value.
|
||||
*/
|
||||
public int getAverageValue(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogAverageValue(m_ports[channel], status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a voltage to a raw value for a specified channel.
|
||||
*
|
||||
* This process depends on the calibration of each channel, so the channel
|
||||
* must be specified.
|
||||
*
|
||||
* @todo This assumes raw values. Oversampling not supported as is.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to convert for.
|
||||
* @param voltage
|
||||
* The voltage to convert.
|
||||
* @return The raw value for the channel.
|
||||
*/
|
||||
public int voltsToValue(final int channel, final double voltage) {
|
||||
// wpi_assert(voltage >= -10.0 && voltage <= 10.0);
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogVoltsToValue(m_ports[channel], (float) voltage, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the voltage.
|
||||
*
|
||||
* Return the voltage from the A/D converter.
|
||||
*
|
||||
* @param channel The channel to read.
|
||||
* @return The scaled voltage from the channel.
|
||||
*/
|
||||
public double getVoltage(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
double value = HALLibrary.getAnalogVoltage(m_ports[channel], status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the averaged voltage.
|
||||
*
|
||||
* Return the averaged voltage from the A/D converter.
|
||||
*
|
||||
* @param channel The channel to read.
|
||||
* @return The scaled averaged and oversampled voltage from the channel.
|
||||
*/
|
||||
public double getAverageVoltage(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
double value = HALLibrary.getAnalogAverageVoltage(m_ports[channel], status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LSB Weight portion of the calibration for a channel.
|
||||
*
|
||||
* @param channel The channel to get calibration data for.
|
||||
* @return LSB Weight calibration point.
|
||||
*/
|
||||
public long getLSBWeight(final int channel) {
|
||||
// TODO: add scaling to make this worth while.
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
long value = HALLibrary.getAnalogLSBWeight(m_ports[channel], status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Offset portion of the calibration for a channel.
|
||||
*
|
||||
* @param channel The channel to get calibration data for.
|
||||
* @return Offset calibration point.
|
||||
*/
|
||||
public int getOffset(final int channel) {
|
||||
// TODO: add scaling to make this worth while.
|
||||
// TODO: actually use this function.
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getAnalogOffset(m_ports[channel], status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.parsing.IInputOutput;
|
||||
import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
|
||||
/**
|
||||
* Class for creating and configuring Analog Triggers
|
||||
*
|
||||
* @author dtjones
|
||||
*/
|
||||
public class AnalogTrigger implements IInputOutput {
|
||||
|
||||
/**
|
||||
* Exceptions dealing with improper operation of the Analog trigger
|
||||
*/
|
||||
public class AnalogTriggerException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new exception with the given message
|
||||
*
|
||||
* @param message
|
||||
* the message to pass with the exception
|
||||
*/
|
||||
public AnalogTriggerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Where the analog trigger is attached
|
||||
*/
|
||||
protected Pointer m_port;
|
||||
protected int m_index;
|
||||
|
||||
/**
|
||||
* Initialize an analog trigger from a module number and channel. This is
|
||||
* the common code for the two constructors that use a module number and
|
||||
* channel.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the analog module to create this trigger on.
|
||||
* @param channel
|
||||
* the port to use for the analog trigger
|
||||
*/
|
||||
protected void initTrigger(final int moduleNumber, final int channel) {
|
||||
Pointer port_pointer = HALLibrary.getPortWithModule(
|
||||
(byte) moduleNumber, (byte) channel);
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
IntBuffer index = IntBuffer.allocate(1);
|
||||
// XXX: Uncomment when analog has been fixed
|
||||
// m_port = HALLibrary
|
||||
// .initializeAnalogTrigger(port_pointer, index, status);
|
||||
//HALUtil.checkStatus(status);
|
||||
//m_index = index.get(0);
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_AnalogTrigger,
|
||||
channel, moduleNumber-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for an analog trigger given a channel number. The default
|
||||
* module is used in this case.
|
||||
*
|
||||
* @param channel
|
||||
* the port to use for the analog trigger
|
||||
*/
|
||||
public AnalogTrigger(final int channel) {
|
||||
initTrigger(AnalogModule.getDefaultAnalogModule(), channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for an analog trigger given both the module number and
|
||||
* channel.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the analog module to create this trigger on.
|
||||
* @param channel
|
||||
* the port to use for the analog trigger
|
||||
*/
|
||||
public AnalogTrigger(final int moduleNumber, final int channel) {
|
||||
initTrigger(moduleNumber, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an analog trigger given an analog channel. This should be used
|
||||
* in the case of sharing an analog channel between the trigger and an
|
||||
* analog input object.
|
||||
*
|
||||
* @param channel
|
||||
* the AnalogChannel to use for the analog trigger
|
||||
*/
|
||||
public AnalogTrigger(AnalogChannel channel) {
|
||||
initTrigger(channel.getModuleNumber(), channel.getChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the resources used by this object
|
||||
*/
|
||||
public void free() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.cleanAnalogTrigger(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
m_port = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the upper and lower limits of the analog trigger. The limits are
|
||||
* given in ADC codes. If oversampling is used, the units must be scaled
|
||||
* appropriately.
|
||||
*
|
||||
* @param lower
|
||||
* the lower raw limit
|
||||
* @param upper
|
||||
* the upper raw limit
|
||||
*/
|
||||
public void setLimitsRaw(final int lower, final int upper) {
|
||||
if (lower > upper) {
|
||||
throw new BoundaryException("Lower bound is greater than upper");
|
||||
}
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogTriggerLimitsRaw(m_port, lower, upper, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the upper and lower limits of the analog trigger. The limits are
|
||||
* given as floating point voltage values.
|
||||
*
|
||||
* @param lower
|
||||
* the lower voltage limit
|
||||
* @param upper
|
||||
* the upper voltage limit
|
||||
*/
|
||||
public void setLimitsVoltage(double lower, double upper) {
|
||||
if (lower > upper) {
|
||||
throw new BoundaryException(
|
||||
"Lower bound is greater than upper bound");
|
||||
}
|
||||
// TODO: This depends on the averaged setting. Only raw values will work
|
||||
// as is.
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogTriggerLimitsVoltage(m_port, (float) lower,
|
||||
(float) upper, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the analog trigger to use the averaged vs. raw values. If the
|
||||
* value is true, then the averaged value is selected for the analog
|
||||
* trigger, otherwise the immediate value is used.
|
||||
*
|
||||
* @param useAveragedValue
|
||||
* true to use an averaged value, false otherwise
|
||||
*/
|
||||
public void setAveraged(boolean useAveragedValue) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogTriggerAveraged(m_port,
|
||||
(byte) (useAveragedValue ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the analog trigger to use a filtered value. The analog trigger
|
||||
* will operate with a 3 point average rejection filter. This is designed to
|
||||
* help with 360 degree pot applications for the period where the pot
|
||||
* crosses through zero.
|
||||
*
|
||||
* @param useFilteredValue
|
||||
* true to use a filterd value, false otherwise
|
||||
*/
|
||||
public void setFiltered(boolean useFilteredValue) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setAnalogTriggerFiltered(m_port,
|
||||
(byte) (useFilteredValue ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the analog trigger. This is the FPGA index of this
|
||||
* analog trigger instance.
|
||||
*
|
||||
* @return The index of the analog trigger.
|
||||
*/
|
||||
public int getIndex() {
|
||||
return m_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the InWindow output of the analog trigger. True if the analog
|
||||
* input is between the upper and lower limits.
|
||||
*
|
||||
* @return The InWindow output of the analog trigger.
|
||||
*/
|
||||
public boolean getInWindow() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
byte value = HALLibrary.getAnalogTriggerInWindow(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the TriggerState output of the analog trigger. True if above upper
|
||||
* limit. False if below lower limit. If in Hysteresis, maintain previous
|
||||
* state.
|
||||
*
|
||||
* @return The TriggerState output of the analog trigger.
|
||||
*/
|
||||
public boolean getTriggerState() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
byte value = HALLibrary.getAnalogTriggerTriggerState(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AnalogTriggerOutput object. Gets an output object that can be
|
||||
* used for routing. Caller is responsible for deleting the
|
||||
* AnalogTriggerOutput object.
|
||||
*
|
||||
* @param type
|
||||
* An enum of the type of output object to create.
|
||||
* @return A pointer to a new AnalogTriggerOutput object.
|
||||
*/
|
||||
AnalogTriggerOutput createOutput(int type) {
|
||||
return new AnalogTriggerOutput(this, type);
|
||||
}
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.parsing.IInputOutput;
|
||||
|
||||
/**
|
||||
* Class to represent a specific output from an analog trigger. This class is
|
||||
* used to get the current output value and also as a DigitalSource to provide
|
||||
* routing of an output to digital subsystems on the FPGA such as Counter,
|
||||
* Encoder, and Interrupt.
|
||||
*
|
||||
* The TriggerState output indicates the primary output value of the trigger. If
|
||||
* the analog signal is less than the lower limit, the output is false. If the
|
||||
* analog value is greater than the upper limit, then the output is true. If the
|
||||
* analog value is in between, then the trigger output state maintains its most
|
||||
* recent value.
|
||||
*
|
||||
* The InWindow output indicates whether or not the analog signal is inside the
|
||||
* range defined by the limits.
|
||||
*
|
||||
* The RisingPulse and FallingPulse outputs detect an instantaneous transition
|
||||
* from above the upper limit to below the lower limit, and vise versa. These
|
||||
* pulses represent a rollover condition of a sensor and can be routed to an up
|
||||
* / down couter or to interrupts. Because the outputs generate a pulse, they
|
||||
* cannot be read directly. To help ensure that a rollover condition is not
|
||||
* missed, there is an average rejection filter available that operates on the
|
||||
* upper 8 bits of a 12 bit number and selects the nearest outlyer of 3 samples.
|
||||
* This will reject a sample that is (due to averaging or sampling) errantly
|
||||
* between the two limits. This filter will fail if more than one sample in a
|
||||
* row is errantly in between the two limits. You may see this problem if
|
||||
* attempting to use this feature with a mechanical rollover sensor, such as a
|
||||
* 360 degree no-stop potentiometer without signal conditioning, because the
|
||||
* rollover transition is not sharp / clean enough. Using the averaging engine
|
||||
* may help with this, but rotational speeds of the sensor will then be limited.
|
||||
*/
|
||||
public class AnalogTriggerOutput extends DigitalSource implements IInputOutput {
|
||||
|
||||
/**
|
||||
* Exceptions dealing with improper operation of the Analog trigger output
|
||||
*/
|
||||
public class AnalogTriggerOutputException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new exception with the given message
|
||||
*
|
||||
* @param message
|
||||
* the message to pass with the exception
|
||||
*/
|
||||
public AnalogTriggerOutputException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private AnalogTrigger m_trigger;
|
||||
private int m_outputType; // define in HALLibrary.AnalogTriggerType
|
||||
|
||||
/**
|
||||
* Create an object that represents one of the four outputs from an analog
|
||||
* trigger.
|
||||
*
|
||||
* Because this class derives from DigitalSource, it can be passed into
|
||||
* routing functions for Counter, Encoder, etc.
|
||||
*
|
||||
* @param trigger
|
||||
* The trigger for which this is an output.
|
||||
* @param outputType
|
||||
* An enum that specifies the output on the trigger to represent.
|
||||
*/
|
||||
public AnalogTriggerOutput(AnalogTrigger trigger, final int outputType) {
|
||||
if (trigger == null)
|
||||
throw new NullPointerException("Analog Trigger given was null");
|
||||
m_trigger = trigger;
|
||||
m_outputType = outputType;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_AnalogTriggerOutput,
|
||||
trigger.getIndex(), outputType);
|
||||
}
|
||||
|
||||
public void free() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the state of the analog trigger output.
|
||||
*
|
||||
* @return The state of the analog trigger output.
|
||||
*/
|
||||
public boolean get() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
byte value = HALLibrary.getAnalogTriggerOutput(m_trigger.m_port,
|
||||
m_outputType, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
public int getChannelForRouting() {
|
||||
return (m_trigger.m_index << 2) + m_outputType;
|
||||
}
|
||||
|
||||
public int getModuleForRouting() {
|
||||
return m_trigger.m_index >> 2;
|
||||
}
|
||||
|
||||
public boolean getAnalogTriggerForRouting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request interrupts asynchronously on this digital input.
|
||||
*
|
||||
* @param handler
|
||||
* the interrupt service routine
|
||||
* @param param
|
||||
* a parameter for the ISR
|
||||
*/
|
||||
// public void requestInterrupts(/*tInterruptHandler*/Object handler, Object
|
||||
// param) {
|
||||
// TODO: add interrupt support
|
||||
// TODO: throw exception
|
||||
// }
|
||||
|
||||
/**
|
||||
* Request interrupts synchronously on this digital input.
|
||||
*/
|
||||
// public void requestInterrupts() {
|
||||
// TODO: throw exception
|
||||
// }
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,229 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.IDevice;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
* Compressor object.
|
||||
* The Compressor object is designed to handle the operation of the compressor, pressure sensor and
|
||||
* relay for a FIRST robot pneumatics system. The Compressor object starts a task which runs in the
|
||||
* backround and periodically polls the pressure sensor and operates the relay that controls the
|
||||
* compressor.
|
||||
*/
|
||||
public class Compressor extends SensorBase implements IDevice, LiveWindowSendable {
|
||||
|
||||
private DigitalInput m_pressureSwitch;
|
||||
private Relay m_relay;
|
||||
private boolean m_enabled;
|
||||
private Thread m_task;
|
||||
private boolean m_run = true;
|
||||
|
||||
/**
|
||||
* Internal thread.
|
||||
*
|
||||
* Task which checks the compressor pressure switch and operates the relay as necessary
|
||||
* depending on the pressure.
|
||||
*
|
||||
* Do not call this function directly.
|
||||
*/
|
||||
private class CompressorThread extends Thread {
|
||||
|
||||
Compressor m_compressor;
|
||||
|
||||
CompressorThread(Compressor comp) {
|
||||
m_compressor = comp;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (m_run) {
|
||||
if (m_compressor.enabled()) {
|
||||
m_compressor.setRelayValue(!m_compressor.getPressureSwitchValue() ? Relay.Value.kOn : Relay.Value.kOff);
|
||||
} else {
|
||||
m_compressor.setRelayValue(Relay.Value.kOff);
|
||||
}
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Compressor object.
|
||||
* This method is the common initialization code for all the constructors for the Compressor
|
||||
* object. It takes the relay channel and pressure switch channel and spawns a task that polls the
|
||||
* compressor and sensor.
|
||||
*
|
||||
* You MUST start the compressor by calling the start() method.
|
||||
*/
|
||||
private void initCompressor(final int pressureSwitchSlot,
|
||||
final int pressureSwitchChannel,
|
||||
final int compresssorRelaySlot,
|
||||
final int compressorRelayChannel) {
|
||||
|
||||
m_enabled = false;
|
||||
m_pressureSwitch = new DigitalInput(pressureSwitchSlot, pressureSwitchChannel);
|
||||
m_relay = new Relay(compresssorRelaySlot, compressorRelayChannel, Relay.Direction.kForward);
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Compressor, 0);
|
||||
|
||||
m_task = new CompressorThread(this);
|
||||
m_task.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compressor constructor.
|
||||
* Given a fully specified relay channel and pressure switch channel, initialize the Compressor object.
|
||||
*
|
||||
* You MUST start the compressor by calling the start() method.
|
||||
*
|
||||
* @param pressureSwitchSlot The module that the pressure switch is attached to.
|
||||
* @param pressureSwitchChannel The GPIO channel that the pressure switch is attached to.
|
||||
* @param compresssorRelaySlot The module that the compressor relay is attached to.
|
||||
* @param compressorRelayChannel The relay channel that the compressor relay is attached to.
|
||||
*/
|
||||
public Compressor(final int pressureSwitchSlot,
|
||||
final int pressureSwitchChannel,
|
||||
final int compresssorRelaySlot,
|
||||
final int compressorRelayChannel) {
|
||||
initCompressor(pressureSwitchSlot,
|
||||
pressureSwitchChannel,
|
||||
compresssorRelaySlot,
|
||||
compressorRelayChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compressor constructor.
|
||||
* Given a relay channel and pressure switch channel (both in the default digital module), initialize
|
||||
* the Compressor object.
|
||||
*
|
||||
* You MUST start the compressor by calling the start() method.
|
||||
*
|
||||
* @param pressureSwitchChannel The GPIO channel that the pressure switch is attached to.
|
||||
* @param compressorRelayChannel The relay channel that the compressor relay is attached to.
|
||||
*/
|
||||
public Compressor(final int pressureSwitchChannel, final int compressorRelayChannel) {
|
||||
initCompressor(getDefaultDigitalModule(),
|
||||
pressureSwitchChannel,
|
||||
getDefaultDigitalModule(),
|
||||
compressorRelayChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the Compressor object.
|
||||
* Delete the allocated resources for the compressor and kill the compressor task that is polling
|
||||
* the pressure switch.
|
||||
*/
|
||||
public void free() {
|
||||
m_run = false;
|
||||
try {
|
||||
m_task.join();
|
||||
} catch (InterruptedException e) {}
|
||||
m_pressureSwitch.free();
|
||||
m_relay.free();
|
||||
m_pressureSwitch = null;
|
||||
m_relay = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operate the relay for the compressor.
|
||||
* Change the value of the relay output that is connected to the compressor motor.
|
||||
* This is only intended to be called by the internal polling thread.
|
||||
* @param relayValue the value to set the relay to
|
||||
*/
|
||||
public void setRelayValue(Relay.Value relayValue) {
|
||||
m_relay.set(relayValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pressure switch value.
|
||||
* Read the pressure switch digital input.
|
||||
*
|
||||
* @return The current state of the pressure switch.
|
||||
*/
|
||||
public boolean getPressureSwitchValue() {
|
||||
return m_pressureSwitch.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the compressor.
|
||||
* This method will allow the polling loop to actually operate the compressor. The
|
||||
* is stopped by default and won't operate until starting it.
|
||||
*/
|
||||
public void start() {
|
||||
m_enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the compressor.
|
||||
* This method will stop the compressor from turning on.
|
||||
*/
|
||||
public void stop() {
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the state of the enabled flag.
|
||||
* Return the state of the enabled flag for the compressor and pressure switch
|
||||
* combination.
|
||||
*
|
||||
* @return The state of the compressor thread's enable flag.
|
||||
*/
|
||||
public boolean enabled() {
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Compressor";
|
||||
}
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putBoolean("Enabled", m_enabled);
|
||||
m_table.putBoolean("Pressure Switch", getPressureSwitchValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
/**
|
||||
* An interface for controllers. Controllers run control loops, the most command
|
||||
* are PID controllers and there variants, but this includes anything that is
|
||||
* controlling an actuator in a separate thread.
|
||||
*
|
||||
* @author alex
|
||||
*/
|
||||
interface Controller {
|
||||
/**
|
||||
* Allows the control loop to run.
|
||||
*/
|
||||
public void enable();
|
||||
|
||||
/**
|
||||
* Stops the control loop from running until explicitly re-enabled by calling
|
||||
* {@link enable()}.
|
||||
*/
|
||||
public void disable();
|
||||
}
|
||||
@@ -1,731 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
|
||||
/**
|
||||
* Class for counting the number of ticks on a digital input channel. This is a
|
||||
* general purpose class for counting repetitive events. It can return the
|
||||
* number of counts, the period of the most recent cycle, and detect when the
|
||||
* signal being counted has stopped by supplying a maximum cycle time.
|
||||
*/
|
||||
public class Counter extends SensorBase implements CounterBase,
|
||||
LiveWindowSendable, PIDSource {
|
||||
|
||||
/**
|
||||
* Mode determines how and what the counter counts
|
||||
*/
|
||||
public static class Mode {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kTwoPulse_val = 0;
|
||||
static final int kSemiperiod_val = 1;
|
||||
static final int kPulseLength_val = 2;
|
||||
static final int kExternalDirection_val = 3;
|
||||
/**
|
||||
* mode: two pulse
|
||||
*/
|
||||
public static final Mode kTwoPulse = new Mode(kTwoPulse_val);
|
||||
/**
|
||||
* mode: semi period
|
||||
*/
|
||||
public static final Mode kSemiperiod = new Mode(kSemiperiod_val);
|
||||
/**
|
||||
* mode: pulse length
|
||||
*/
|
||||
public static final Mode kPulseLength = new Mode(kPulseLength_val);
|
||||
/**
|
||||
* mode: external direction
|
||||
*/
|
||||
public static final Mode kExternalDirection = new Mode(
|
||||
kExternalDirection_val);
|
||||
|
||||
private Mode(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private DigitalSource m_upSource; // /< What makes the counter count up.
|
||||
private DigitalSource m_downSource; // /< What makes the counter count down.
|
||||
private boolean m_allocatedUpSource;
|
||||
private boolean m_allocatedDownSource;
|
||||
private Pointer m_counter; // /< The FPGA counter object.
|
||||
private int m_index; // /< The index of this counter.
|
||||
private PIDSourceParameter m_pidSource;
|
||||
private double m_distancePerPulse; // distance of travel for each tick
|
||||
|
||||
private void initCounter(final Mode mode) {
|
||||
IntBuffer status = IntBuffer.allocate(1), index = IntBuffer.allocate(1);
|
||||
m_counter = HALLibrary.initializeCounter(mode.value, index, status);
|
||||
HALUtil.checkStatus(status);
|
||||
m_index = index.get();
|
||||
|
||||
m_allocatedUpSource = false;
|
||||
m_allocatedDownSource = false;
|
||||
m_upSource = null;
|
||||
m_downSource = null;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Counter, m_index,
|
||||
mode.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a counter where no sources are selected. Then they
|
||||
* all must be selected by calling functions to specify the upsource and the
|
||||
* downsource independently.
|
||||
*/
|
||||
public Counter() {
|
||||
initCounter(Mode.kTwoPulse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a counter from a Digital Input. This is used if an
|
||||
* existing digital input is to be shared by multiple other objects such as
|
||||
* encoders.
|
||||
*
|
||||
* @param source
|
||||
* the digital source to count
|
||||
*/
|
||||
public Counter(DigitalSource source) {
|
||||
if (source == null)
|
||||
throw new NullPointerException("Source given was null");
|
||||
initCounter(Mode.kTwoPulse);
|
||||
setUpSource(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Counter object. Create an up-Counter instance
|
||||
* given a channel. The default digital module is assumed.
|
||||
*
|
||||
* @param channel
|
||||
* the digital input channel to count
|
||||
*/
|
||||
public Counter(int channel) {
|
||||
initCounter(Mode.kTwoPulse);
|
||||
setUpSource(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Counter object. Create an instance of an
|
||||
* up-Counter given a digital module and a channel.
|
||||
*
|
||||
* @param slot
|
||||
* The cRIO chassis slot for the digital module used
|
||||
* @param channel
|
||||
* The channel in the digital module
|
||||
*/
|
||||
public Counter(int slot, int channel) {
|
||||
initCounter(Mode.kTwoPulse);
|
||||
setUpSource(slot, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Counter object. Create an instance of a simple
|
||||
* up-Counter given an analog trigger. Use the trigger state output from the
|
||||
* analog trigger.
|
||||
*
|
||||
* @param encodingType
|
||||
* which edges to count
|
||||
* @param upSource
|
||||
* first source to count
|
||||
* @param downSource
|
||||
* second source for direction
|
||||
* @param inverted
|
||||
* true to invert the count
|
||||
*/
|
||||
public Counter(EncodingType encodingType, DigitalSource upSource,
|
||||
DigitalSource downSource, boolean inverted) {
|
||||
initCounter(Mode.kExternalDirection);
|
||||
if (encodingType != EncodingType.k1X
|
||||
&& encodingType != EncodingType.k2X) {
|
||||
throw new RuntimeException(
|
||||
"Counters only support 1X and 2X quadreature decoding!");
|
||||
}
|
||||
if (upSource == null)
|
||||
throw new NullPointerException("Up Source given was null");
|
||||
setUpSource(upSource);
|
||||
if (downSource == null)
|
||||
throw new NullPointerException("Down Source given was null");
|
||||
setDownSource(downSource);
|
||||
|
||||
if (encodingType == null)
|
||||
throw new NullPointerException("Encoding type given was null");
|
||||
|
||||
if (encodingType == EncodingType.k1X) {
|
||||
setUpSourceEdge(true, false);
|
||||
} else {
|
||||
setUpSourceEdge(true, true);
|
||||
}
|
||||
|
||||
setDownSourceEdge(inverted, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Counter object. Create an instance of a simple
|
||||
* up-Counter given an analog trigger. Use the trigger state output from the
|
||||
* analog trigger.
|
||||
*
|
||||
* @param trigger
|
||||
* the analog trigger to count
|
||||
*/
|
||||
public Counter(AnalogTrigger trigger) {
|
||||
initCounter(Mode.kTwoPulse);
|
||||
setUpSource(trigger.createOutput(HALLibrary.AnalogTriggerType.kState));
|
||||
}
|
||||
|
||||
public void free() {
|
||||
setUpdateWhenEmpty(true);
|
||||
|
||||
clearUpSource();
|
||||
clearDownSource();
|
||||
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.freeCounter(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
|
||||
m_upSource = null;
|
||||
m_downSource = null;
|
||||
m_counter = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the up source for the counter as digital input channel and slot.
|
||||
*
|
||||
* @param slot
|
||||
* the location of the digital module to use
|
||||
* @param channel
|
||||
* the digital port to count
|
||||
*/
|
||||
public void setUpSource(int slot, int channel) {
|
||||
setUpSource(new DigitalInput(slot, channel));
|
||||
m_allocatedUpSource = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the upsource for the counter as a digital input channel. The slot
|
||||
* will be the default digital module slot.
|
||||
*
|
||||
* @param channel
|
||||
* the digital port to count
|
||||
*/
|
||||
public void setUpSource(int channel) {
|
||||
setUpSource(new DigitalInput(channel));
|
||||
m_allocatedUpSource = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the source object that causes the counter to count up. Set the up
|
||||
* counting DigitalSource.
|
||||
*
|
||||
* @param source
|
||||
* the digital source to count
|
||||
*/
|
||||
public void setUpSource(DigitalSource source) {
|
||||
if (m_upSource != null && m_allocatedUpSource) {
|
||||
m_upSource.free();
|
||||
m_allocatedUpSource = false;
|
||||
}
|
||||
m_upSource = source;
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterUpSourceWithModule(m_counter,
|
||||
(byte) source.getModuleForRouting(),
|
||||
source.getChannelForRouting(),
|
||||
(byte) (source.getAnalogTriggerForRouting() ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the up counting source to be an analog trigger.
|
||||
*
|
||||
* @param analogTrigger
|
||||
* The analog trigger object that is used for the Up Source
|
||||
* @param triggerType
|
||||
* The analog trigger output that will trigger the counter.
|
||||
*/
|
||||
public void setUpSource(AnalogTrigger analogTrigger, int triggerType) {
|
||||
analogTrigger.createOutput(triggerType);
|
||||
m_allocatedUpSource = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the edge sensitivity on an up counting source. Set the up source to
|
||||
* either detect rising edges or falling edges.
|
||||
*
|
||||
* @param risingEdge
|
||||
* true to count rising edge
|
||||
* @param fallingEdge
|
||||
* true to count falling edge
|
||||
*/
|
||||
public void setUpSourceEdge(boolean risingEdge, boolean fallingEdge) {
|
||||
if (m_upSource == null)
|
||||
throw new RuntimeException(
|
||||
"Up Source must be set before setting the edge!");
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterUpSourceEdge(m_counter,
|
||||
(byte) (risingEdge ? 1 : 0), (byte) (fallingEdge ? 1 : 0),
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the up counting source to the counter.
|
||||
*/
|
||||
public void clearUpSource() {
|
||||
if (m_upSource != null && m_allocatedUpSource) {
|
||||
m_upSource.free();
|
||||
m_allocatedUpSource = false;
|
||||
}
|
||||
m_upSource = null;
|
||||
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.clearCounterUpSource(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the down counting source to be a digital input channel. The slot will
|
||||
* be set to the default digital module slot.
|
||||
*
|
||||
* @param channel
|
||||
* the digital port to count
|
||||
*/
|
||||
public void setDownSource(int channel) {
|
||||
setDownSource(new DigitalInput(channel));
|
||||
m_allocatedDownSource = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the down counting source to be a digital input slot and channel.
|
||||
*
|
||||
* @param slot
|
||||
* the location of the digital module to use
|
||||
* @param channel
|
||||
* the digital port to count
|
||||
*/
|
||||
public void setDownSource(int slot, int channel) {
|
||||
setDownSource(new DigitalInput(slot, channel));
|
||||
m_allocatedDownSource = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the source object that causes the counter to count down. Set the down
|
||||
* counting DigitalSource.
|
||||
*
|
||||
* @param source
|
||||
* the digital source to count
|
||||
*/
|
||||
public void setDownSource(DigitalSource source) {
|
||||
if (m_downSource != null && m_allocatedDownSource) {
|
||||
m_downSource.free();
|
||||
m_allocatedDownSource = false;
|
||||
}
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterDownSourceWithModule(m_counter,
|
||||
(byte) source.getModuleForRouting(),
|
||||
source.getChannelForRouting(),
|
||||
(byte) (source.getAnalogTriggerForRouting() ? 1 : 0), status);
|
||||
if (status.get() == HALLibrary.PARAMETER_OUT_OF_RANGE) {
|
||||
throw new IllegalArgumentException(
|
||||
"Counter only supports DownSource in TwoPulse and ExternalDirection modes.");
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
m_downSource = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the down counting source to be an analog trigger.
|
||||
*
|
||||
* @param analogTrigger
|
||||
* The analog trigger object that is used for the Down Source
|
||||
* @param triggerType
|
||||
* The analog trigger output that will trigger the counter.
|
||||
*/
|
||||
public void setDownSource(AnalogTrigger analogTrigger, int triggerType) {
|
||||
setDownSource(analogTrigger.createOutput(triggerType));
|
||||
m_allocatedDownSource = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the edge sensitivity on a down counting source. Set the down source
|
||||
* to either detect rising edges or falling edges.
|
||||
*
|
||||
* @param risingEdge
|
||||
* true to count the rising edge
|
||||
* @param fallingEdge
|
||||
* true to count the falling edge
|
||||
*/
|
||||
public void setDownSourceEdge(boolean risingEdge, boolean fallingEdge) {
|
||||
if (m_downSource == null)
|
||||
throw new RuntimeException(
|
||||
" Down Source must be set before setting the edge!");
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterDownSourceEdge(m_counter, (byte) (risingEdge ? 1
|
||||
: 0), (byte) (fallingEdge ? 0 : 1), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the down counting source to the counter.
|
||||
*/
|
||||
public void clearDownSource() {
|
||||
if (m_downSource != null && m_allocatedDownSource) {
|
||||
m_downSource.free();
|
||||
m_allocatedDownSource = false;
|
||||
}
|
||||
m_downSource = null;
|
||||
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.clearCounterDownSource(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set standard up / down counting mode on this counter. Up and down counts
|
||||
* are sourced independently from two inputs.
|
||||
*/
|
||||
public void setUpDownCounterMode() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterUpDownMode(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set external direction mode on this counter. Counts are sourced on the Up
|
||||
* counter input. The Down counter input represents the direction to count.
|
||||
*/
|
||||
public void setExternalDirectionMode() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterExternalDirectionMode(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Semi-period mode on this counter. Counts up on both rising and
|
||||
* falling edges.
|
||||
*
|
||||
* @param highSemiPeriod
|
||||
* true to count up on both rising and falling
|
||||
*/
|
||||
public void setSemiPeriodMode(boolean highSemiPeriod) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterSemiPeriodMode(m_counter,
|
||||
(byte) (highSemiPeriod ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the counter to count in up or down based on the length of the
|
||||
* input pulse. This mode is most useful for direction sensitive gear tooth
|
||||
* sensors.
|
||||
*
|
||||
* @param threshold
|
||||
* The pulse length beyond which the counter counts the opposite
|
||||
* direction. Units are seconds.
|
||||
*/
|
||||
public void setPulseLengthMode(double threshold) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterPulseLengthMode(m_counter, (float) threshold,
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the Counter counting. This enables the counter and it starts
|
||||
* accumulating counts from the associated input channel. The counter value
|
||||
* is not reset on starting, and still has the previous value.
|
||||
*/
|
||||
public void start() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.startCounter(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the current counter value. Read the value at this instant. It may
|
||||
* still be running, so it reflects the current value. Next time it is read,
|
||||
* it might have a different value.
|
||||
*/
|
||||
public int get() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getCounter(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the current scaled counter value. Read the value at this instant,
|
||||
* scaled by the distance per pulse (defaults to 1).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public double getDistance() {
|
||||
return get() * m_distancePerPulse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the Counter to zero. Set the counter value to zero. This doesn't
|
||||
* effect the running state of the counter, just sets the current value to
|
||||
* zero.
|
||||
*/
|
||||
public void reset() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.resetCounter(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the Counter. Stops the counting but doesn't effect the current
|
||||
* value.
|
||||
*/
|
||||
public void stop() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.stopCounter(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum period where the device is still considered "moving".
|
||||
* Sets the maximum period where the device is considered moving. This value
|
||||
* is used to determine the "stopped" state of the counter using the
|
||||
* GetStopped method.
|
||||
*
|
||||
* @param maxPeriod
|
||||
* The maximum period where the counted device is considered
|
||||
* moving in seconds.
|
||||
*/
|
||||
public void setMaxPeriod(double maxPeriod) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterMaxPeriod(m_counter, maxPeriod, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select whether you want to continue updating the event timer output when
|
||||
* there are no samples captured. The output of the event timer has a buffer
|
||||
* of periods that are averaged and posted to a register on the FPGA. When
|
||||
* the timer detects that the event source has stopped (based on the
|
||||
* MaxPeriod) the buffer of samples to be averaged is emptied. If you enable
|
||||
* the update when empty, you will be notified of the stopped source and the
|
||||
* event time will report 0 samples. If you disable update when empty, the
|
||||
* most recent average will remain on the output until a new sample is
|
||||
* acquired. You will never see 0 samples output (except when there have
|
||||
* been no events since an FPGA reset) and you will likely not see the
|
||||
* stopped bit become true (since it is updated at the end of an average and
|
||||
* there are no samples to average).
|
||||
*
|
||||
* @param enabled
|
||||
* true to continue updating
|
||||
*/
|
||||
public void setUpdateWhenEmpty(boolean enabled) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterUpdateWhenEmpty(m_counter,
|
||||
(byte) (enabled ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the clock is stopped. Determine if the clocked input is
|
||||
* stopped based on the MaxPeriod value set using the SetMaxPeriod method.
|
||||
* If the clock exceeds the MaxPeriod, then the device (and counter) are
|
||||
* assumed to be stopped and it returns true.
|
||||
*
|
||||
* @return Returns true if the most recent counter period exceeds the
|
||||
* MaxPeriod value set by SetMaxPeriod.
|
||||
*/
|
||||
public boolean getStopped() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getCounterStopped(m_counter, status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The last direction the counter value changed.
|
||||
*
|
||||
* @return The last direction the counter value changed.
|
||||
*/
|
||||
public boolean getDirection() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getCounterDirection(m_counter, status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Counter to return reversed sensing on the direction. This allows
|
||||
* counters to change the direction they are counting in the case of 1X and
|
||||
* 2X quadrature encoding only. Any other counter mode isn't supported.
|
||||
*
|
||||
* @param reverseDirection
|
||||
* true if the value counted should be negated.
|
||||
*/
|
||||
public void setReverseDirection(boolean reverseDirection) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterReverseDirection(m_counter,
|
||||
(byte) (reverseDirection ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Period of the most recent count. Returns the time interval of the
|
||||
* most recent count. This can be used for velocity calculations to
|
||||
* determine shaft speed.
|
||||
*
|
||||
* @returns The period of the last two pulses in units of seconds.
|
||||
*/
|
||||
public double getPeriod() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
double value = HALLibrary.getCounterPeriod(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current rate of the Counter. Read the current rate of the counter
|
||||
* accounting for the distance per pulse value. The default value for
|
||||
* distance per pulse (1) yields units of pulses per second.
|
||||
*
|
||||
* @return The rate in units/sec
|
||||
*/
|
||||
public double getRate() {
|
||||
return m_distancePerPulse / getPeriod();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Samples to Average which specifies the number of samples of the
|
||||
* timer to average when calculating the period. Perform averaging to
|
||||
* account for mechanical imperfections or as oversampling to increase
|
||||
* resolution.
|
||||
*
|
||||
* @param samplesToAverage
|
||||
* The number of samples to average from 1 to 127.
|
||||
*/
|
||||
public void setSamplesToAverage(int samplesToAverage) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setCounterSamplesToAverage(m_counter, samplesToAverage,
|
||||
status);
|
||||
if (status.get() == HALLibrary.PARAMETER_OUT_OF_RANGE) {
|
||||
throw new BoundaryException(BoundaryException.getMessage(
|
||||
samplesToAverage, 1, 127));
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Samples to Average which specifies the number of samples of the
|
||||
* timer to average when calculating the period. Perform averaging to
|
||||
* account for mechanical imperfections or as oversampling to increase
|
||||
* resolution.
|
||||
*
|
||||
* @return SamplesToAverage The number of samples being averaged (from 1 to
|
||||
* 127)
|
||||
*/
|
||||
public int getSamplesToAverage() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getCounterSamplesToAverage(m_counter, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the distance per pulse for this counter. This sets the multiplier
|
||||
* used to determine the distance driven based on the count value from the
|
||||
* encoder. Set this value based on the Pulses per Revolution and factor in
|
||||
* any gearing reductions. This distance can be in any units you like,
|
||||
* linear or angular.
|
||||
*
|
||||
* @param distancePerPulse
|
||||
* The scale factor that will be used to convert pulses to useful
|
||||
* units.
|
||||
*/
|
||||
public void setDistancePerPulse(double distancePerPulse) {
|
||||
m_distancePerPulse = distancePerPulse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set which parameter of the encoder you are using as a process control
|
||||
* variable. The counter class supports the rate and distance parameters.
|
||||
*
|
||||
* @param pidSource
|
||||
* An enum to select the parameter.
|
||||
*/
|
||||
public void setPIDSourceParameter(PIDSourceParameter pidSource) {
|
||||
BoundaryException.assertWithinBounds(pidSource.value, 0, 1);
|
||||
m_pidSource = pidSource;
|
||||
}
|
||||
|
||||
public double pidGet() {
|
||||
switch (m_pidSource.value) {
|
||||
case PIDSourceParameter.kDistance_val:
|
||||
return getDistance();
|
||||
case PIDSourceParameter.kRate_val:
|
||||
return getRate();
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Counter";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
* Interface for counting the number of ticks on a digital input channel.
|
||||
* Encoders, Gear tooth sensors, and counters should all subclass this so it can be used to
|
||||
* build more advanced classes for control and driving.
|
||||
*/
|
||||
public interface CounterBase {
|
||||
|
||||
/**
|
||||
* The number of edges for the counterbase to increment or decrement on
|
||||
*/
|
||||
public static class EncodingType {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int k1X_val = 0;
|
||||
static final int k2X_val = 1;
|
||||
static final int k4X_val = 2;
|
||||
/**
|
||||
* Count only the rising edge
|
||||
*/
|
||||
public static final EncodingType k1X = new EncodingType(k1X_val);
|
||||
/**
|
||||
* Count both the rising and falling edge
|
||||
*/
|
||||
public static final EncodingType k2X = new EncodingType(k2X_val);
|
||||
/**
|
||||
* Count rising and falling on both channels
|
||||
*/
|
||||
public static final EncodingType k4X = new EncodingType(k4X_val);
|
||||
|
||||
private EncodingType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the counter
|
||||
*/
|
||||
public void start();
|
||||
|
||||
/**
|
||||
* Get the count
|
||||
* @return the count
|
||||
*/
|
||||
int get();
|
||||
|
||||
/**
|
||||
* Reset the count to zero
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Stop counting
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Get the time between the last two edges counted
|
||||
* @return the time beteween the last two ticks in seconds
|
||||
*/
|
||||
double getPeriod();
|
||||
|
||||
/**
|
||||
* Set the maximum time between edges to be considered stalled
|
||||
* @param maxPeriod the maximum period in seconds
|
||||
*/
|
||||
void setMaxPeriod(double maxPeriod);
|
||||
|
||||
/**
|
||||
* Determine if the counter is not moving
|
||||
* @return true if the counter has not changed for the max period
|
||||
*/
|
||||
boolean getStopped();
|
||||
|
||||
/**
|
||||
* Determine which direction the counter is going
|
||||
* @return true for one direction, false for the other
|
||||
*/
|
||||
boolean getDirection();
|
||||
}
|
||||
@@ -1,372 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.util.Stack;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.parsing.IInputOutput;
|
||||
|
||||
/**
|
||||
* Pack data into the "user data" field that gets sent to the dashboard laptop
|
||||
* via the driver station.
|
||||
*/
|
||||
public class Dashboard implements IDashboard, IInputOutput {
|
||||
|
||||
protected class MemAccess {
|
||||
|
||||
byte[] m_bytes;
|
||||
|
||||
protected MemAccess(byte[] bytes) {
|
||||
m_bytes = bytes;
|
||||
}
|
||||
|
||||
protected MemAccess(int length) {
|
||||
m_bytes = new byte[length];
|
||||
}
|
||||
|
||||
public void setByte(int index, byte value) {
|
||||
m_bytes[index] = value;
|
||||
}
|
||||
|
||||
public void setShort(int index, short value) {
|
||||
setByte(index++, (byte) (value >>> 8));
|
||||
setByte(index++, (byte) (value));
|
||||
}
|
||||
|
||||
public void setInt(int index, int value) {
|
||||
setByte(index++, (byte) (value >>> 24));
|
||||
setByte(index++, (byte) (value >>> 16));
|
||||
setByte(index++, (byte) (value >>> 8));
|
||||
setByte(index++, (byte) (value));
|
||||
}
|
||||
|
||||
public void setFloat(int index, float value) {
|
||||
setInt(index, Float.floatToIntBits(value));
|
||||
}
|
||||
|
||||
public void setDouble(int index, double value) {
|
||||
setInt(index, (int) (Double.doubleToLongBits(value) >>> 32));
|
||||
setInt(index + 4, (int) Double.doubleToLongBits(value));
|
||||
}
|
||||
|
||||
public void setString(int index, String value) {
|
||||
setBytes(index, value.getBytes(), 0, value.length());
|
||||
}
|
||||
|
||||
public void setBytes(int index, byte[] value, int offset, int number) {
|
||||
for (int i = 0; i < number; i++) {
|
||||
m_bytes[i + index] = value[i + offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
private static final String kArray = "Array";
|
||||
private static final String kCluster = "Cluster";
|
||||
private static final Integer kByte = new Integer(0);
|
||||
private static final Integer kShort = new Integer(1);
|
||||
private static final Integer kInt = new Integer(2);
|
||||
private static final Integer kFloat = new Integer(3);
|
||||
private static final Integer kDouble = new Integer(4);
|
||||
private static final Integer kString = new Integer(5);
|
||||
private static final Integer kOther = new Integer(6);
|
||||
private static final Integer kBoolean = new Integer(7);
|
||||
private static final int kMaxDashboardDataSize = DriverStation.USER_STATUS_DATA_SIZE -
|
||||
4 * 3 - 1; // 13 bytes needed for 3 size parameters and the sequence number
|
||||
private static boolean m_reported = false;
|
||||
protected MemAccess m_userStatus;
|
||||
protected int m_userStatusSize = 0;
|
||||
private MemAccess m_localBuffer;
|
||||
private int m_packPtr;
|
||||
private Stack m_expectedArrayElementType = new Stack();
|
||||
private Stack m_arrayElementCount = new Stack();
|
||||
private Stack m_arraySizePtr = new Stack();
|
||||
private Stack m_complexTypeStack = new Stack();
|
||||
private final Object m_statusDataSemaphore;
|
||||
|
||||
/**
|
||||
* Dashboard constructor.
|
||||
*
|
||||
* This is only called once when the DriverStation constructor is called.
|
||||
* @param statusDataSemaphore the object to synchronize on
|
||||
*/
|
||||
protected Dashboard(Object statusDataSemaphore) {
|
||||
m_userStatus = new MemAccess(kMaxDashboardDataSize);
|
||||
m_localBuffer = new MemAccess(kMaxDashboardDataSize);
|
||||
m_packPtr = 0;
|
||||
m_statusDataSemaphore = statusDataSemaphore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a signed 8-bit int into the dashboard data structure.
|
||||
* @param value Data to be packed into the structure.
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addByte(byte value) {
|
||||
if (!validateAdd(1)) {
|
||||
return false;
|
||||
}
|
||||
m_localBuffer.setByte(m_packPtr, value);
|
||||
m_packPtr += 1;
|
||||
return addedElement(kByte);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a signed 16-bit int into the dashboard data structure.
|
||||
* @param value Data to be packed into the structure.
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addShort(short value) {
|
||||
if (!validateAdd(2)) {
|
||||
return false;
|
||||
}
|
||||
m_localBuffer.setShort(m_packPtr, value);
|
||||
m_packPtr += 2;
|
||||
return addedElement(kShort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a signed 32-bit int into the dashboard data structure.
|
||||
* @param value Data to be packed into the structure.
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addInt(int value) {
|
||||
if (!validateAdd(4)) {
|
||||
return false;
|
||||
}
|
||||
m_localBuffer.setInt(m_packPtr, value);
|
||||
m_packPtr += 4;
|
||||
return addedElement(kInt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a 32-bit floating point number into the dashboard data structure.
|
||||
* @param value Data to be packed into the structure.
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addFloat(float value) {
|
||||
if (!validateAdd(4)) {
|
||||
return false;
|
||||
}
|
||||
m_localBuffer.setFloat(m_packPtr, value);
|
||||
m_packPtr += 4;
|
||||
return addedElement(kFloat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a 64-bit floating point number into the dashboard data structure.
|
||||
* @param value Data to be packed into the structure.
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addDouble(double value) {
|
||||
if (!validateAdd(8)) {
|
||||
return false;
|
||||
}
|
||||
m_localBuffer.setDouble(m_packPtr, value);
|
||||
m_packPtr += 8;
|
||||
return addedElement(kDouble);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a boolean into the dashboard data structure.
|
||||
* @param value Data to be packed into the structure.
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addBoolean(boolean value) {
|
||||
if (!validateAdd(1)) {
|
||||
return false;
|
||||
}
|
||||
m_localBuffer.setByte(m_packPtr, (byte) (value ? 1 : 0));
|
||||
m_packPtr += 1;
|
||||
return addedElement(kBoolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a NULL-terminated string of 8-bit characters into the dashboard data structure.
|
||||
* @param value Data to be packed into the structure.
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addString(String value) {
|
||||
if (!validateAdd(value.length() + 4)) {
|
||||
return false;
|
||||
}
|
||||
m_localBuffer.setInt(m_packPtr, value.length());
|
||||
m_packPtr += 4;
|
||||
m_localBuffer.setString(m_packPtr, value);
|
||||
m_packPtr += value.length();
|
||||
return addedElement(kString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack a string of 8-bit characters of specified length into the dashboard data structure.
|
||||
* @param value Data to be packed into the structure.
|
||||
* @param length The number of bytes in the string to pack.
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addString(String value, int length) {
|
||||
return addString(value.substring(0, length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an array in the packed dashboard data structure.
|
||||
*
|
||||
* After calling addArray(), call the appropriate Add method for each element of the array.
|
||||
* Make sure you call the same add each time. An array must contain elements of the same type.
|
||||
* You can use clusters inside of arrays to make each element of the array contain a structure of values.
|
||||
* You can also nest arrays inside of other arrays.
|
||||
* Every call to addArray() must have a matching call to finalizeArray().
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addArray() {
|
||||
if (!validateAdd(4)) {
|
||||
return false;
|
||||
}
|
||||
m_complexTypeStack.push(kArray);
|
||||
m_arrayElementCount.push(new Integer(0));
|
||||
m_arraySizePtr.push(new Integer(m_packPtr));
|
||||
m_packPtr += 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate the end of an array packed into the dashboard data structure.
|
||||
*
|
||||
* After packing data into the array, call finalizeArray().
|
||||
* Every call to addArray() must have a matching call to finalizeArray().
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean finalizeArray() {
|
||||
if (m_complexTypeStack.peek() != kArray) {
|
||||
System.err.println("Attempted to finalize an array in the middle of a cluster or without starting the array");
|
||||
return false;
|
||||
}
|
||||
m_complexTypeStack.pop();
|
||||
m_localBuffer.setInt(((Integer) m_arraySizePtr.pop()).intValue(),
|
||||
((Integer) m_arrayElementCount.peek()).intValue());
|
||||
|
||||
|
||||
if (((Integer) m_arrayElementCount.peek()).intValue() != 0) {
|
||||
m_expectedArrayElementType.pop();
|
||||
}
|
||||
m_arrayElementCount.pop();
|
||||
return addedElement(kOther);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a cluster in the packed dashboard data structure.
|
||||
*
|
||||
* After calling addCluster(), call the appropriate Add method for each element of the cluster.
|
||||
* You can use clusters inside of arrays to make each element of the array contain a structure of values.
|
||||
* Every call to addCluster() must have a matching call to finalizeCluster().
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean addCluster() {
|
||||
m_complexTypeStack.push(kCluster);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate the end of a cluster packed into the dashboard data structure.
|
||||
*
|
||||
* After packing data into the cluster, call finalizeCluster().
|
||||
* Every call to addCluster() must have a matching call to finalizeCluster
|
||||
* @return True on success
|
||||
*/
|
||||
public boolean finalizeCluster() {
|
||||
if (m_complexTypeStack.peek() != kCluster) {
|
||||
System.err.println("Attempted to close a cluster on an open array or without starting the cluster");
|
||||
return false;
|
||||
}
|
||||
m_complexTypeStack.pop();
|
||||
return addedElement(kOther);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the packing is complete and commit the buffer to the DriverStation.
|
||||
*
|
||||
* The packing of the dashboard packet is complete.
|
||||
* If you are not using the packed dashboard data, you can call commit() to commit the Printf() buffer and the error string buffer.
|
||||
* In effect, you are packing an empty structure.
|
||||
* Prepares a packet to go to the dashboard...
|
||||
* Pack the sequence number, Printf() buffer, the errors messages (not implemented yet), and packed dashboard data buffer.
|
||||
* @return The total size of the data packed into the userData field of the status packet.
|
||||
*/
|
||||
public synchronized int commit() {
|
||||
|
||||
if (!m_complexTypeStack.empty()) {
|
||||
System.err.println("didn't finish complex type");
|
||||
m_packPtr = 0;
|
||||
System.err.println("didn't finish complex type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!m_reported) {
|
||||
UsageReporting.report(tResourceType.kResourceType_Dashboard, 0);
|
||||
m_reported = true;
|
||||
}
|
||||
|
||||
synchronized (m_statusDataSemaphore) {
|
||||
// Sequence number
|
||||
DriverStation.getInstance().incrementUpdateNumber();
|
||||
|
||||
// Packed Dashboard Data
|
||||
m_userStatusSize = m_packPtr;
|
||||
m_userStatus.setBytes(0, m_localBuffer.m_bytes, 0, m_userStatusSize);
|
||||
m_packPtr = 0;
|
||||
|
||||
}
|
||||
return m_userStatusSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the data being packed will fit in the buffer.
|
||||
*/
|
||||
private boolean validateAdd(int size) {
|
||||
if (m_packPtr + size > kMaxDashboardDataSize) {
|
||||
m_packPtr = 0;
|
||||
System.err.println("Dashboard data is too long to send");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for consistent types when adding elements to an array and keep track of the number of elements in the array.
|
||||
*/
|
||||
private boolean addedElement(Integer type) {
|
||||
if (isArrayRoot()) {
|
||||
if (((Integer) m_arrayElementCount.peek()).intValue() == 0) {
|
||||
m_expectedArrayElementType.push(type);
|
||||
} else {
|
||||
if (type != m_expectedArrayElementType.peek()) {
|
||||
System.err.println("Attempted to add multiple datatypes to the same array");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_arrayElementCount.push(new Integer(((Integer) m_arrayElementCount.pop()).intValue() + 1));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the top of the type stack an array?
|
||||
*/
|
||||
private boolean isArrayRoot() {
|
||||
return !m_complexTypeStack.empty() && m_complexTypeStack.peek() == kArray;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return m_userStatus.m_bytes;
|
||||
}
|
||||
|
||||
public int getBytesLength() {
|
||||
return m_userStatusSize;
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
}
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary.InterruptHandlerFunction;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.IInputOutput;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
|
||||
/**
|
||||
* Class to read a digital input. This class will read digital inputs and return
|
||||
* the current value on the channel. Other devices such as encoders, gear tooth
|
||||
* sensors, etc. that are implemented 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 IInputOutput,
|
||||
LiveWindowSendable {
|
||||
|
||||
/**
|
||||
* Create an instance of a Digital Input class. Creates a digital input
|
||||
* given a channel and uses the default module.
|
||||
*
|
||||
* @param channel
|
||||
* the port for the digital input
|
||||
*/
|
||||
public DigitalInput(int channel) {
|
||||
this(getDefaultDigitalModule(), channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Digital Input class. Creates a digital input
|
||||
* given an channel and module.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the digital module to use for this input
|
||||
* @param channel
|
||||
* the port for the digital input
|
||||
*/
|
||||
public DigitalInput(int moduleNumber, int channel) {
|
||||
initDigitalPort(moduleNumber, channel, true);
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_DigitalInput,
|
||||
channel, moduleNumber - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value from a digital input channel. Retrieve the value of a
|
||||
* single digital input channel from the FPGA.
|
||||
*
|
||||
* @return the stats of the digital input
|
||||
*/
|
||||
public boolean get() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getDIO(m_port, status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channel of the digital input
|
||||
*
|
||||
* @return The GPIO channel number that this object represents.
|
||||
*/
|
||||
public int getChannel() {
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
public boolean getAnalogTriggerForRouting() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request interrupts asynchronously on this digital input.
|
||||
*
|
||||
* @param handler
|
||||
* The address of the interrupt handler function of type
|
||||
* tInterruptHandler that will be called whenever there is an
|
||||
* interrupt on the digitial input port. Request interrupts in
|
||||
* synchronus mode where the user program interrupt handler will
|
||||
* be called when an interrupt occurs. The default is interrupt
|
||||
* on rising edges only.
|
||||
*/
|
||||
public void requestInterrupts(InterruptHandlerFunction handler) {
|
||||
// TODO: add interrupt support
|
||||
|
||||
try {
|
||||
m_interruptIndex = interrupts.allocate();
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException(
|
||||
"No interrupts are left to be allocated");
|
||||
}
|
||||
|
||||
allocateInterrupts(false);
|
||||
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.requestInterrupts(m_interrupt, (byte) getModuleForRouting(),
|
||||
getChannelForRouting(),
|
||||
(byte) (getAnalogTriggerForRouting() ? 1 : 0), status);
|
||||
setUpSourceEdge(true, false);
|
||||
HALLibrary.attachInterruptHandler(m_interrupt, handler, null, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request interrupts synchronously on this digital input. Request
|
||||
* interrupts in synchronus mode where the user program will have to
|
||||
* explicitly wait for the interrupt to occur. The default is interrupt on
|
||||
* rising edges only.
|
||||
*/
|
||||
public void requestInterrupts() {
|
||||
try {
|
||||
m_interruptIndex = interrupts.allocate();
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException(
|
||||
"No interrupts are left to be allocated");
|
||||
}
|
||||
|
||||
allocateInterrupts(true);
|
||||
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.requestInterrupts(m_interrupt, (byte) getModuleForRouting(),
|
||||
getChannelForRouting(),
|
||||
(byte) (getAnalogTriggerForRouting() ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
setUpSourceEdge(true, false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set which edge to trigger interrupts on
|
||||
*
|
||||
* @param risingEdge
|
||||
* true to interrupt on rising edge
|
||||
* @param fallingEdge
|
||||
* true to interrupt on falling edge
|
||||
*/
|
||||
public void setUpSourceEdge(boolean risingEdge, boolean fallingEdge) {
|
||||
if (m_interrupt != null) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setInterruptUpSourceEdge(m_interrupt,
|
||||
(byte) (risingEdge ? 1 : 0), (byte) (fallingEdge ? 1 : 0),
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"You must call RequestInterrupts before setUpSourceEdge");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Digital Input";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putBoolean("Value", get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
}
|
||||
@@ -1,521 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tModuleType;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
|
||||
/**
|
||||
* Class representing a digital module
|
||||
*
|
||||
* @author dtjones
|
||||
*/
|
||||
public class DigitalModule extends Module {
|
||||
|
||||
/**
|
||||
* Expected loop timing
|
||||
*/
|
||||
public static final int kExpectedLoopTiming = 260;
|
||||
private int m_module;
|
||||
private Pointer[] m_digital_ports;
|
||||
private Pointer[] m_relay_ports;
|
||||
private Pointer[] m_pwm_ports;
|
||||
|
||||
/**
|
||||
* Get an instance of an Digital Module. Singleton digital module creation
|
||||
* where a module is allocated on the first use and the same module is
|
||||
* returned on subsequent uses.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the digital module to access.
|
||||
* @return The digital module of the specified number.
|
||||
*/
|
||||
public static synchronized DigitalModule getInstance(final int moduleNumber) {
|
||||
SensorBase.checkDigitalModule(moduleNumber);
|
||||
return (DigitalModule) getModule(tModuleType.kModuleType_Digital,
|
||||
moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Convert a channel to its fpga reference
|
||||
*
|
||||
* @param channel
|
||||
* the channel to convert
|
||||
* @return the converted channel
|
||||
*/
|
||||
public static int remapDigitalChannel(final int channel) {
|
||||
System.err.println("This is going away for compatability reasons. Don't use it.");
|
||||
return SensorBase.kDigitalChannels - channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Convert a channel from it's fpga reference
|
||||
*
|
||||
* @param channel
|
||||
* the channel to convert
|
||||
* @return the converted channel
|
||||
*/
|
||||
public static int unmapDigitalChannel(final int channel) {
|
||||
System.err.println("This is going away for compatability reasons. Don't use it.");
|
||||
return SensorBase.kDigitalChannels - channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new digital module
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the digital module to use (1 or 2)
|
||||
*/
|
||||
protected DigitalModule(final int moduleNumber) {
|
||||
super(tModuleType.kModuleType_Digital, moduleNumber);
|
||||
m_module = moduleNumber;
|
||||
|
||||
m_digital_ports = new Pointer[SensorBase.kDigitalChannels];
|
||||
for (int i = 0; i < SensorBase.kDigitalChannels; i++) {
|
||||
Pointer port_pointer = HALLibrary.getPortWithModule(
|
||||
(byte) moduleNumber, (byte) (i + 1));
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
m_digital_ports[i] = HALLibrary.initializeDigitalPort(port_pointer,
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
m_relay_ports = new Pointer[SensorBase.kRelayChannels];
|
||||
for (int i = 0; i < SensorBase.kRelayChannels; i++) {
|
||||
Pointer port_pointer = HALLibrary.getPortWithModule(
|
||||
(byte) moduleNumber, (byte) (i + 1));
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
m_relay_ports[i] = HALLibrary.initializeDigitalPort(port_pointer,
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
m_pwm_ports = new Pointer[SensorBase.kPwmChannels];
|
||||
for (int i = 0; i < SensorBase.kPwmChannels; i++) {
|
||||
Pointer port_pointer = HALLibrary.getPortWithModule(
|
||||
(byte) moduleNumber, (byte) (i + 1));
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
m_pwm_ports[i] = HALLibrary.initializeDigitalPort(port_pointer,
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a PWM channel to the desired value. The values range from 0 to 255
|
||||
* and the period is controlled by the PWM Period and MinHigh registers.
|
||||
*
|
||||
* @param channel
|
||||
* The PWM channel to set.
|
||||
* @param value
|
||||
* The PWM value to set.
|
||||
*/
|
||||
public void setPWM(final int channel, final int value) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setPWM(m_pwm_ports[channel - 1], (short) value, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from a PWM channel. The values range from 0 to 255.
|
||||
*
|
||||
* @param channel
|
||||
* The PWM channel to read from.
|
||||
* @return The raw PWM value.
|
||||
*/
|
||||
public int getPWM(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = (int) HALLibrary.getPWM(m_pwm_ports[channel - 1], status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set how how often the PWM signal is squelched, thus scaling the period.
|
||||
*
|
||||
* @param channel
|
||||
* The PWM channel to configure.
|
||||
* @param squelchMask
|
||||
* The 2-bit mask of outputs to squelch.
|
||||
*/
|
||||
public void setPWMPeriodScale(final int channel, final int squelchMask) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setPWMPeriodScale(m_pwm_ports[channel - 1], squelchMask,
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of a relay. Set the state of a relay output to be forward.
|
||||
* Relays have two outputs and each is independently set to 0v or 12v.
|
||||
*
|
||||
* @param channel
|
||||
* The Relay channel.
|
||||
* @param on
|
||||
* Indicates whether to set the relay to the On state.
|
||||
*/
|
||||
public void setRelayForward(final int channel, final boolean on) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setRelayForward(m_relay_ports[channel - 1], (byte) (on ? 1
|
||||
: 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state of a relay. Set the state of a relay output to be reverse.
|
||||
* Relays have two outputs and each is independently set to 0v or 12v.
|
||||
*
|
||||
* @param channel
|
||||
* The Relay channel.
|
||||
* @param on
|
||||
* Indicates whether to set the relay to the On state.
|
||||
*/
|
||||
public void setRelayReverse(final int channel, final boolean on) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setRelayReverse(m_relay_ports[channel - 1], (byte) (on ? 1
|
||||
: 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state of the forward relay channel
|
||||
*
|
||||
* @param channel
|
||||
* the channel of the relay to get
|
||||
* @return The current state of the relay.
|
||||
*/
|
||||
public boolean getRelayForward(int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getRelayForward(m_relay_ports[channel - 1],
|
||||
status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state of all of the forward relay channels on this
|
||||
* module.
|
||||
*
|
||||
* @return The state of all forward relay channels as a byte.
|
||||
*/
|
||||
public byte getRelayForward() {
|
||||
byte value = 0;
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
for (int i = 0; i < SensorBase.kRelayChannels; i++) {
|
||||
value |= HALLibrary.getRelayForward(m_relay_ports[i], status) << i;
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state of the reverse relay channel
|
||||
*
|
||||
* @param channel
|
||||
* the channel of the relay to get
|
||||
* @return The current statte of the relay
|
||||
*/
|
||||
public boolean getRelayReverse(int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getRelayReverse(m_relay_ports[channel - 1],
|
||||
status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current state of all of the reverse relay channels on this
|
||||
* module.
|
||||
*
|
||||
* @return The state of all forward relay channels as a byte.
|
||||
*/
|
||||
public byte getRelayReverse() {
|
||||
byte value = 0;
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
for (int i = 0; i < SensorBase.kRelayChannels; i++) {
|
||||
value |= HALLibrary.getRelayReverse(m_relay_ports[i], status) << i;
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate Digital I/O channels. Allocate channels so that they are not
|
||||
* accidently reused. Also the direction is set at the time of the
|
||||
* allocation.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to allocate.
|
||||
* @param input
|
||||
* Indicates whether the I/O pin is an input (true) or an output
|
||||
* (false).
|
||||
* @return True if the I/O pin was allocated, false otherwise.
|
||||
*/
|
||||
public boolean allocateDIO(final int channel, final boolean input) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean allocated = HALLibrary.allocateDIO(
|
||||
m_digital_ports[channel - 1], (byte) (input ? 1 : 0), status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return allocated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resource associated with a digital I/O channel.
|
||||
*
|
||||
* @param channel
|
||||
* The channel whose resources should be freed.
|
||||
*/
|
||||
public void freeDIO(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.freeDIO(m_digital_ports[channel - 1], status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a digital I/O bit to the FPGA. Set a single value on a digital I/O
|
||||
* channel.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to set.
|
||||
* @param value
|
||||
* The value to set.
|
||||
*/
|
||||
public void setDIO(final int channel, final boolean value) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setDIO(m_digital_ports[channel - 1], (byte) (value ? 1 : 0),
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a digital I/O bit from the FPGA. Get a single value from a digital
|
||||
* I/O channel.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to read
|
||||
* @return The value of the selected channel
|
||||
*/
|
||||
public boolean getDIO(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getDIO(m_digital_ports[channel - 1], status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the state of all the Digital I/O lines from the FPGA These are not
|
||||
* remapped to logical order. They are still in hardware order.
|
||||
*
|
||||
* @return The state of all the Digital IO lines in hardware order
|
||||
*/
|
||||
public short getAllDIO() {
|
||||
byte value = 0;
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
for (int i = 0; i < SensorBase.kDigitalChannels; i++) {
|
||||
value |= HALLibrary.getDIO(m_digital_ports[i], status) << i;
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the direction of a digital I/O line
|
||||
*
|
||||
* @param channel
|
||||
* The channel of the DIO to get the direction of.
|
||||
* @return True if the digital channel is configured as an output, false if
|
||||
* it is an input
|
||||
*/
|
||||
public boolean getDIODirection(int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getDIODirection(
|
||||
m_digital_ports[channel - 1], status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the direction of all the Digital I/O lines from the FPGA A 1 bit
|
||||
* means output and a 0 bit means input. These are not remapped to logical
|
||||
* order. They are still in hardware order.
|
||||
*
|
||||
* @return The direction of all the Digital IO lines in hardware order
|
||||
*/
|
||||
public short getDIODirection() {
|
||||
byte value = 0;
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
for (int i = 0; i < SensorBase.kDigitalChannels; i++) {
|
||||
value |= HALLibrary.getDIODirection(m_digital_ports[i], status) << i;
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a single pulse. Write a pulse to the specified digital output
|
||||
* channel. There can only be a single pulse going at any time.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to pulse.
|
||||
* @param pulseLength
|
||||
* The length of the pulse.
|
||||
*/
|
||||
public void pulse(final int channel, final float pulseLength) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.pulse(m_digital_ports[channel - 1], pulseLength, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Generate a single pulse. Write a pulse to the specified
|
||||
* digital output channel. There can only be a single pulse
|
||||
* going at any time.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to pulse.
|
||||
* @param pulseLength
|
||||
* The length of the pulse.
|
||||
*/
|
||||
public void pulse(final int channel, final int pulseLength) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
float convertedPulse = (float) (pulseLength / 1.0e9 * (HALLibrary
|
||||
.getLoopTiming(status) * 25));
|
||||
System.err
|
||||
.println("You should use the float version of pulse for portability. This is deprecated");
|
||||
HALLibrary.pulse(m_digital_ports[channel - 1], convertedPulse, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a DIO line to see if it is currently generating a pulse.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to check.
|
||||
* @return True if the channel is pulsing, false otherwise.
|
||||
*/
|
||||
public boolean isPulsing(final int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.isPulsing(m_digital_ports[channel - 1],
|
||||
status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if any DIO line is currently generating a pulse.
|
||||
*
|
||||
* @return True if any channel is pulsing, false otherwise.
|
||||
*/
|
||||
public boolean isPulsing() {
|
||||
boolean value;
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
value = HALLibrary.isAnyPulsingWithModule((byte) m_module, status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a DO PWM Generator. Allocate PWM generators so that they are not
|
||||
* accidently reused.
|
||||
*/
|
||||
public int allocateDO_PWM() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.allocatePWMWithModule((byte) m_module, status)
|
||||
.getInt(0); // XXX: Hacky, needs heavy testing
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resource associated with a DO PWM generator.
|
||||
*/
|
||||
public void freeDO_PWM(int pwmGenerator) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
Pointer pointer = new IntByReference(pwmGenerator).getPointer();
|
||||
HALLibrary.freePWMWithModule((byte) m_module, pointer, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the frequency of the DO PWM generator.
|
||||
*
|
||||
* The valid range is from 0.6 Hz to 19 kHz. The frequency resolution is
|
||||
* logarithmic.
|
||||
*
|
||||
* @param rate
|
||||
* The frequency to output all digital output PWM signals on this
|
||||
* module.
|
||||
*/
|
||||
public void setDO_PWMRate(double rate) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setPWMRateWithModuleIntHack((byte) m_module, Float.floatToIntBits((float) rate), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure which DO channel the PWM siganl is output on
|
||||
*
|
||||
* @param pwmGenerator
|
||||
* The generator index reserved by allocateDO_PWM()
|
||||
* @param channel
|
||||
* The Digital Output channel to output on
|
||||
*/
|
||||
public void setDO_PWMOutputChannel(int pwmGenerator, int channel) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
Pointer pointer = new IntByReference(pwmGenerator).getPointer();
|
||||
HALLibrary.setPWMOutputChannelWithModule((byte) m_module, pointer,
|
||||
channel, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the duty-cycle of the PWM generator
|
||||
*
|
||||
* @param pwmGenerator
|
||||
* The generator index reserved by allocateDO_PWM()
|
||||
* @param dutyCycle
|
||||
* The percent duty cycle to output [0..1].
|
||||
*/
|
||||
public void setDO_PWMDutyCycle(int pwmGenerator, double dutyCycle) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
Pointer pointer = new IntByReference(pwmGenerator).getPointer();
|
||||
HALLibrary.setPWMDutyCycleWithModuleIntHack((byte) m_module, pointer,
|
||||
Float.floatToIntBits((float) dutyCycle), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an I2C object for this digital module
|
||||
*
|
||||
* @param address
|
||||
* The device address.
|
||||
* @return The associated I2C object.
|
||||
*/
|
||||
public I2C getI2C(final int address) {
|
||||
return new I2C(this, address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the loop timing of the Digital Module
|
||||
*
|
||||
* @return The number of clock ticks per DIO loop
|
||||
*/
|
||||
public int getLoopTiming() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getLoopTiming(status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.IInputOutput;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
|
||||
/**
|
||||
* Class to write digital outputs. This class will wrtie digital outputs. Other
|
||||
* devices that are implemented elsewhere will automatically allocate digital
|
||||
* inputs and outputs as required.
|
||||
*/
|
||||
public class DigitalOutput extends DigitalSource implements IInputOutput,
|
||||
LiveWindowSendable {
|
||||
|
||||
private Pointer m_pwmGenerator;
|
||||
|
||||
/**
|
||||
* Create an instance of a digital output. Create an instance of a digital
|
||||
* output given a module number and channel.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the digital module to use
|
||||
* @param channel
|
||||
* the port to use for the digital output
|
||||
*/
|
||||
public DigitalOutput(int moduleNumber, int channel) {
|
||||
initDigitalPort(moduleNumber, channel, false);
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_DigitalOutput,
|
||||
channel, moduleNumber - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a digital output. Create a digital output given a
|
||||
* channel. The default module is used.
|
||||
*
|
||||
* @param channel
|
||||
* the port to use for the digital output
|
||||
*/
|
||||
public DigitalOutput(int channel) {
|
||||
this(getDefaultDigitalModule(), channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resources associated with a digital output.
|
||||
*/
|
||||
public void free() {
|
||||
// disable the pwm only if we have allocated it
|
||||
if (m_pwmGenerator != null) {
|
||||
disablePWM();
|
||||
}
|
||||
super.free();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a digital output.
|
||||
*
|
||||
* @param value
|
||||
* true is on, off is false
|
||||
*/
|
||||
public void set(boolean value) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setDIO(m_port, (short) (value ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The GPIO channel number that this object represents.
|
||||
*/
|
||||
public int getChannel() {
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a single pulse. Write a pulse to the specified digital output
|
||||
* channel. There can only be a single pulse going at any time.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to pulse.
|
||||
* @param pulseLength
|
||||
* The length of the pulse.
|
||||
*/
|
||||
public void pulse(final int channel, final float pulseLength) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.pulse(m_port, pulseLength, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Generate a single pulse. Write a pulse to the specified
|
||||
* digital output channel. There can only be a single pulse
|
||||
* going at any time.
|
||||
*
|
||||
* @param channel
|
||||
* The channel to pulse.
|
||||
* @param pulseLength
|
||||
* The length of the pulse.
|
||||
*/
|
||||
public void pulse(final int channel, final int pulseLength) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
float convertedPulse = (float) (pulseLength / 1.0e9 * (HALLibrary
|
||||
.getLoopTiming(status) * 25));
|
||||
System.err
|
||||
.println("You should use the float version of pulse for portability. This is deprecated");
|
||||
HALLibrary.pulse(m_port, convertedPulse, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the pulse is still going. Determine if a previously started
|
||||
* pulse is still going.
|
||||
*
|
||||
* @return true if pulsing
|
||||
*/
|
||||
public boolean isPulsing() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.isPulsing(m_port, status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the PWM frequency of the PWM output on a Digital Output line.
|
||||
*
|
||||
* The valid range is from 0.6 Hz to 19 kHz. The frequency resolution is
|
||||
* logarithmic.
|
||||
*
|
||||
* There is only one PWM frequency per digital module.
|
||||
*
|
||||
* @param rate
|
||||
* The frequency to output all digital output PWM signals on this
|
||||
* module.
|
||||
*/
|
||||
public void setPWMRate(double rate) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setPWMRateWithModule((byte) m_moduleNumber, (float) rate,
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable a PWM Output on this line.
|
||||
*
|
||||
* Allocate one of the 4 DO PWM generator resources from this module.
|
||||
*
|
||||
* Supply the initial duty-cycle to output so as to avoid a glitch when
|
||||
* first starting.
|
||||
*
|
||||
* The resolution of the duty cycle is 8-bit for low frequencies (1kHz or
|
||||
* less) but is reduced the higher the frequency of the PWM signal is.
|
||||
*
|
||||
* @param initialDutyCycle
|
||||
* The duty-cycle to start generating. [0..1]
|
||||
*/
|
||||
public void enablePWM(double initialDutyCycle) {
|
||||
if (m_pwmGenerator == null)
|
||||
return;
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
m_pwmGenerator = HALLibrary.allocatePWMWithModule(
|
||||
(byte) m_moduleNumber, status);
|
||||
HALUtil.checkStatus(status);
|
||||
HALLibrary.setPWMDutyCycle(m_pwmGenerator, (float) initialDutyCycle,
|
||||
status);
|
||||
HALUtil.checkStatus(status);
|
||||
HALLibrary.setPWMOutputChannelWithModule((byte) m_moduleNumber,
|
||||
m_pwmGenerator, m_channel, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this line from a PWM output back to a static Digital Output line.
|
||||
*
|
||||
* Free up one of the 4 DO PWM generator resources that were in use.
|
||||
*/
|
||||
public void disablePWM() {
|
||||
// Disable the output by routing to a dead bit.
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary
|
||||
.setPWMOutputChannel(m_pwmGenerator, kDigitalChannels, status);
|
||||
HALUtil.checkStatus(status);
|
||||
HALLibrary.freePWMWithModule((byte) m_moduleNumber, m_pwmGenerator,
|
||||
status);
|
||||
m_pwmGenerator = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the duty-cycle that is being generated on the line.
|
||||
*
|
||||
* The resolution of the duty cycle is 8-bit for low frequencies (1kHz or
|
||||
* less) but is reduced the higher the frequency of the PWM signal is.
|
||||
*
|
||||
* @param dutyCycle
|
||||
* The duty-cycle to change to. [0..1]
|
||||
*/
|
||||
public void updateDutyCycle(double dutyCycle) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setPWMDutyCycleWithModule((byte) m_moduleNumber,
|
||||
m_pwmGenerator, (float) dutyCycle, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Digital Output";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
private ITableListener m_table_listener;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
// TODO: Put current value.
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
m_table_listener = new ITableListener() {
|
||||
public void valueChanged(ITable itable, String key, Object value,
|
||||
boolean bln) {
|
||||
set(((Boolean) value).booleanValue());
|
||||
}
|
||||
};
|
||||
m_table.addTableListener("Value", m_table_listener, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
// TODO: Broken, should only remove the listener from "Value" only.
|
||||
m_table.removeTableListener(m_table_listener);
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
|
||||
/**
|
||||
* DigitalSource Interface. The DigitalSource represents all the possible inputs
|
||||
* for a counter or a quadrature encoder. The source may be either a digital
|
||||
* input or an analog input. If the caller just provides a channel, then a
|
||||
* digital input will be constructed and freed when finished for the source. The
|
||||
* source can either be a digital input or analog trigger but not both.
|
||||
*/
|
||||
public abstract class DigitalSource extends InterruptableSensorBase {
|
||||
|
||||
protected static Resource channels = new Resource(kDigitalChannels
|
||||
* kDigitalModules);
|
||||
protected Pointer m_port;
|
||||
protected int m_moduleNumber, m_channel;
|
||||
|
||||
protected void initDigitalPort(int moduleNumber, int channel, boolean input) {
|
||||
|
||||
m_channel = channel;
|
||||
m_moduleNumber = moduleNumber;
|
||||
if (HALLibrary.checkDigitalModule((byte) m_moduleNumber) != 1) {
|
||||
throw new AllocationException("Digital input " + m_channel
|
||||
+ " on module " + m_moduleNumber
|
||||
+ " cannot be allocated. Module is not present.");
|
||||
}
|
||||
checkDigitalChannel(m_channel); // XXX: Replace with
|
||||
// HALLibrary.checkDigitalChannel when
|
||||
// implemented
|
||||
|
||||
try {
|
||||
channels.allocate((m_moduleNumber - 1) * kDigitalChannels
|
||||
+ m_channel - 1);
|
||||
} catch (CheckedAllocationException ex) {
|
||||
throw new AllocationException("Digital input " + m_channel
|
||||
+ " on module " + m_moduleNumber + " is already allocated");
|
||||
}
|
||||
|
||||
Pointer port_pointer = HALLibrary.getPortWithModule(
|
||||
(byte) moduleNumber, (byte) channel);
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
m_port = HALLibrary.initializeDigitalPort(port_pointer, status);
|
||||
HALUtil.checkStatus(status);
|
||||
HALLibrary.allocateDIO(m_port, (byte) (input ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
public void free() {
|
||||
channels.free(((m_moduleNumber - 1) * kDigitalChannels + m_channel - 1));
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.freeDIO(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
m_channel = 0;
|
||||
m_moduleNumber = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channel routing number
|
||||
*
|
||||
* @return channel routing number
|
||||
*/
|
||||
public int getChannelForRouting() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int channel = HALLibrary.remapDigitalChannel(m_channel - 1, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the module routing number
|
||||
*
|
||||
* @return module routing number
|
||||
*/
|
||||
public int getModuleForRouting() {
|
||||
return m_moduleNumber - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this an analog trigger
|
||||
*
|
||||
* @return true if this is an analog trigger
|
||||
*/
|
||||
public boolean getAnalogTriggerForRouting() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
|
||||
/**
|
||||
* DoubleSolenoid class for running 2 channels of high voltage Digital Output
|
||||
* (9472 module).
|
||||
*
|
||||
* 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 {
|
||||
|
||||
/**
|
||||
* Possible values for a DoubleSolenoid
|
||||
*/
|
||||
public static class Value {
|
||||
|
||||
public final int value;
|
||||
public static final int kOff_val = 0;
|
||||
public static final int kForward_val = 1;
|
||||
public static final int kReverse_val = 2;
|
||||
public static final Value kOff = new Value(kOff_val);
|
||||
public static final Value kForward = new Value(kForward_val);
|
||||
public static final Value kReverse = new Value(kReverse_val);
|
||||
|
||||
private Value(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
private int m_forwardChannel; ///< The forward channel on the module to control.
|
||||
private int m_reverseChannel; ///< The reverse channel on the module to control.
|
||||
private byte m_forwardMask; ///< The mask for the forward channel.
|
||||
private byte m_reverseMask; ///< The mask for the reverse channel.
|
||||
|
||||
/**
|
||||
* Common function to implement constructor behavior.
|
||||
*/
|
||||
private synchronized void initSolenoid() {
|
||||
checkSolenoidModule(m_moduleNumber);
|
||||
checkSolenoidChannel(m_forwardChannel);
|
||||
checkSolenoidChannel(m_reverseChannel);
|
||||
|
||||
try {
|
||||
m_allocated.allocate((m_moduleNumber - 1) * kSolenoidChannels + m_forwardChannel - 1);
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException(
|
||||
"Solenoid channel " + m_forwardChannel + " on module " + m_moduleNumber + " is already allocated");
|
||||
}
|
||||
try {
|
||||
m_allocated.allocate((m_moduleNumber - 1) * kSolenoidChannels + m_reverseChannel - 1);
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException(
|
||||
"Solenoid channel " + m_reverseChannel + " on module " + m_moduleNumber + " is already allocated");
|
||||
}
|
||||
m_forwardMask = (byte) (1 << (m_forwardChannel - 1));
|
||||
m_reverseMask = (byte) (1 << (m_reverseChannel - 1));
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Solenoid, m_forwardChannel, m_moduleNumber-1);
|
||||
UsageReporting.report(tResourceType.kResourceType_Solenoid, m_reverseChannel, m_moduleNumber-1);
|
||||
LiveWindow.addActuator("DoubleSolenoid", m_moduleNumber, m_forwardChannel, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param forwardChannel The forward channel on the module to control.
|
||||
* @param reverseChannel The reverse channel on the module to control.
|
||||
*/
|
||||
public DoubleSolenoid(final int forwardChannel, final int reverseChannel) {
|
||||
super(getDefaultSolenoidModule());
|
||||
m_forwardChannel = forwardChannel;
|
||||
m_reverseChannel = reverseChannel;
|
||||
initSolenoid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param moduleNumber The module number of the solenoid module to use.
|
||||
* @param forwardChannel The forward channel on the module to control.
|
||||
* @param reverseChannel The reverse channel on the module to control.
|
||||
*/
|
||||
public DoubleSolenoid(final int moduleNumber, final int forwardChannel, final int reverseChannel) {
|
||||
super(moduleNumber);
|
||||
m_forwardChannel = forwardChannel;
|
||||
m_reverseChannel = reverseChannel;
|
||||
initSolenoid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public synchronized void free() {
|
||||
m_allocated.free((m_moduleNumber - 1) * kSolenoidChannels + m_forwardChannel - 1);
|
||||
m_allocated.free((m_moduleNumber - 1) * kSolenoidChannels + m_reverseChannel - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a solenoid.
|
||||
*
|
||||
* @param value Move the solenoid to forward, reverse, or don't move it.
|
||||
*/
|
||||
public void set(final Value value) {
|
||||
byte rawValue = 0;
|
||||
|
||||
switch (value.value) {
|
||||
case Value.kOff_val:
|
||||
rawValue = 0x00;
|
||||
break;
|
||||
case Value.kForward_val:
|
||||
rawValue = m_forwardMask;
|
||||
break;
|
||||
case Value.kReverse_val:
|
||||
rawValue = m_reverseMask;
|
||||
break;
|
||||
}
|
||||
|
||||
set(rawValue, m_forwardMask | m_reverseMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the current value of the solenoid.
|
||||
*
|
||||
* @return The current value of the solenoid.
|
||||
*/
|
||||
public Value get() {
|
||||
byte value = getAll();
|
||||
|
||||
if ((value & m_forwardMask) != 0) return Value.kForward;
|
||||
if ((value & m_reverseMask) != 0) return Value.kReverse;
|
||||
return Value.kOff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Double Solenoid";
|
||||
}
|
||||
private ITable m_table;
|
||||
private ITableListener m_table_listener;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
//TODO: this is bad
|
||||
m_table.putString("Value", (get() == Value.kForward ? "Forward" : (get() == Value.kReverse ? "Reverse" : "Off")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
set(Value.kOff); // Stop for safety
|
||||
m_table_listener = new ITableListener() {
|
||||
public void valueChanged(ITable itable, String key, Object value, boolean bln) {
|
||||
//TODO: this is bad also
|
||||
if (value.toString().equals("Reverse"))
|
||||
set(Value.kReverse);
|
||||
else if (value.toString().equals("Forward"))
|
||||
set(Value.kForward);
|
||||
else
|
||||
set(Value.kOff);
|
||||
}
|
||||
};
|
||||
m_table.addTableListener("Value", m_table_listener, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
set(Value.kOff); // Stop for safety
|
||||
// TODO: Broken, should only remove the listener from "Value" only.
|
||||
m_table.removeTableListener(m_table_listener);
|
||||
}
|
||||
}
|
||||
@@ -1,648 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.*;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.parsing.IInputOutput;
|
||||
|
||||
/**
|
||||
* Provide access to the network communication data to / from the Driver Station.
|
||||
*/
|
||||
public class DriverStation implements IInputOutput {
|
||||
|
||||
/**
|
||||
* The size of the user status data
|
||||
*/
|
||||
public static final int USER_STATUS_DATA_SIZE = FRC_NetworkCommunicationsLibrary.USER_STATUS_DATA_SIZE;
|
||||
/**
|
||||
* Slot for the analog module to read the battery
|
||||
*/
|
||||
public static final int kBatterySlot = 1;
|
||||
/**
|
||||
* Analog channel to read the battery
|
||||
*/
|
||||
public static final int kBatteryChannel = 8;
|
||||
/**
|
||||
* Number of Joystick Ports
|
||||
*/
|
||||
public static final int kJoystickPorts = 4;
|
||||
/**
|
||||
* Number of Joystick Axes
|
||||
*/
|
||||
public static final int kJoystickAxes = 6;
|
||||
/**
|
||||
* Convert from raw values to volts
|
||||
*/
|
||||
public static final double kDSAnalogInScaling = 5.0 / 1023.0;
|
||||
|
||||
/**
|
||||
* The robot alliance that the robot is a part of
|
||||
*/
|
||||
public static class Alliance {
|
||||
|
||||
/** The integer value representing this enumeration. */
|
||||
public final int value;
|
||||
/** The Alliance name. */
|
||||
public final String name;
|
||||
public static final int kRed_val = 0;
|
||||
public static final int kBlue_val = 1;
|
||||
public static final int kInvalid_val = 2;
|
||||
/** alliance: Red */
|
||||
public static final Alliance kRed = new Alliance(kRed_val, "Red");
|
||||
/** alliance: Blue */
|
||||
public static final Alliance kBlue = new Alliance(kBlue_val, "Blue");
|
||||
/** alliance: Invalid */
|
||||
public static final Alliance kInvalid = new Alliance(kInvalid_val, "invalid");
|
||||
|
||||
private Alliance(int value, String name) {
|
||||
this.value = value;
|
||||
this.name = name;
|
||||
}
|
||||
} /* Alliance */
|
||||
|
||||
|
||||
private static class DriverStationTask implements Runnable {
|
||||
|
||||
private DriverStation m_ds;
|
||||
|
||||
DriverStationTask(DriverStation ds) {
|
||||
m_ds = ds;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
m_ds.task();
|
||||
}
|
||||
} /* DriverStationTask */
|
||||
|
||||
private static DriverStation instance = new DriverStation();
|
||||
private FRCCommonControlData m_controlData;
|
||||
private AnalogChannel m_batteryChannel;
|
||||
private Thread m_thread;
|
||||
private final Object m_semaphore;
|
||||
private final Object m_dataSem;
|
||||
private int m_digitalOut;
|
||||
private volatile boolean m_thread_keepalive = true;
|
||||
private final Dashboard m_dashboardDefaultHigh;
|
||||
private final Dashboard m_dashboardDefaultLow;
|
||||
private IDashboard m_dashboardInUseHigh;
|
||||
private IDashboard m_dashboardInUseLow;
|
||||
private int m_updateNumber = 0;
|
||||
private double m_approxMatchTimeOffset = -1.0;
|
||||
private boolean m_userInDisabled = false;
|
||||
private boolean m_userInAutonomous = false;
|
||||
private boolean m_userInTeleop = false;
|
||||
private boolean m_userInTest = false;
|
||||
private boolean m_newControlData;
|
||||
private final Pointer m_packetDataAvailableSem;
|
||||
// XXX: Add DriverStationEnhancedIO back
|
||||
// private DriverStationEnhancedIO m_enhancedIO = new DriverStationEnhancedIO();
|
||||
|
||||
/**
|
||||
* Gets an instance of the DriverStation
|
||||
*
|
||||
* @return The DriverStation.
|
||||
*/
|
||||
public static DriverStation getInstance() {
|
||||
return DriverStation.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* DriverStation constructor.
|
||||
*
|
||||
* The single DriverStation instance is created statically with the
|
||||
* instance static member variable.
|
||||
*/
|
||||
protected DriverStation() {
|
||||
m_controlData = new FRCCommonControlData();
|
||||
m_semaphore = new Object();
|
||||
m_dataSem = new Object();
|
||||
|
||||
m_dashboardInUseHigh = m_dashboardDefaultHigh = new Dashboard(m_semaphore);
|
||||
m_dashboardInUseLow = m_dashboardDefaultLow = new Dashboard(m_semaphore);
|
||||
|
||||
// m_controlData is initialized in constructor FRCCommonControlData.
|
||||
|
||||
// XXX: Uncomment when analogChannel is fixed
|
||||
//m_batteryChannel = new AnalogChannel(kBatterySlot, kBatteryChannel);
|
||||
|
||||
m_packetDataAvailableSem = HALLibrary.initializeMutex(HALLibrary.SEMAPHORE_Q_PRIORITY.get());
|
||||
FRC_NetworkCommunicationsLibrary.setNewDataSem(m_packetDataAvailableSem);
|
||||
|
||||
m_thread = new Thread(new DriverStationTask(this), "FRCDriverStation");
|
||||
m_thread.setPriority((Thread.NORM_PRIORITY + Thread.MAX_PRIORITY) / 2);
|
||||
|
||||
m_thread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Kill the thread
|
||||
*/
|
||||
public void release() {
|
||||
m_thread_keepalive = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the service routine for the DS polling thread.
|
||||
*/
|
||||
private void task() {
|
||||
int safetyCounter = 0;
|
||||
while (m_thread_keepalive) {
|
||||
HALLibrary.takeMutex(m_packetDataAvailableSem, HALLibrary.SEMAPHORE_WAIT_FOREVER.get());
|
||||
synchronized (this) {
|
||||
getData();
|
||||
// XXX: Add DriverStationEnhancedIO back
|
||||
// m_enhancedIO.updateData();
|
||||
setData();
|
||||
}
|
||||
synchronized (m_dataSem) {
|
||||
m_dataSem.notifyAll();
|
||||
}
|
||||
if (++safetyCounter >= 5) {
|
||||
// System.out.println("Checking safety");
|
||||
MotorSafetyHelper.checkMotors();
|
||||
safetyCounter = 0;
|
||||
}
|
||||
if (m_userInDisabled) {
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramDisabled();
|
||||
}
|
||||
if (m_userInAutonomous) {
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramAutonomous();
|
||||
}
|
||||
if (m_userInTeleop) {
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramTeleop();
|
||||
}
|
||||
if (m_userInTest) {
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramTest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for new data from the driver station.
|
||||
*/
|
||||
public void waitForData() {
|
||||
waitForData(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for new data or for timeout, which ever comes first. If timeout is
|
||||
* 0, wait for new data only.
|
||||
*
|
||||
* @param timeout The maximum time in milliseconds to wait.
|
||||
*/
|
||||
public void waitForData(long timeout) {
|
||||
synchronized (m_dataSem) {
|
||||
try {
|
||||
m_dataSem.wait(timeout);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
private static boolean lastEnabled = false;
|
||||
|
||||
/**
|
||||
* Copy data from the DS task for the user.
|
||||
* If no new data exists, it will just be returned, otherwise
|
||||
* the data will be copied from the DS polling loop.
|
||||
*/
|
||||
protected synchronized void getData() {
|
||||
FRC_NetworkCommunicationsLibrary.getCommonControlData(m_controlData, HALLibrary.SEMAPHORE_WAIT_FOREVER.get());
|
||||
|
||||
if (!lastEnabled && isEnabled()) {
|
||||
// If starting teleop, assume that autonomous just took up 15 seconds
|
||||
if (isAutonomous()) {
|
||||
m_approxMatchTimeOffset = Timer.getFPGATimestamp();
|
||||
} else {
|
||||
m_approxMatchTimeOffset = Timer.getFPGATimestamp() - 15.0;
|
||||
}
|
||||
} else if (lastEnabled && !isEnabled()) {
|
||||
m_approxMatchTimeOffset = -1.0;
|
||||
}
|
||||
lastEnabled = isEnabled();
|
||||
|
||||
m_newControlData = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy status data from the DS task for the user.
|
||||
* This is used primarily to set digital outputs on the DS.
|
||||
*/
|
||||
protected void setData() {
|
||||
synchronized (m_semaphore) {
|
||||
FRC_NetworkCommunicationsLibrary.setStatusData((float) getBatteryVoltage(),
|
||||
(byte) m_digitalOut,
|
||||
(byte) m_updateNumber,
|
||||
new String(m_dashboardInUseHigh.getBytes()),
|
||||
m_dashboardInUseHigh.getBytesLength(),
|
||||
new String(m_dashboardInUseLow.getBytes()),
|
||||
m_dashboardInUseLow.getBytesLength(),
|
||||
HALLibrary.SEMAPHORE_WAIT_FOREVER.get());
|
||||
m_dashboardInUseHigh.flush();
|
||||
m_dashboardInUseLow.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the battery voltage from the specified AnalogChannel.
|
||||
*
|
||||
* This accessor assumes that the battery voltage is being measured
|
||||
* through the voltage divider on an analog breakout.
|
||||
*
|
||||
* @return The battery voltage.
|
||||
*/
|
||||
public double getBatteryVoltage() {
|
||||
// The Analog bumper has a voltage divider on the battery source.
|
||||
// Vbatt *--/\/\/\--* Vsample *--/\/\/\--* Gnd
|
||||
// 680 Ohms 1000 Ohms
|
||||
// XXX: Uncomment this when analog channel is fixed
|
||||
//return m_batteryChannel.getAverageVoltage() * (1680.0 / 1000.0);
|
||||
return 12.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the axis on a joystick.
|
||||
* This depends on the mapping of the joystick connected to the specified port.
|
||||
*
|
||||
* @param stick The joystick to read.
|
||||
* @param axis The analog axis value to read from the joystick.
|
||||
* @return The value of the axis on the joystick.
|
||||
*/
|
||||
public double getStickAxis(int stick, int axis) {
|
||||
if (axis < 1 || axis > kJoystickAxes) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
int value;
|
||||
switch (stick) {
|
||||
case 1:
|
||||
value = m_controlData.field2.stick0Axes[axis - 1];
|
||||
break;
|
||||
case 2:
|
||||
value = m_controlData.field3.stick1Axes[axis - 1];
|
||||
break;
|
||||
case 3:
|
||||
value = m_controlData.field4.stick2Axes[axis - 1];
|
||||
break;
|
||||
case 4:
|
||||
value = m_controlData.field5.stick3Axes[axis - 1];
|
||||
break;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double result;
|
||||
if (value < 0) {
|
||||
result = ((double) value) / 128.0;
|
||||
} else {
|
||||
result = ((double) value) / 127.0;
|
||||
}
|
||||
|
||||
// wpi_assert(result <= 1.0 && result >= -1.0);
|
||||
if (result > 1.0) {
|
||||
result = 1.0;
|
||||
} else if (result < -1.0) {
|
||||
result = -1.0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* The state of the buttons on the joystick.
|
||||
* 12 buttons (4 msb are unused) from the joystick.
|
||||
*
|
||||
* @param stick The joystick to read.
|
||||
* @return The state of the buttons on the joystick.
|
||||
*/
|
||||
public int getStickButtons(final int stick) {
|
||||
switch (stick) {
|
||||
case 1:
|
||||
return m_controlData.stick0Buttons;
|
||||
case 2:
|
||||
return m_controlData.stick1Buttons;
|
||||
case 3:
|
||||
return m_controlData.stick2Buttons;
|
||||
case 4:
|
||||
return m_controlData.stick3Buttons;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an analog voltage from the Driver Station.
|
||||
* The analog values are returned as voltage values for the Driver Station analog inputs.
|
||||
* These inputs are typically used for advanced operator interfaces consisting of potentiometers
|
||||
* or resistor networks representing values on a rotary switch.
|
||||
*
|
||||
* @param channel The analog input channel on the driver station to read from. Valid range is 1 - 4.
|
||||
* @return The analog voltage on the input.
|
||||
*/
|
||||
public double getAnalogIn(final int channel) {
|
||||
switch (channel) {
|
||||
case 1:
|
||||
return kDSAnalogInScaling * m_controlData.analog1;
|
||||
case 2:
|
||||
return kDSAnalogInScaling * m_controlData.analog2;
|
||||
case 3:
|
||||
return kDSAnalogInScaling * m_controlData.analog3;
|
||||
case 4:
|
||||
return kDSAnalogInScaling * m_controlData.analog4;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get values from the digital inputs on the Driver Station.
|
||||
* Return digital values from the Drivers Station. These values are typically used for buttons
|
||||
* and switches on advanced operator interfaces.
|
||||
* @param channel The digital input to get. Valid range is 1 - 8.
|
||||
* @return The value of the digital input
|
||||
*/
|
||||
public boolean getDigitalIn(final int channel) {
|
||||
return ((m_controlData.dsDigitalIn >> (channel - 1)) & 0x1) == 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value for the digital outputs on the Driver Station.
|
||||
*
|
||||
* Control digital outputs on the Drivers Station. These values are typically used for
|
||||
* giving feedback on a custom operator station such as LEDs.
|
||||
*
|
||||
* @param channel The digital output to set. Valid range is 1 - 8.
|
||||
* @param value The state to set the digital output.
|
||||
*/
|
||||
public void setDigitalOut(final int channel, final boolean value) {
|
||||
m_digitalOut &= ~(0x1 << (channel - 1));
|
||||
m_digitalOut |= ((value ? 1 : 0) << (channel - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value that was set for the digital outputs on the Driver Station.
|
||||
* @param channel The digital ouput to monitor. Valid range is 1 through 8.
|
||||
* @return A digital value being output on the Drivers Station.
|
||||
*/
|
||||
public boolean getDigitalOut(final int channel) {
|
||||
return ((m_digitalOut >> (channel - 1)) & 0x1) == 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether the Driver Station requires the
|
||||
* robot to be enabled.
|
||||
*
|
||||
* @return True if the robot is enabled, false otherwise.
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return (m_controlData.field1.control & FRCCommonControlMasks.ENABLED) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether the Driver Station requires the
|
||||
* robot to be disabled.
|
||||
*
|
||||
* @return True if the robot should be disabled, false otherwise.
|
||||
*/
|
||||
public boolean isDisabled() {
|
||||
return !isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether the Driver Station requires the
|
||||
* robot to be running in autonomous mode.
|
||||
*
|
||||
* @return True if autonomous mode should be enabled, false otherwise.
|
||||
*/
|
||||
public boolean isAutonomous() {
|
||||
return (m_controlData.field1.control & FRCCommonControlMasks.AUTONOMOUS) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether the Driver Station requires the
|
||||
* robot to be running in test mode.
|
||||
* @return True if test mode should be enabled, false otherwise.
|
||||
*/
|
||||
public boolean isTest() {
|
||||
return (m_controlData.field1.control & FRCCommonControlMasks.TEST) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether the Driver Station requires the
|
||||
* robot to be running in operator-controlled mode.
|
||||
*
|
||||
* @return True if operator-controlled mode should be enabled, false otherwise.
|
||||
*/
|
||||
public boolean isOperatorControl() {
|
||||
return !(isAutonomous() || isTest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Has a new control packet from the driver station arrived since the last time this function was called?
|
||||
* @return True if the control data has been updated since the last call.
|
||||
*/
|
||||
public synchronized boolean isNewControlData() {
|
||||
boolean result = m_newControlData;
|
||||
m_newControlData = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DS packet number.
|
||||
* The packet number is the index of this set of data returned by the driver station.
|
||||
* Each time new data is received, the packet number (included with the sent data) is returned.
|
||||
*
|
||||
* @return The DS packet number.
|
||||
*/
|
||||
public int getPacketNumber() {
|
||||
return m_controlData.packetIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current alliance from the FMS
|
||||
* @return the current alliance
|
||||
*/
|
||||
public Alliance getAlliance() {
|
||||
switch (m_controlData.dsID_Alliance) {
|
||||
case 'R':
|
||||
return Alliance.kRed;
|
||||
case 'B':
|
||||
return Alliance.kBlue;
|
||||
default:
|
||||
return Alliance.kInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location of the team's driver station controls.
|
||||
*
|
||||
* @return the location of the team's driver station controls: 1, 2, or 3
|
||||
*/
|
||||
public int getLocation() {
|
||||
return m_controlData.dsID_Position - '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the team number that the Driver Station is configured for
|
||||
* @return The team number
|
||||
*/
|
||||
public int getTeamNumber() {
|
||||
return m_controlData.teamID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dashboard packer to use for sending high priority user data to a
|
||||
* dashboard receiver. This can idle or restore the default packer.
|
||||
* (Initializing SmartDashboard sets the high priority packer in use, so
|
||||
* beware that the default packer will then be idle. You can restore the
|
||||
* default high priority packer by calling
|
||||
* {@code setDashboardPackerToUseHigh(getDashboardPackerHigh())}.)
|
||||
*
|
||||
* @param dashboard any kind of IDashboard object
|
||||
*/
|
||||
public void setDashboardPackerToUseHigh(IDashboard dashboard) {
|
||||
m_dashboardInUseHigh = dashboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default dashboard packer for sending high priority user data to
|
||||
* a dashboard receiver. This instance stays around even after a call to
|
||||
* {@link #setDashboardPackerToUseHigh} changes which packer is in use.
|
||||
*
|
||||
* @return the default Dashboard object; it may be idle
|
||||
*/
|
||||
public Dashboard getDashboardPackerHigh() {
|
||||
return m_dashboardDefaultHigh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dashboard packer that's currently in use for sending high
|
||||
* priority user data to a dashboard receiver. This can be any kind of
|
||||
* IDashboard.
|
||||
*
|
||||
* @return the current IDashboard object
|
||||
*/
|
||||
public IDashboard getDashboardPackerInUseHigh() {
|
||||
return m_dashboardInUseHigh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dashboard packer to use for sending low priority user data to a
|
||||
* dashboard receiver. This can idle or restore the default packer.
|
||||
*
|
||||
* @param dashboard any kind of IDashboard object
|
||||
*/
|
||||
public void setDashboardPackerToUseLow(IDashboard dashboard) {
|
||||
m_dashboardInUseLow = dashboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default dashboard packer for sending low priority user data to
|
||||
* a dashboard receiver. This instance stays around even after a call to
|
||||
* {@link #setDashboardPackerToUseLow} changes which packer is in use.
|
||||
*
|
||||
* @return the default Dashboard object; it may be idle
|
||||
*/
|
||||
public Dashboard getDashboardPackerLow() {
|
||||
return m_dashboardDefaultLow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dashboard packer that's currently in use for sending low
|
||||
* priority user data to a dashboard receiver. This can be any kind of
|
||||
* IDashboard.
|
||||
*
|
||||
* @return the current IDashboard object
|
||||
*/
|
||||
public IDashboard getDashboardPackerInUseLow() {
|
||||
return m_dashboardInUseLow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status data monitor
|
||||
* @return The status data monitor for use with IDashboard objects which must
|
||||
* send data across the network.
|
||||
*/
|
||||
public Object getStatusDataMonitor() {
|
||||
return m_semaphore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the internal update number sent across the network along with
|
||||
* status data.
|
||||
*/
|
||||
void incrementUpdateNumber() {
|
||||
synchronized (m_semaphore) {
|
||||
m_updateNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the driver station attached to a Field Management System?
|
||||
* Note: This does not work with the Blue DS.
|
||||
* @return True if the robot is competing on a field being controlled by a Field Management System
|
||||
*/
|
||||
public boolean isFMSAttached() {
|
||||
return (m_controlData.field1.control & FRCCommonControlMasks.FMS_ATTATCHED) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interface to the enhanced IO of the new driver station.
|
||||
* @return An enhanced IO object for the advanced features of the driver
|
||||
* station.
|
||||
*/
|
||||
// XXX: Add DriverStationEnhancedIO back
|
||||
// public DriverStationEnhancedIO getEnhancedIO() {
|
||||
// return m_enhancedIO;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return the approximate match time
|
||||
* The FMS does not currently send the official match time to the robots
|
||||
* This returns the time since the enable signal sent from the Driver Station
|
||||
* At the beginning of autonomous, the time is reset to 0.0 seconds
|
||||
* At the beginning of teleop, the time is reset to +15.0 seconds
|
||||
* If the robot is disabled, this returns 0.0 seconds
|
||||
* Warning: This is not an official time (so it cannot be used to argue with referees)
|
||||
* @return Match time in seconds since the beginning of autonomous
|
||||
*/
|
||||
public double getMatchTime() {
|
||||
if (m_approxMatchTimeOffset < 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
return Timer.getFPGATimestamp() - m_approxMatchTimeOffset;
|
||||
}
|
||||
|
||||
/** Only to be used to tell the Driver Station what code you claim to be executing
|
||||
* for diagnostic purposes only
|
||||
* @param entering If true, starting disabled code; if false, leaving disabled code */
|
||||
public void InDisabled(boolean entering) {
|
||||
m_userInDisabled=entering;
|
||||
}
|
||||
|
||||
/** Only to be used to tell the Driver Station what code you claim to be executing
|
||||
* for diagnostic purposes only
|
||||
* @param entering If true, starting autonomous code; if false, leaving autonomous code */
|
||||
public void InAutonomous(boolean entering) {
|
||||
m_userInAutonomous=entering;
|
||||
}
|
||||
|
||||
/** Only to be used to tell the Driver Station what code you claim to be executing
|
||||
* for diagnostic purposes only
|
||||
* @param entering If true, starting teleop code; if false, leaving teleop code */
|
||||
public void InOperatorControl(boolean entering) {
|
||||
m_userInTeleop=entering;
|
||||
}
|
||||
|
||||
/** Only to be used to tell the Driver Station what code you claim to be executing
|
||||
* for diagnostic purposes only
|
||||
* @param entering If true, starting test code; if false, leaving test code */
|
||||
public void InTest(boolean entering) {
|
||||
m_userInTeleop = entering;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,198 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.parsing.IInputOutput;
|
||||
|
||||
/**
|
||||
* Provide access to "LCD" on the Driver Station.
|
||||
* This is the Messages box on the DS Operation tab.
|
||||
*
|
||||
* Buffer the printed data locally and then send it
|
||||
* when UpdateLCD is called.
|
||||
*/
|
||||
public class DriverStationLCD extends SensorBase implements IInputOutput {
|
||||
|
||||
private static DriverStationLCD m_instance;
|
||||
/**
|
||||
* Driver station timeout in milliseconds
|
||||
*/
|
||||
public static final int kSyncTimeout_ms = 20;
|
||||
/**
|
||||
* Command to display text
|
||||
*/
|
||||
public static final int kFullDisplayTextCommand = 0x9FFF;
|
||||
/**
|
||||
* Maximum line length for Driver Station display
|
||||
*/
|
||||
public static final int kLineLength = 21;
|
||||
/**
|
||||
* Total number of lines available
|
||||
*/
|
||||
public static final int kNumLines = 6;
|
||||
|
||||
/**
|
||||
* The line number on the Driver Station LCD
|
||||
*/
|
||||
public static class Line {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kMain6_val = 0;
|
||||
static final int kUser1_val = 0;
|
||||
static final int kUser2_val = 1;
|
||||
static final int kUser3_val = 2;
|
||||
static final int kUser4_val = 3;
|
||||
static final int kUser5_val = 4;
|
||||
static final int kUser6_val = 5;
|
||||
/**
|
||||
* @deprecated Use kUser1
|
||||
* Line at the Top of the screen
|
||||
*/
|
||||
public static final Line kMain6 = new Line(kMain6_val);
|
||||
/**
|
||||
* Line at the Top of the screen
|
||||
*/
|
||||
public static final Line kUser1 = new Line(kUser1_val);
|
||||
/**
|
||||
* Line on the user screen
|
||||
*/
|
||||
public static final Line kUser2 = new Line(kUser2_val);
|
||||
/**
|
||||
* Line on the user screen
|
||||
*/
|
||||
public static final Line kUser3 = new Line(kUser3_val);
|
||||
/**
|
||||
* Line on the user screen
|
||||
*/
|
||||
public static final Line kUser4 = new Line(kUser4_val);
|
||||
/**
|
||||
* Line on the user screen
|
||||
*/
|
||||
public static final Line kUser5 = new Line(kUser5_val);
|
||||
/**
|
||||
* Bottom line on the user screen
|
||||
*/
|
||||
public static final Line kUser6 = new Line(kUser6_val);
|
||||
|
||||
private Line(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] m_textBuffer;
|
||||
|
||||
/**
|
||||
* Get an instance of the DriverStationLCD
|
||||
* @return an instance of the DriverStationLCD
|
||||
*/
|
||||
public static synchronized DriverStationLCD getInstance() {
|
||||
if (m_instance == null)
|
||||
m_instance = new DriverStationLCD();
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* DriverStationLCD constructor.
|
||||
*
|
||||
* This is only called once the first time GetInstance() is called
|
||||
*/
|
||||
private DriverStationLCD() {
|
||||
m_textBuffer = new byte[FRC_NetworkCommunicationsLibrary.USER_DS_LCD_DATA_SIZE];
|
||||
|
||||
for (int i = 0; i < FRC_NetworkCommunicationsLibrary.USER_DS_LCD_DATA_SIZE; i++) {
|
||||
m_textBuffer[i] = ' ';
|
||||
}
|
||||
|
||||
m_textBuffer[0] = (byte) (kFullDisplayTextCommand >> 8);
|
||||
m_textBuffer[1] = (byte) kFullDisplayTextCommand;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_DriverStationLCD, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the text data to the Driver Station.
|
||||
*/
|
||||
public synchronized void updateLCD() {
|
||||
FRC_NetworkCommunicationsLibrary.setUserDsLcdData(new String(m_textBuffer), FRC_NetworkCommunicationsLibrary.USER_DS_LCD_DATA_SIZE, kSyncTimeout_ms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print formatted text to the Driver Station LCD text buffer.
|
||||
*
|
||||
* Use UpdateLCD() periodically to actually send the test to the Driver Station.
|
||||
*
|
||||
* @param line The line on the LCD to print to.
|
||||
* @param startingColumn The column to start printing to. This is a 1-based number.
|
||||
* @param text the text to print
|
||||
*/
|
||||
public void println(Line line, int startingColumn, String text) {
|
||||
int start = startingColumn - 1;
|
||||
int maxLength = kLineLength - start;
|
||||
|
||||
if (startingColumn < 1 || startingColumn > kLineLength) {
|
||||
throw new IndexOutOfBoundsException("Column must be between 1 and " + kLineLength + ", inclusive");
|
||||
}
|
||||
|
||||
int length = text.length();
|
||||
int finalLength = (length < maxLength ? length : maxLength);
|
||||
synchronized (this) {
|
||||
for (int i = 0; i < finalLength; i++) {
|
||||
m_textBuffer[i + start + line.value * kLineLength + 2] = (byte)text.charAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print formatted text to the Driver Station LCD text buffer.
|
||||
*
|
||||
* Use UpdateLCD() periodically to actually send the test to the Driver Station.
|
||||
*
|
||||
* @param line The line on the LCD to print to.
|
||||
* @param startingColumn The column to start printing to. This is a 1-based number.
|
||||
* @param text the text to print
|
||||
*/
|
||||
public void println(Line line, int startingColumn, StringBuffer text) {
|
||||
int start = startingColumn - 1;
|
||||
int maxLength = kLineLength - start;
|
||||
|
||||
if (startingColumn < 1 || startingColumn > kLineLength) {
|
||||
throw new IndexOutOfBoundsException("Column must be between 1 and " + kLineLength + ", inclusive");
|
||||
}
|
||||
|
||||
int length = text.length();
|
||||
int finalLength = (length < maxLength ? length : maxLength);
|
||||
synchronized (this) {
|
||||
for (int i = 0; i < finalLength; i++) {
|
||||
m_textBuffer[i + start + line.value * kLineLength + 2] = (byte) text.charAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear User Messages box on DS Operations Tab
|
||||
*
|
||||
* This method will clear all text currently displayed in the message box
|
||||
*/
|
||||
public void clear() {
|
||||
synchronized (this) {
|
||||
for (int i=0; i < kLineLength*kNumLines; i++) {
|
||||
m_textBuffer[i+2] = ' ';
|
||||
}
|
||||
}
|
||||
updateLCD();
|
||||
}
|
||||
}
|
||||
@@ -1,887 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tInstances;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.ISensor;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
|
||||
/**
|
||||
* Class to read quad encoders. Quadrature encoders are devices that count shaft
|
||||
* rotation and can sense direction. The output of the QuadEncoder class is an
|
||||
* integer that can count either up or down, and can go negative for reverse
|
||||
* direction counting. When creating QuadEncoders, a direction is supplied that
|
||||
* changes the sense of the output to make code more readable if the encoder is
|
||||
* mounted such that forward movement generates negative values. Quadrature
|
||||
* encoders have two digital outputs, an A Channel and a B Channel that are out
|
||||
* of phase with each other to allow the FPGA to do direction sensing.
|
||||
*/
|
||||
public class Encoder extends SensorBase implements CounterBase, PIDSource,
|
||||
ISensor, LiveWindowSendable {
|
||||
|
||||
/**
|
||||
* The a source
|
||||
*/
|
||||
protected DigitalSource m_aSource; // the A phase of the quad encoder
|
||||
/**
|
||||
* The b source
|
||||
*/
|
||||
protected DigitalSource m_bSource; // the B phase of the quad encoder
|
||||
/**
|
||||
* The index source
|
||||
*/
|
||||
protected DigitalSource m_indexSource = null; // Index on some encoders
|
||||
private Pointer m_encoder;
|
||||
private int m_index;
|
||||
private double m_distancePerPulse; // distance of travel for each encoder
|
||||
// tick
|
||||
private Counter m_counter; // Counter object for 1x and 2x encoding
|
||||
private EncodingType m_encodingType = EncodingType.k4X;
|
||||
private boolean m_allocatedA;
|
||||
private boolean m_allocatedB;
|
||||
private boolean m_allocatedI;
|
||||
private PIDSourceParameter m_pidSource;
|
||||
|
||||
/**
|
||||
* Common initialization code for Encoders. This code allocates resources
|
||||
* for Encoders and is common to all constructors.
|
||||
*
|
||||
* @param reverseDirection
|
||||
* If true, counts down instead of up (this is all relative)
|
||||
* @param encodingType
|
||||
* either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If
|
||||
* 4X is selected, then an encoder FPGA object is used and the
|
||||
* returned counts will be 4x the encoder spec'd value since all
|
||||
* rising and falling edges are counted. If 1X or 2X are selected
|
||||
* then a counter object will be used and the returned value will
|
||||
* either exactly match the spec'd count or be double (2x) the
|
||||
* spec'd count.
|
||||
*/
|
||||
private void initEncoder(boolean reverseDirection) {
|
||||
switch (m_encodingType.value) {
|
||||
case EncodingType.k4X_val:
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
IntBuffer index = IntBuffer.allocate(1);
|
||||
m_encoder = HALLibrary.initializeEncoder(
|
||||
(byte) m_aSource.getModuleForRouting(),
|
||||
m_aSource.getChannelForRouting(),
|
||||
(byte) (m_aSource.getAnalogTriggerForRouting() ? 1 : 0),
|
||||
(byte) m_bSource.getModuleForRouting(),
|
||||
m_bSource.getChannelForRouting(),
|
||||
(byte) (m_bSource.getAnalogTriggerForRouting() ? 1 : 0),
|
||||
(byte) (reverseDirection ? 1 : 0), index, status);
|
||||
HALUtil.checkStatus(status);
|
||||
m_index = index.get();
|
||||
m_counter = null;
|
||||
break;
|
||||
case EncodingType.k2X_val:
|
||||
case EncodingType.k1X_val:
|
||||
m_counter = new Counter(m_encodingType, m_aSource, m_bSource,
|
||||
reverseDirection);
|
||||
break;
|
||||
}
|
||||
m_distancePerPulse = 1.0;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Encoder,
|
||||
m_index, m_encodingType.value);
|
||||
LiveWindow.addSensor("Encoder", m_aSource.getModuleForRouting(),
|
||||
m_aSource.getChannelForRouting(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b modules and
|
||||
* channels fully specified.
|
||||
*
|
||||
* @param aSlot
|
||||
* The a channel digital input module.
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bSlot
|
||||
* The b channel digital input module.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
* @param reverseDirection
|
||||
* represents the orientation of the encoder and inverts the
|
||||
* output values if necessary so forward represents positive
|
||||
* values.
|
||||
*/
|
||||
public Encoder(final int aSlot, final int aChannel, final int bSlot,
|
||||
final int bChannel, boolean reverseDirection) {
|
||||
m_allocatedA = true;
|
||||
m_allocatedB = true;
|
||||
m_allocatedI = false;
|
||||
m_aSource = new DigitalInput(aSlot, aChannel);
|
||||
m_bSource = new DigitalInput(bSlot, bChannel);
|
||||
initEncoder(reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b modules and
|
||||
* channels fully specified.
|
||||
*
|
||||
* @param aSlot
|
||||
* The a channel digital input module.
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bSlot
|
||||
* The b channel digital input module.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
*/
|
||||
public Encoder(final int aSlot, final int aChannel, final int bSlot,
|
||||
final int bChannel) {
|
||||
this(aSlot, aChannel, bSlot, bChannel, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b modules and
|
||||
* channels fully specified.
|
||||
*
|
||||
* @param aSlot
|
||||
* The a channel digital input module.
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bSlot
|
||||
* The b channel digital input module.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
* @param reverseDirection
|
||||
* represents the orientation of the encoder and inverts the
|
||||
* output values if necessary so forward represents positive
|
||||
* values.
|
||||
* @param encodingType
|
||||
* either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If
|
||||
* 4X is selected, then an encoder FPGA object is used and the
|
||||
* returned counts will be 4x the encoder spec'd value since all
|
||||
* rising and falling edges are counted. If 1X or 2X are selected
|
||||
* then a counter object will be used and the returned value will
|
||||
* either exactly match the spec'd count or be double (2x) the
|
||||
* spec'd count.
|
||||
*/
|
||||
public Encoder(final int aSlot, final int aChannel, final int bSlot,
|
||||
final int bChannel, boolean reverseDirection,
|
||||
final EncodingType encodingType) {
|
||||
m_allocatedA = true;
|
||||
m_allocatedB = true;
|
||||
m_allocatedI = false;
|
||||
m_aSource = new DigitalInput(aSlot, aChannel);
|
||||
m_bSource = new DigitalInput(bSlot, bChannel);
|
||||
if (encodingType == null)
|
||||
throw new NullPointerException("Given encoding type was null");
|
||||
m_encodingType = encodingType;
|
||||
initEncoder(reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b modules and
|
||||
* channels fully specified. Using the index pulse forces 4x encoding.
|
||||
*
|
||||
* @param aSlot
|
||||
* The a channel digital input module.
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bSlot
|
||||
* The b channel digital input module.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
* @param indexSlot
|
||||
* The index channel digital input module.
|
||||
* @param indexChannel
|
||||
* The index channel digital input channel.
|
||||
* @param reverseDirection
|
||||
* represents the orientation of the encoder and inverts the
|
||||
* output values if necessary so forward represents positive
|
||||
* values.
|
||||
*/
|
||||
public Encoder(final int aSlot, final int aChannel, final int bSlot,
|
||||
final int bChannel, final int indexSlot, final int indexChannel,
|
||||
boolean reverseDirection) {
|
||||
m_allocatedA = true;
|
||||
m_allocatedB = true;
|
||||
m_allocatedI = true;
|
||||
m_aSource = new DigitalInput(aSlot, aChannel);
|
||||
m_bSource = new DigitalInput(bSlot, bChannel);
|
||||
m_indexSource = new DigitalInput(indexSlot, indexChannel);
|
||||
initEncoder(reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b modules and
|
||||
* channels fully specified. Using the index pulse forces 4x encoding.
|
||||
*
|
||||
* @param aSlot
|
||||
* The a channel digital input module.
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bSlot
|
||||
* The b channel digital input module.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
* @param indexSlot
|
||||
* The index channel digital input module.
|
||||
* @param indexChannel
|
||||
* The index channel digital input channel.
|
||||
*/
|
||||
public Encoder(final int aSlot, final int aChannel, final int bSlot,
|
||||
final int bChannel, final int indexSlot, final int indexChannel) {
|
||||
this(aSlot, aChannel, bSlot, bChannel, indexSlot, indexChannel, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels assuming
|
||||
* the default module.
|
||||
*
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
* @param reverseDirection
|
||||
* represents the orientation of the encoder and inverts the
|
||||
* output values if necessary so forward represents positive
|
||||
* values.
|
||||
*/
|
||||
public Encoder(final int aChannel, final int bChannel,
|
||||
boolean reverseDirection) {
|
||||
m_allocatedA = true;
|
||||
m_allocatedB = true;
|
||||
m_allocatedI = false;
|
||||
m_aSource = new DigitalInput(aChannel);
|
||||
m_bSource = new DigitalInput(bChannel);
|
||||
initEncoder(reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels assuming
|
||||
* the default module.
|
||||
*
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
*/
|
||||
public Encoder(final int aChannel, final int bChannel) {
|
||||
this(aChannel, bChannel, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels assuming
|
||||
* the default module.
|
||||
*
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
* @param reverseDirection
|
||||
* represents the orientation of the encoder and inverts the
|
||||
* output values if necessary so forward represents positive
|
||||
* values.
|
||||
* @param encodingType
|
||||
* either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If
|
||||
* 4X is selected, then an encoder FPGA object is used and the
|
||||
* returned counts will be 4x the encoder spec'd value since all
|
||||
* rising and falling edges are counted. If 1X or 2X are selected
|
||||
* then a counter object will be used and the returned value will
|
||||
* either exactly match the spec'd count or be double (2x) the
|
||||
* spec'd count.
|
||||
*/
|
||||
public Encoder(final int aChannel, final int bChannel,
|
||||
boolean reverseDirection, final EncodingType encodingType) {
|
||||
m_allocatedA = true;
|
||||
m_allocatedB = true;
|
||||
m_allocatedI = false;
|
||||
if (encodingType == null)
|
||||
throw new NullPointerException("Given encoding type was null");
|
||||
m_encodingType = encodingType;
|
||||
m_aSource = new DigitalInput(aChannel);
|
||||
m_bSource = new DigitalInput(bChannel);
|
||||
initEncoder(reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels assuming
|
||||
* the default module. Using an index pulse forces 4x encoding
|
||||
*
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
* @param indexChannel
|
||||
* The index channel digital input channel.
|
||||
* @param reverseDirection
|
||||
* represents the orientation of the encoder and inverts the
|
||||
* output values if necessary so forward represents positive
|
||||
* values.
|
||||
*/
|
||||
public Encoder(final int aChannel, final int bChannel,
|
||||
final int indexChannel, boolean reverseDirection) {
|
||||
m_allocatedA = true;
|
||||
m_allocatedB = true;
|
||||
m_allocatedI = true;
|
||||
m_aSource = new DigitalInput(aChannel);
|
||||
m_bSource = new DigitalInput(bChannel);
|
||||
m_indexSource = new DigitalInput(indexChannel);
|
||||
initEncoder(reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels assuming
|
||||
* the default module. Using an index pulse forces 4x encoding
|
||||
*
|
||||
* @param aChannel
|
||||
* The a channel digital input channel.
|
||||
* @param bChannel
|
||||
* The b channel digital input channel.
|
||||
* @param indexChannel
|
||||
* The index channel digital input channel.
|
||||
*/
|
||||
public Encoder(final int aChannel, final int bChannel,
|
||||
final int indexChannel) {
|
||||
this(aChannel, bChannel, indexChannel, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels as
|
||||
* digital inputs. This is used in the case where the digital inputs are
|
||||
* shared. The Encoder class will not allocate the digital inputs and assume
|
||||
* that they already are counted.
|
||||
*
|
||||
* @param aSource
|
||||
* The source that should be used for the a channel.
|
||||
* @param bSource
|
||||
* the source that should be used for the b channel.
|
||||
* @param reverseDirection
|
||||
* represents the orientation of the encoder and inverts the
|
||||
* output values if necessary so forward represents positive
|
||||
* values.
|
||||
*/
|
||||
public Encoder(DigitalSource aSource, DigitalSource bSource,
|
||||
boolean reverseDirection) {
|
||||
m_allocatedA = false;
|
||||
m_allocatedB = false;
|
||||
m_allocatedI = false;
|
||||
if (aSource == null)
|
||||
throw new NullPointerException("Digital Source A was null");
|
||||
m_aSource = aSource;
|
||||
if (bSource == null)
|
||||
throw new NullPointerException("Digital Source B was null");
|
||||
m_bSource = bSource;
|
||||
initEncoder(reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels as
|
||||
* digital inputs. This is used in the case where the digital inputs are
|
||||
* shared. The Encoder class will not allocate the digital inputs and assume
|
||||
* that they already are counted.
|
||||
*
|
||||
* @param aSource
|
||||
* The source that should be used for the a channel.
|
||||
* @param bSource
|
||||
* the source that should be used for the b channel.
|
||||
*/
|
||||
public Encoder(DigitalSource aSource, DigitalSource bSource) {
|
||||
this(aSource, bSource, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels as
|
||||
* digital inputs. This is used in the case where the digital inputs are
|
||||
* shared. The Encoder class will not allocate the digital inputs and assume
|
||||
* that they already are counted.
|
||||
*
|
||||
* @param aSource
|
||||
* The source that should be used for the a channel.
|
||||
* @param bSource
|
||||
* the source that should be used for the b channel.
|
||||
* @param reverseDirection
|
||||
* represents the orientation of the encoder and inverts the
|
||||
* output values if necessary so forward represents positive
|
||||
* values.
|
||||
* @param encodingType
|
||||
* either k1X, k2X, or k4X to indicate 1X, 2X or 4X decoding. If
|
||||
* 4X is selected, then an encoder FPGA object is used and the
|
||||
* returned counts will be 4x the encoder spec'd value since all
|
||||
* rising and falling edges are counted. If 1X or 2X are selected
|
||||
* then a counter object will be used and the returned value will
|
||||
* either exactly match the spec'd count or be double (2x) the
|
||||
* spec'd count.
|
||||
*/
|
||||
public Encoder(DigitalSource aSource, DigitalSource bSource,
|
||||
boolean reverseDirection, final EncodingType encodingType) {
|
||||
m_allocatedA = false;
|
||||
m_allocatedB = false;
|
||||
m_allocatedI = false;
|
||||
if (encodingType == null)
|
||||
throw new NullPointerException("Given encoding type was null");
|
||||
m_encodingType = encodingType;
|
||||
if (aSource == null)
|
||||
throw new NullPointerException("Digital Source A was null");
|
||||
m_aSource = aSource;
|
||||
if (bSource == null)
|
||||
throw new NullPointerException("Digital Source B was null");
|
||||
m_aSource = aSource;
|
||||
m_bSource = bSource;
|
||||
initEncoder(reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels as
|
||||
* digital inputs. This is used in the case where the digital inputs are
|
||||
* shared. The Encoder class will not allocate the digital inputs and assume
|
||||
* that they already are counted.
|
||||
*
|
||||
* @param aSource
|
||||
* The source that should be used for the a channel.
|
||||
* @param bSource
|
||||
* the source that should be used for the b channel.
|
||||
* @param indexSource
|
||||
* the source that should be used for the index channel.
|
||||
* @param reverseDirection
|
||||
* represents the orientation of the encoder and inverts the
|
||||
* output values if necessary so forward represents positive
|
||||
* values.
|
||||
*/
|
||||
public Encoder(DigitalSource aSource, DigitalSource bSource,
|
||||
DigitalSource indexSource, boolean reverseDirection) {
|
||||
m_allocatedA = false;
|
||||
m_allocatedB = false;
|
||||
m_allocatedI = false;
|
||||
if (aSource == null)
|
||||
throw new NullPointerException("Digital Source A was null");
|
||||
m_aSource = aSource;
|
||||
if (bSource == null)
|
||||
throw new NullPointerException("Digital Source B was null");
|
||||
m_aSource = aSource;
|
||||
m_bSource = bSource;
|
||||
m_indexSource = indexSource;
|
||||
initEncoder(reverseDirection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encoder constructor. Construct a Encoder given a and b channels as
|
||||
* digital inputs. This is used in the case where the digital inputs are
|
||||
* shared. The Encoder class will not allocate the digital inputs and assume
|
||||
* that they already are counted.
|
||||
*
|
||||
* @param aSource
|
||||
* The source that should be used for the a channel.
|
||||
* @param bSource
|
||||
* the source that should be used for the b channel.
|
||||
* @param indexSource
|
||||
* the source that should be used for the index channel.
|
||||
*/
|
||||
public Encoder(DigitalSource aSource, DigitalSource bSource,
|
||||
DigitalSource indexSource) {
|
||||
this(aSource, bSource, indexSource, false);
|
||||
}
|
||||
|
||||
public void free() {
|
||||
if (m_aSource != null && m_allocatedA) {
|
||||
m_aSource.free();
|
||||
m_allocatedA = false;
|
||||
}
|
||||
if (m_bSource != null && m_allocatedB) {
|
||||
m_bSource.free();
|
||||
m_allocatedB = false;
|
||||
}
|
||||
if (m_indexSource != null && m_allocatedI) {
|
||||
m_indexSource.free();
|
||||
m_allocatedI = false;
|
||||
}
|
||||
|
||||
m_aSource = null;
|
||||
m_bSource = null;
|
||||
m_indexSource = null;
|
||||
if (m_counter != null) {
|
||||
m_counter.free();
|
||||
m_counter = null;
|
||||
} else {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.freeEncoder(m_encoder, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the Encoder. Starts counting pulses on the Encoder device.
|
||||
*/
|
||||
public void start() {
|
||||
if (m_counter != null) {
|
||||
m_counter.start();
|
||||
} else {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.startEncoder(m_encoder, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops counting pulses on the Encoder device. The value is not changed.
|
||||
*/
|
||||
public void stop() {
|
||||
if (m_counter != null) {
|
||||
m_counter.stop();
|
||||
} else {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.stopEncoder(m_encoder, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw value from the encoder. The raw value is the actual count
|
||||
* unscaled by the 1x, 2x, or 4x scale factor.
|
||||
*
|
||||
* @return Current raw count from the encoder
|
||||
*/
|
||||
public int getRaw() {
|
||||
int value;
|
||||
if (m_counter != null) {
|
||||
value = m_counter.get();
|
||||
} else {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
value = HALLibrary.getEncoder(m_encoder, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current count. Returns the current count on the Encoder. This
|
||||
* method compensates for the decoding type.
|
||||
*
|
||||
* @return Current count from the Encoder adjusted for the 1x, 2x, or 4x
|
||||
* scale factor.
|
||||
*/
|
||||
public int get() {
|
||||
return (int) (getRaw() * decodingScaleFactor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the Encoder distance to zero. Resets the current count to zero on
|
||||
* the encoder.
|
||||
*/
|
||||
public void reset() {
|
||||
if (m_counter != null) {
|
||||
m_counter.reset();
|
||||
} else {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.resetEncoder(m_encoder, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the period of the most recent pulse. Returns the period of the
|
||||
* most recent Encoder pulse in seconds. This method compensates for the
|
||||
* decoding type.
|
||||
*
|
||||
* @deprecated Use getRate() in favor of this method. This returns unscaled
|
||||
* periods and getRate() scales using value from
|
||||
* setDistancePerPulse().
|
||||
*
|
||||
* @return Period in seconds of the most recent pulse.
|
||||
*/
|
||||
public double getPeriod() {
|
||||
double measuredPeriod;
|
||||
if (m_counter != null) {
|
||||
measuredPeriod = m_counter.getPeriod();
|
||||
} else {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
measuredPeriod = HALLibrary.getEncoderPeriod(m_encoder, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
return measuredPeriod / decodingScaleFactor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum period for stopped detection. Sets the value that
|
||||
* represents the maximum period of the Encoder before it will assume that
|
||||
* the attached device is stopped. This timeout allows users to determine if
|
||||
* the wheels or other shaft has stopped rotating. This method compensates
|
||||
* for the decoding type.
|
||||
*
|
||||
*
|
||||
* @param maxPeriod
|
||||
* The maximum time between rising and falling edges before the
|
||||
* FPGA will report the device stopped. This is expressed in
|
||||
* seconds.
|
||||
*/
|
||||
public void setMaxPeriod(double maxPeriod) {
|
||||
if (m_counter != null) {
|
||||
m_counter.setMaxPeriod(maxPeriod * decodingScaleFactor());
|
||||
} else {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary
|
||||
.setEncoderMaxPeriod(m_encoder, (float) maxPeriod, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the encoder is stopped. Using the MaxPeriod value, a boolean
|
||||
* is returned that is true if the encoder is considered stopped and false
|
||||
* if it is still moving. A stopped encoder is one where the most recent
|
||||
* pulse width exceeds the MaxPeriod.
|
||||
*
|
||||
* @return True if the encoder is considered stopped.
|
||||
*/
|
||||
public boolean getStopped() {
|
||||
if (m_counter != null) {
|
||||
return m_counter.getStopped();
|
||||
} else {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getEncoderStopped(m_encoder, status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The last direction the encoder value changed.
|
||||
*
|
||||
* @return The last direction the encoder value changed.
|
||||
*/
|
||||
public boolean getDirection() {
|
||||
if (m_counter != null) {
|
||||
return m_counter.getDirection();
|
||||
} else {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getEncoderDirection(m_encoder, status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The scale needed to convert a raw counter value into a number of encoder
|
||||
* pulses.
|
||||
*/
|
||||
private double decodingScaleFactor() {
|
||||
switch (m_encodingType.value) {
|
||||
case EncodingType.k1X_val:
|
||||
return 1.0;
|
||||
case EncodingType.k2X_val:
|
||||
return 0.5;
|
||||
case EncodingType.k4X_val:
|
||||
return 0.25;
|
||||
default:
|
||||
// This is never reached, EncodingType enum limits values
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance the robot has driven since the last reset.
|
||||
*
|
||||
* @return The distance driven since the last reset as scaled by the value
|
||||
* from setDistancePerPulse().
|
||||
*/
|
||||
public double getDistance() {
|
||||
return getRaw() * decodingScaleFactor() * m_distancePerPulse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current rate of the encoder. Units are distance per second as
|
||||
* scaled by the value from setDistancePerPulse().
|
||||
*
|
||||
* @return The current rate of the encoder.
|
||||
*/
|
||||
public double getRate() {
|
||||
return m_distancePerPulse / getPeriod();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum rate of the device before the hardware reports it
|
||||
* stopped.
|
||||
*
|
||||
* @param minRate
|
||||
* The minimum rate. The units are in distance per second as
|
||||
* scaled by the value from setDistancePerPulse().
|
||||
*/
|
||||
public void setMinRate(double minRate) {
|
||||
setMaxPeriod(m_distancePerPulse / minRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the distance per pulse for this encoder. This sets the multiplier
|
||||
* used to determine the distance driven based on the count value from the
|
||||
* encoder. Do not include the decoding type in this scale. The library
|
||||
* already compensates for the decoding type. Set this value based on the
|
||||
* encoder's rated Pulses per Revolution and factor in gearing reductions
|
||||
* following the encoder shaft. This distance can be in any units you like,
|
||||
* linear or angular.
|
||||
*
|
||||
* @param distancePerPulse
|
||||
* The scale factor that will be used to convert pulses to useful
|
||||
* units.
|
||||
*/
|
||||
public void setDistancePerPulse(double distancePerPulse) {
|
||||
m_distancePerPulse = distancePerPulse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param reverseDirection
|
||||
* true if the encoder direction should be reversed
|
||||
*/
|
||||
public void setReverseDirection(boolean reverseDirection) {
|
||||
if (m_counter != null) {
|
||||
m_counter.setReverseDirection(reverseDirection);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Samples to Average which specifies the number of samples of the
|
||||
* timer to average when calculating the period. Perform averaging to
|
||||
* account for mechanical imperfections or as oversampling to increase
|
||||
* resolution.
|
||||
*
|
||||
* TODO: Should this throw a checked exception, so that the user has to deal
|
||||
* with giving an incorrect value?
|
||||
*
|
||||
* @param samplesToAverage
|
||||
* The number of samples to average from 1 to 127.
|
||||
*/
|
||||
public void setSamplesToAverage(int samplesToAverage) {
|
||||
switch (m_encodingType.value) {
|
||||
case EncodingType.k4X_val:
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setEncoderSamplesToAverage(m_encoder, samplesToAverage,
|
||||
status);
|
||||
if (status.get() == HALLibrary.PARAMETER_OUT_OF_RANGE) {
|
||||
throw new BoundaryException(BoundaryException.getMessage(
|
||||
samplesToAverage, 1, 127));
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
break;
|
||||
case EncodingType.k1X_val:
|
||||
case EncodingType.k2X_val:
|
||||
m_counter.setSamplesToAverage(samplesToAverage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Samples to Average which specifies the number of samples of the
|
||||
* timer to average when calculating the period. Perform averaging to
|
||||
* account for mechanical imperfections or as oversampling to increase
|
||||
* resolution.
|
||||
*
|
||||
* @return SamplesToAverage The number of samples being averaged (from 1 to
|
||||
* 127)
|
||||
*/
|
||||
public int getSamplesToAverage() {
|
||||
switch (m_encodingType.value) {
|
||||
case EncodingType.k4X_val:
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary
|
||||
.getEncoderSamplesToAverage(m_encoder, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
case EncodingType.k1X_val:
|
||||
case EncodingType.k2X_val:
|
||||
return m_counter.getSamplesToAverage();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set which parameter of the encoder you are using as a process control
|
||||
* variable. The encoder class supports the rate and distance parameters.
|
||||
*
|
||||
* @param pidSource
|
||||
* An enum to select the parameter.
|
||||
*/
|
||||
public void setPIDSourceParameter(PIDSourceParameter pidSource) {
|
||||
BoundaryException.assertWithinBounds(pidSource.value, 0, 1);
|
||||
m_pidSource = pidSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement the PIDSource interface.
|
||||
*
|
||||
* @return The current value of the selected source parameter.
|
||||
*/
|
||||
public double pidGet() {
|
||||
switch (m_pidSource.value) {
|
||||
case PIDSourceParameter.kDistance_val:
|
||||
return getDistance();
|
||||
case PIDSourceParameter.kRate_val:
|
||||
return getRate();
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
switch (m_encodingType.value) {
|
||||
case EncodingType.k4X_val:
|
||||
return "Quadrature Encoder";
|
||||
default:
|
||||
return "Encoder";
|
||||
}
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Speed", getRate());
|
||||
m_table.putNumber("Distance", getDistance());
|
||||
m_table.putNumber("Distance per Tick", m_distancePerPulse);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.parsing.ISensor;
|
||||
|
||||
/**
|
||||
* Alias for counter class.
|
||||
* Implement the gear tooth sensor supplied by FIRST. Currently there is no reverse sensing on
|
||||
* the gear tooth sensor, but in future versions we might implement the necessary timing in the
|
||||
* FPGA to sense direction.
|
||||
*/
|
||||
public class GearTooth extends Counter implements ISensor {
|
||||
|
||||
private static final double kGearToothThreshold = 55e-6;
|
||||
|
||||
/**
|
||||
* Common code called by the constructors.
|
||||
*/
|
||||
public void enableDirectionSensing(boolean directionSensitive) {
|
||||
if (directionSensitive) {
|
||||
setPulseLengthMode(kGearToothThreshold);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GearTooth sensor given a channel.
|
||||
*
|
||||
* The default module is assumed.
|
||||
*
|
||||
* @param channel The GPIO channel on the digital module that the sensor is connected to.
|
||||
* @param directionSensitive Enable the pulse length decoding in hardware to specify count direction.
|
||||
*/
|
||||
public GearTooth(final int channel, boolean directionSensitive) {
|
||||
super(channel);
|
||||
enableDirectionSensing(directionSensitive);
|
||||
if(directionSensitive) {
|
||||
UsageReporting.report(tResourceType.kResourceType_GearTooth, channel, DigitalModule.getDefaultDigitalModule()-1, "D");
|
||||
} else {
|
||||
UsageReporting.report(tResourceType.kResourceType_GearTooth, channel, DigitalModule.getDefaultDigitalModule()-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GearTooth sensor given a channel.
|
||||
*
|
||||
* The default module is assumed.
|
||||
* No direction sensing is assumed.
|
||||
*
|
||||
* @param channel The GPIO channel on the digital module that the sensor is connected to.
|
||||
*/
|
||||
public GearTooth(final int channel) {
|
||||
this(channel,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GearTooth sensor given a channel and module.
|
||||
*
|
||||
* @param slot The slot in the chassis that the digital module is plugged in to.
|
||||
* @param channel The GPIO channel on the digital module that the sensor is connected to.
|
||||
* @param directionSensitive Enable the pulse length decoding in hardware to specify count direction.
|
||||
*/
|
||||
public GearTooth(final int slot, final int channel, boolean directionSensitive) {
|
||||
super(slot, channel);
|
||||
enableDirectionSensing(directionSensitive);
|
||||
if(directionSensitive) {
|
||||
UsageReporting.report(tResourceType.kResourceType_GearTooth, channel, DigitalModule.getDefaultDigitalModule()-1, "D");
|
||||
} else {
|
||||
UsageReporting.report(tResourceType.kResourceType_GearTooth, channel, DigitalModule.getDefaultDigitalModule()-1);
|
||||
}
|
||||
LiveWindow.addSensor("GearTooth", slot, channel, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GearTooth sensor given a channel and module.
|
||||
*
|
||||
* No direction sensing is assumed.
|
||||
*
|
||||
* @param slot The slot in the chassis that the digital module is plugged in to.
|
||||
* @param channel The GPIO channel on the digital module that the sensor is connected to.
|
||||
*/
|
||||
public GearTooth(final int slot, final int channel) {
|
||||
this(slot, channel,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GearTooth sensor given a digital input.
|
||||
* This should be used when sharing digial inputs.
|
||||
*
|
||||
* @param source An object that fully descibes the input that the sensor is connected to.
|
||||
* @param directionSensitive Enable the pulse length decoding in hardware to specify count direction.
|
||||
*/
|
||||
public GearTooth(DigitalSource source, boolean directionSensitive) {
|
||||
super(source);
|
||||
enableDirectionSensing(directionSensitive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GearTooth sensor given a digital input.
|
||||
* This should be used when sharing digial inputs.
|
||||
*
|
||||
* No direction sensing is assumed.
|
||||
*
|
||||
* @param source An object that fully descibes the input that the sensor is connected to.
|
||||
*/
|
||||
public GearTooth(DigitalSource source) {
|
||||
this(source,false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Gear Tooth";
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
* GenericHID Interface
|
||||
*/
|
||||
public abstract class GenericHID {
|
||||
|
||||
/**
|
||||
* Which hand the Human Interface Device is associated with.
|
||||
*/
|
||||
public static class Hand {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kLeft_val = 0;
|
||||
static final int kRight_val = 1;
|
||||
/**
|
||||
* hand: left
|
||||
*/
|
||||
public static final Hand kLeft = new Hand(kLeft_val);
|
||||
/**
|
||||
* hand: right
|
||||
*/
|
||||
public static final Hand kRight = new Hand(kRight_val);
|
||||
|
||||
private Hand(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the x position of the HID
|
||||
* @return the x position of the HID
|
||||
*/
|
||||
public final double getX() {
|
||||
return getX(Hand.kRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the x position of HID
|
||||
* @param hand which hand, left or right
|
||||
* @return the x position
|
||||
*/
|
||||
public abstract double getX(Hand hand);
|
||||
|
||||
/**
|
||||
* Get the y position of the HID
|
||||
* @return the y position
|
||||
*/
|
||||
public final double getY() {
|
||||
return getY(Hand.kRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the y position of the HID
|
||||
* @param hand which hand, left or right
|
||||
* @return the y position
|
||||
*/
|
||||
public abstract double getY(Hand hand);
|
||||
|
||||
/**
|
||||
* Get the z position of the HID
|
||||
* @return the z position
|
||||
*/
|
||||
public final double getZ() {
|
||||
return getZ(Hand.kRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the z position of the HID
|
||||
* @param hand which hand, left or right
|
||||
* @return the z position
|
||||
*/
|
||||
public abstract double getZ(Hand hand);
|
||||
|
||||
/**
|
||||
* Get the twist value
|
||||
* @return the twist value
|
||||
*/
|
||||
public abstract double getTwist();
|
||||
|
||||
/**
|
||||
* Get the throttle
|
||||
* @return the throttle value
|
||||
*/
|
||||
public abstract double getThrottle();
|
||||
|
||||
/**
|
||||
* Get the raw axis
|
||||
* @param which index of the axis
|
||||
* @return the raw value of the selected axis
|
||||
*/
|
||||
public abstract double getRawAxis(int which);
|
||||
|
||||
/**
|
||||
* Is the trigger pressed
|
||||
* @return true if pressed
|
||||
*/
|
||||
public final boolean getTrigger() {
|
||||
return getTrigger(Hand.kRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the trigger pressed
|
||||
* @param hand which hand
|
||||
* @return true if the trigger for the given hand is pressed
|
||||
*/
|
||||
public abstract boolean getTrigger(Hand hand);
|
||||
|
||||
/**
|
||||
* Is the top button pressed
|
||||
* @return true if the top button is pressed
|
||||
*/
|
||||
public final boolean getTop() {
|
||||
return getTop(Hand.kRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the top button pressed
|
||||
* @param hand which hand
|
||||
* @return true if hte top button for the given hand is pressed
|
||||
*/
|
||||
public abstract boolean getTop(Hand hand);
|
||||
|
||||
/**
|
||||
* Is the bumper pressed
|
||||
* @return true if the bumper is pressed
|
||||
*/
|
||||
public final boolean getBumper() {
|
||||
return getBumper(Hand.kRight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the bumper pressed
|
||||
* @param hand which hand
|
||||
* @return true if hte bumper is pressed
|
||||
*/
|
||||
public abstract boolean getBumper(Hand hand);
|
||||
|
||||
/**
|
||||
* Is the given button pressed
|
||||
* @param button which button number
|
||||
* @return true if the button is pressed
|
||||
*/
|
||||
public abstract boolean getRawButton(int button);
|
||||
}
|
||||
@@ -1,290 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.ISensor;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
|
||||
/**
|
||||
* Use a rate gyro to return the robots heading relative to a starting position.
|
||||
* The Gyro class tracks the robots heading based on the starting position. As
|
||||
* the robot rotates the new heading is computed by integrating the rate of
|
||||
* rotation returned by the sensor. When the class is instantiated, it does a
|
||||
* short calibration routine where it samples the gyro while at rest to
|
||||
* determine the default offset. This is subtracted from each sample to
|
||||
* determine the heading.
|
||||
*/
|
||||
public class Gyro extends SensorBase implements PIDSource, ISensor,
|
||||
LiveWindowSendable {
|
||||
|
||||
static final int kOversampleBits = 10;
|
||||
static final int kAverageBits = 0;
|
||||
static final double kSamplesPerSecond = 50.0;
|
||||
static final double kCalibrationSampleTime = 5.0;
|
||||
static final double kDefaultVoltsPerDegreePerSecond = 0.007;
|
||||
AnalogChannel m_analog;
|
||||
double m_voltsPerDegreePerSecond;
|
||||
double m_offset;
|
||||
int m_center;
|
||||
boolean m_channelAllocated;
|
||||
AccumulatorResult result;
|
||||
private PIDSourceParameter m_pidSource;
|
||||
|
||||
/**
|
||||
* Initialize the gyro. Calibrate the gyro by running for a number of
|
||||
* samples and computing the center value for this part. Then use the center
|
||||
* value as the Accumulator center value for subsequent measurements. It's
|
||||
* important to make sure that the robot is not moving while the centering
|
||||
* calculations are in progress, this is typically done when the robot is
|
||||
* first turned on while it's sitting at rest before the competition starts.
|
||||
*/
|
||||
private void initGyro() {
|
||||
result = new AccumulatorResult();
|
||||
if (m_analog == null) {
|
||||
System.out.println("Null m_analog");
|
||||
}
|
||||
m_voltsPerDegreePerSecond = kDefaultVoltsPerDegreePerSecond;
|
||||
m_analog.setAverageBits(kAverageBits);
|
||||
m_analog.setOversampleBits(kOversampleBits);
|
||||
double sampleRate = kSamplesPerSecond
|
||||
* (1 << (kAverageBits + kOversampleBits));
|
||||
m_analog.setSampleRate(sampleRate);
|
||||
|
||||
Timer.delay(1.0);
|
||||
m_analog.initAccumulator();
|
||||
|
||||
Timer.delay(kCalibrationSampleTime);
|
||||
|
||||
m_analog.getAccumulatorOutput(result);
|
||||
|
||||
m_center = (int) ((double) result.value / (double) result.count + .5);
|
||||
|
||||
m_offset = ((double) result.value / (double) result.count)
|
||||
- (double) m_center;
|
||||
|
||||
m_analog.setAccumulatorCenter(m_center);
|
||||
|
||||
m_analog.setAccumulatorDeadband(0); // /< TODO: compute / parameterize
|
||||
// this
|
||||
m_analog.resetAccumulator();
|
||||
|
||||
setPIDSourceParameter(PIDSourceParameter.kAngle);
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Gyro,
|
||||
m_analog.getChannel(), m_analog.getModuleNumber() - 1);
|
||||
LiveWindow.addSensor("Gyro", m_analog.getModuleNumber(),
|
||||
m_analog.getChannel(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gyro constructor given a slot and a channel. .
|
||||
*
|
||||
* @param slot
|
||||
* The cRIO slot for the analog module the gyro is connected to.
|
||||
* @param channel
|
||||
* The analog channel the gyro is connected to.
|
||||
*/
|
||||
public Gyro(int slot, int channel) {
|
||||
m_analog = new AnalogChannel(slot, channel);
|
||||
m_channelAllocated = true;
|
||||
initGyro();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gyro constructor with only a channel.
|
||||
*
|
||||
* Use the default analog module slot.
|
||||
*
|
||||
* @param channel
|
||||
* The analog channel the gyro is connected to.
|
||||
*/
|
||||
public Gyro(int channel) {
|
||||
m_analog = new AnalogChannel(channel);
|
||||
m_channelAllocated = true;
|
||||
initGyro();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gyro constructor with a precreated analog channel object. Use this
|
||||
* constructor when the analog channel needs to be shared. There is no
|
||||
* reference counting when an AnalogChannel is passed to the gyro.
|
||||
*
|
||||
* @param channel
|
||||
* The AnalogChannel object that the gyro is connected to.
|
||||
*/
|
||||
public Gyro(AnalogChannel channel) {
|
||||
m_analog = channel;
|
||||
if (m_analog == null) {
|
||||
System.err
|
||||
.println("Analog channel supplied to Gyro constructor is null");
|
||||
} else {
|
||||
m_channelAllocated = false;
|
||||
initGyro();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the gyro. Resets the gyro to a heading of zero. This can be used if
|
||||
* there is significant drift in the gyro and it needs to be recalibrated
|
||||
* after it has been running.
|
||||
*/
|
||||
public void reset() {
|
||||
if (m_analog != null) {
|
||||
m_analog.resetAccumulator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete (free) the accumulator and the analog components used for the
|
||||
* gyro.
|
||||
*/
|
||||
public void free() {
|
||||
if (m_analog != null && m_channelAllocated) {
|
||||
m_analog.free();
|
||||
}
|
||||
m_analog = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the actual angle in degrees that the robot is currently facing.
|
||||
*
|
||||
* The angle is based on the current accumulator value corrected by the
|
||||
* oversampling rate, the gyro type and the A/D calibration values. The
|
||||
* angle is continuous, that is can go beyond 360 degrees. This make
|
||||
* algorithms that wouldn't want to see a discontinuity in the gyro output
|
||||
* as it sweeps past 0 on the second time around.
|
||||
*
|
||||
* @return the current heading of the robot in degrees. This heading is
|
||||
* based on integration of the returned rate from the gyro.
|
||||
*/
|
||||
public double getAngle() {
|
||||
if (m_analog == null) {
|
||||
return 0.0;
|
||||
} else {
|
||||
m_analog.getAccumulatorOutput(result);
|
||||
|
||||
long value = result.value - (long) (result.count * m_offset);
|
||||
|
||||
double scaledValue = value
|
||||
* 1e-9
|
||||
* m_analog.getLSBWeight()
|
||||
* (1 << m_analog.getAverageBits())
|
||||
/ (m_analog.getModule().getSampleRate() * m_voltsPerDegreePerSecond);
|
||||
|
||||
return scaledValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rate of rotation of the gyro
|
||||
*
|
||||
* The rate is based on the most recent reading of the gyro analog value
|
||||
*
|
||||
* @return the current rate in degrees per second
|
||||
*/
|
||||
public double getRate() {
|
||||
if (m_analog == null) {
|
||||
return 0.0;
|
||||
} else {
|
||||
return (m_analog.getAverageValue() - ((double) m_center + m_offset))
|
||||
* 1e-9
|
||||
* m_analog.getLSBWeight()
|
||||
/ ((1 << m_analog.getOversampleBits()) * m_voltsPerDegreePerSecond);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the gyro type based on the sensitivity. This takes the number of
|
||||
* volts/degree/second sensitivity of the gyro and uses it in subsequent
|
||||
* calculations to allow the code to work with multiple gyros.
|
||||
*
|
||||
* @param voltsPerDegreePerSecond
|
||||
* The type of gyro specified as the voltage that represents one
|
||||
* degree/second.
|
||||
*/
|
||||
public void setSensitivity(double voltsPerDegreePerSecond) {
|
||||
m_voltsPerDegreePerSecond = voltsPerDegreePerSecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set which parameter of the encoder you are using as a process control
|
||||
* variable. The Gyro class supports the rate and angle parameters
|
||||
*
|
||||
* @param pidSource
|
||||
* An enum to select the parameter.
|
||||
*/
|
||||
public void setPIDSourceParameter(PIDSourceParameter pidSource) {
|
||||
BoundaryException.assertWithinBounds(pidSource.value, 1, 2);
|
||||
m_pidSource = pidSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the angle of the gyro for use with PIDControllers
|
||||
*
|
||||
* @return the current angle according to the gyro
|
||||
*/
|
||||
public double pidGet() {
|
||||
switch (m_pidSource.value) {
|
||||
case PIDSourceParameter.kRate_val:
|
||||
return getRate();
|
||||
case PIDSourceParameter.kAngle_val:
|
||||
return getAngle();
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Gyro";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getAngle());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
}
|
||||
@@ -1,385 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.ISensor;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
* HiTechnic NXT Color Sensor.
|
||||
*
|
||||
* This class allows access to a HiTechnic NXT Color Sensor on an I2C bus.
|
||||
* These sensors do not allow changing addresses so you cannot have more
|
||||
* than one on a single bus.
|
||||
*
|
||||
* Details on the sensor can be found here:
|
||||
* http://www.hitechnic.com/index.html?lang=en-us&target=d17.html
|
||||
*
|
||||
*/
|
||||
public class HiTechnicColorSensor extends SensorBase implements ISensor, LiveWindowSendable {
|
||||
|
||||
/**
|
||||
* An exception dealing with connecting to and communicating with the
|
||||
* HiTechnicCompass
|
||||
*/
|
||||
public class ColorSensorException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new exception with the given message
|
||||
* @param message the message to pass with the exception
|
||||
*/
|
||||
public ColorSensorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of three color values bundled into one object
|
||||
*/
|
||||
public class RGB {
|
||||
public double red, green, blue;
|
||||
|
||||
public double getRed() {
|
||||
return red;
|
||||
}
|
||||
public double getGreen() {
|
||||
return green;
|
||||
}
|
||||
public double getBlue() {
|
||||
return blue;
|
||||
}
|
||||
}
|
||||
|
||||
public static class tColorSensorMode {
|
||||
public final int value;
|
||||
static final int kActive_val = 0;
|
||||
static final int kPassive_val = 1;
|
||||
static final int kRaw_val = 3;
|
||||
public static final tColorSensorMode kActive = new tColorSensorMode(kActive_val);
|
||||
public static final tColorSensorMode kPassive = new tColorSensorMode(kPassive_val);
|
||||
public static final tColorSensorMode kRaw = new tColorSensorMode(kRaw_val);
|
||||
|
||||
private tColorSensorMode(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static final byte kAddress = 0x02;
|
||||
private static final byte kManufacturerBaseRegister = 0x08;
|
||||
private static final byte kManufacturerSize = 0x08;
|
||||
private static final byte kSensorTypeBaseRegister = 0x10;
|
||||
private static final byte kSensorTypeSize = 0x08;
|
||||
private static final byte kModeRegister = 0x41;
|
||||
private static final byte kColorRegister = 0x42;
|
||||
private static final byte kRedRegister = 0x43;
|
||||
private static final byte kGreenRegister = 0x44;
|
||||
private static final byte kBlueRegister = 0x45;
|
||||
private static final byte kRawRedRegister = 0x43;
|
||||
private static final byte kRawGreenRegister = 0x45;
|
||||
private static final byte kRawBlueRegister = 0x47;
|
||||
private I2C m_i2c;
|
||||
private int m_mode = tColorSensorMode.kActive.value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param slot The slot of the digital module that the sensor is plugged into.
|
||||
*/
|
||||
public HiTechnicColorSensor(int slot) {
|
||||
DigitalModule module = DigitalModule.getInstance(slot);
|
||||
m_i2c = module.getI2C(kAddress);
|
||||
|
||||
// Verify Sensor
|
||||
final byte[] kExpectedManufacturer = "HiTechnc".getBytes();
|
||||
final byte[] kExpectedSensorType = "ColorPD ".getBytes();
|
||||
if (!m_i2c.verifySensor(kManufacturerBaseRegister, kManufacturerSize, kExpectedManufacturer)) {
|
||||
throw new ColorSensorException("Invalid Color Sensor Manufacturer");
|
||||
}
|
||||
if (!m_i2c.verifySensor(kSensorTypeBaseRegister, kSensorTypeSize, kExpectedSensorType)) {
|
||||
throw new ColorSensorException("Invalid Sensor type");
|
||||
}
|
||||
|
||||
LiveWindow.addSensor("HiTechnicColorSensor", slot, 0, this);
|
||||
UsageReporting.report(tResourceType.kResourceType_HiTechnicColorSensor, module.getModuleNumber()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public void free() {
|
||||
if (m_i2c != null) {
|
||||
m_i2c.free();
|
||||
}
|
||||
m_i2c = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the estimated color.
|
||||
*
|
||||
* Gets a color estimate from the sensor corresponding to the
|
||||
* table found with the sensor or at the following site:
|
||||
* http://www.hitechnic.com/cgi-bin/commerce.cgi?preadd=action&key=NCO1038
|
||||
*
|
||||
* @return The estimated color.
|
||||
*/
|
||||
public byte getColor() {
|
||||
byte[] color = new byte[1];
|
||||
if(m_mode != tColorSensorMode.kActive.value) {
|
||||
setMode(tColorSensorMode.kActive);
|
||||
}
|
||||
m_i2c.read(kColorRegister, (byte) color.length, color);
|
||||
|
||||
return color[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of all three colors from a single sensor reading.
|
||||
* Using this method ensures that all three values come from the
|
||||
* same sensor reading, using the individual color methods provides
|
||||
* no such guarantee.
|
||||
*
|
||||
* The sensor must be in active mode to access the regular RGB data
|
||||
* if the sensor is not in active mode, it will be placed into active
|
||||
* mode by this method.
|
||||
*
|
||||
* @return RGB object with the three color values
|
||||
*/
|
||||
public RGB getRGB() {
|
||||
byte[] colors = new byte[3];
|
||||
RGB result = new RGB();
|
||||
if(m_mode != tColorSensorMode.kActive.value) {
|
||||
setMode(tColorSensorMode.kActive);
|
||||
}
|
||||
m_i2c.read(kRedRegister, (byte) colors.length, colors);
|
||||
|
||||
result.red = (colors[0]&0xFFFF);
|
||||
result.green = (colors[1]&0xFFFF);
|
||||
result.blue = (colors[2]&0xFFFF);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Red value.
|
||||
*
|
||||
* Gets the (0-255) red value from the sensor.
|
||||
*
|
||||
* The sensor must be in active mode to access the regular RGB data
|
||||
* if the sensor is not in active mode, it will be placed into active
|
||||
* mode by this method.
|
||||
*
|
||||
* @return The Red sensor value.
|
||||
*/
|
||||
public int getRed() {
|
||||
byte[] red = new byte[1];
|
||||
if(m_mode != tColorSensorMode.kActive.value) {
|
||||
setMode(tColorSensorMode.kActive);
|
||||
}
|
||||
m_i2c.read(kRedRegister, (byte) red.length, red);
|
||||
|
||||
return (red[0]&0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Green value.
|
||||
*
|
||||
* Gets the(0-255) green value from the sensor.
|
||||
*
|
||||
* The sensor must be in active mode to access the regular RGB data
|
||||
* if the sensor is not in active mode, it will be placed into active
|
||||
* mode by this method.
|
||||
*
|
||||
* @return The Green sensor value.
|
||||
*/
|
||||
public int getGreen() {
|
||||
byte[] green = new byte[1];
|
||||
if(m_mode != tColorSensorMode.kActive.value) {
|
||||
setMode(tColorSensorMode.kActive);
|
||||
}
|
||||
m_i2c.read(kGreenRegister, (byte) green.length, green);
|
||||
|
||||
return (green[0]&0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Blue value.
|
||||
*
|
||||
* Gets the raw (0-255) blue value from the sensor.
|
||||
*
|
||||
* The sensor must be in active mode to access the regular RGB data
|
||||
* if the sensor is not in active mode, it will be placed into active
|
||||
* mode by this method.
|
||||
*
|
||||
* @return The Blue sensor value.
|
||||
*/
|
||||
public int getBlue() {
|
||||
byte[] blue = new byte[1];
|
||||
if(m_mode != tColorSensorMode.kActive.value) {
|
||||
setMode(tColorSensorMode.kActive);
|
||||
}
|
||||
m_i2c.read(kBlueRegister, (byte) blue.length, blue);
|
||||
|
||||
return (blue[0]&0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Raw Red value.
|
||||
*
|
||||
* Gets the (0-65536) raw red value from the sensor.
|
||||
*
|
||||
* The sensor must be in raw or passive mode to access the regular RGB data
|
||||
* if the sensor is not in raw or passive mode, it will be placed into raw
|
||||
* mode by this method.
|
||||
*
|
||||
* @return The Raw Red sensor value.
|
||||
*/
|
||||
public double getRawRed() {
|
||||
byte[] rawRed = new byte[2];
|
||||
if(m_mode == tColorSensorMode.kActive.value) {
|
||||
setMode(tColorSensorMode.kRaw);
|
||||
}
|
||||
m_i2c.read(kRawRedRegister, (byte) rawRed.length, rawRed);
|
||||
|
||||
return (((int)rawRed[0]&0xFF) * (int) (1 << 8) + ((int)rawRed[1]&0xFF));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Raw Green value.
|
||||
*
|
||||
* Gets the (0-65536) raw green value from the sensor.
|
||||
*
|
||||
* The sensor must be in raw or passive mode to access the regular RGB data
|
||||
* if the sensor is not in raw or passive mode, it will be placed into raw
|
||||
* mode by this method.
|
||||
*
|
||||
* @return The Raw Green sensor value.
|
||||
*/
|
||||
public double getRawGreen() {
|
||||
byte[] rawGreen = new byte[2];
|
||||
if(m_mode == tColorSensorMode.kActive.value) {
|
||||
setMode(tColorSensorMode.kRaw);
|
||||
}
|
||||
m_i2c.read(kRawGreenRegister, (byte) rawGreen.length, rawGreen);
|
||||
|
||||
return (((int)rawGreen[0]&0xFF) * (int) (1 << 8) + ((int)rawGreen[1]&0xFF));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Raw Blue value.
|
||||
*
|
||||
* Gets the (0-65536) raw blue value from the sensor.
|
||||
*
|
||||
* The sensor must be in raw or passive mode to access the regular RGB data
|
||||
* if the sensor is not in raw or passive mode, it will be placed into raw
|
||||
* mode by this method.
|
||||
*
|
||||
* @return The Raw Blue sensor value.
|
||||
*/
|
||||
public double getRawBlue() {
|
||||
byte[] rawBlue = new byte[2];
|
||||
if(m_mode == tColorSensorMode.kActive.value) {
|
||||
setMode(tColorSensorMode.kRaw);
|
||||
}
|
||||
m_i2c.read(kRawBlueRegister, (byte) rawBlue.length, rawBlue);
|
||||
|
||||
return (((int)rawBlue[0]&0xFF) * (int) (1 << 8) + ((int)rawBlue[1]&0xFF));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw value of all three colors from a single sensor reading.
|
||||
* Using this method ensures that all three values come from the
|
||||
* same sensor reading, using the individual color methods provides
|
||||
* no such guarantee.
|
||||
*
|
||||
* Gets the (0-65536) raw color values from the sensor.
|
||||
*
|
||||
* The sensor must be in raw or passive mode to access the regular RGB data
|
||||
* if the sensor is not in raw or passive mode, it will be placed into raw
|
||||
* mode by this method.
|
||||
*
|
||||
* @return An RGB object with the raw sensor values.
|
||||
*/
|
||||
public RGB getRawRGB() {
|
||||
byte[] colors = new byte[6];
|
||||
RGB result = new RGB();
|
||||
if(m_mode == tColorSensorMode.kActive.value) {
|
||||
setMode(tColorSensorMode.kRaw);
|
||||
}
|
||||
m_i2c.read(kRawRedRegister, (byte) colors.length, colors);
|
||||
|
||||
result.red = (((int)colors[0]&0xFF) * (int) (1 << 8) + ((int)colors[1]&0xFF));
|
||||
result.green = (((int)colors[2]&0xFF) * (int) (1 << 8) + ((int)colors[3]&0xFF));
|
||||
result.blue = (((int)colors[4]&0xFF) * (int) (1 << 8) + ((int)colors[5]&0xFF));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Mode of the color sensor
|
||||
* This method is used to set the color sensor to one of the three modes,
|
||||
* active, passive or raw. The sensor defaults to active mode which uses the
|
||||
* internal LED and returns an interpreted color value and 3 8-bit RGB channel
|
||||
* values. Raw mode uses the internal LED and returns 3 16-bit RGB channel values.
|
||||
* Passive mode disables the internal LED and returns 3 16-bit RGB channel values.
|
||||
* @param mode The mode to set
|
||||
*/
|
||||
public void setMode(tColorSensorMode mode) {
|
||||
m_i2c.write(kModeRegister, mode.value);
|
||||
m_mode = mode.value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
* TODO: Should this have its own type?
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Counter";
|
||||
}
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
if(m_mode == tColorSensorMode.kActive.value) {
|
||||
m_table.putNumber("Color", getColor());
|
||||
} else {
|
||||
m_table.putNumber("Color", 99);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.ISensor;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
* HiTechnic NXT Compass.
|
||||
*
|
||||
* This class alows access to a HiTechnic NXT Compass on an I2C bus.
|
||||
* These sensors to not allow changing addresses so you cannot have more
|
||||
* than one on a single bus.
|
||||
*
|
||||
* Details on the sensor can be found here:
|
||||
* http://www.hitechnic.com/index.html?lang=en-us&target=d17.html
|
||||
*
|
||||
*/
|
||||
public class HiTechnicCompass extends SensorBase implements ISensor, LiveWindowSendable {
|
||||
|
||||
/**
|
||||
* An exception dealing with connecting to and communicating with the
|
||||
* HiTechnicCompass
|
||||
*/
|
||||
public class CompassException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new exception with the given message
|
||||
* @param message the message to pass with the exception
|
||||
*/
|
||||
public CompassException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final byte kAddress = 0x02;
|
||||
private static final byte kManufacturerBaseRegister = 0x08;
|
||||
private static final byte kManufacturerSize = 0x08;
|
||||
private static final byte kSensorTypeBaseRegister = 0x10;
|
||||
private static final byte kSensorTypeSize = 0x08;
|
||||
private static final byte kHeadingRegister = 0x44;
|
||||
private I2C m_i2c;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param slot The slot of the digital module that the sensor is plugged into.
|
||||
*/
|
||||
public HiTechnicCompass(int slot) {
|
||||
DigitalModule module = DigitalModule.getInstance(slot);
|
||||
m_i2c = module.getI2C(kAddress);
|
||||
|
||||
// Verify Sensor
|
||||
final byte[] kExpectedManufacturer = "HiTechnc".getBytes();
|
||||
final byte[] kExpectedSensorType = "Compass ".getBytes();
|
||||
if (!m_i2c.verifySensor(kManufacturerBaseRegister, kManufacturerSize, kExpectedManufacturer)) {
|
||||
throw new CompassException("Invalid Compass Manufacturer");
|
||||
}
|
||||
if (!m_i2c.verifySensor(kSensorTypeBaseRegister, kSensorTypeSize, kExpectedSensorType)) {
|
||||
throw new CompassException("Invalid Sensor type");
|
||||
}
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_HiTechnicCompass, module.getModuleNumber()-1);
|
||||
LiveWindow.addSensor("HiTechnicCompass", slot, 0, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public void free() {
|
||||
if (m_i2c != null) {
|
||||
m_i2c.free();
|
||||
}
|
||||
m_i2c = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the compass angle in degrees.
|
||||
*
|
||||
* The resolution of this reading is 1 degree.
|
||||
*
|
||||
* @return Angle of the compass in degrees.
|
||||
*/
|
||||
public double getAngle() {
|
||||
byte[] heading = new byte[2];
|
||||
m_i2c.read(kHeadingRegister, (byte) heading.length, heading);
|
||||
|
||||
return ((int) heading[0] + (int) heading[1] * (int) (1 << 8));
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Compass";
|
||||
}
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getAngle());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
|
||||
/**
|
||||
* I2C bus interface class.
|
||||
*
|
||||
* This class is intended to be used by sensor (and other I2C device) drivers.
|
||||
* It probably should not be used directly.
|
||||
*
|
||||
* It is constructed by calling DigitalModule::GetI2C() on a DigitalModule
|
||||
* object.
|
||||
*/
|
||||
public class I2C extends SensorBase {
|
||||
|
||||
private DigitalModule m_module;
|
||||
private int m_deviceAddress;
|
||||
private boolean m_compatibilityMode;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param module
|
||||
* The Digital Module to which the device is connected.
|
||||
* @param deviceAddress
|
||||
* The address of the device on the I2C bus.
|
||||
*/
|
||||
public I2C(DigitalModule module, int deviceAddress) {
|
||||
if (module == null) {
|
||||
throw new NullPointerException("Digital Module given was null");
|
||||
}
|
||||
m_module = module;
|
||||
m_deviceAddress = deviceAddress;
|
||||
m_compatibilityMode = true;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_I2C, deviceAddress,
|
||||
module.getModuleNumber()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public void free() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic transaction.
|
||||
*
|
||||
* This is a lower-level interface to the I2C hardware giving you more
|
||||
* control over each transaction.
|
||||
*
|
||||
* @param dataToSend
|
||||
* Buffer of data to send as part of the transaction.
|
||||
* @param sendSize
|
||||
* Number of bytes to send as part of the transaction. [0..6]
|
||||
* @param dataReceived
|
||||
* Buffer to read data into.
|
||||
* @param receiveSize
|
||||
* Number of bytes to read from the device. [0..7]
|
||||
* @return Transfer Aborted... false for success, true for aborted.
|
||||
*/
|
||||
public synchronized boolean transaction(byte[] dataToSend, int sendSize,
|
||||
byte[] dataReceived, int receiveSize) {
|
||||
boolean aborted = true;
|
||||
|
||||
ByteBuffer dataToSendBuffer = ByteBuffer.wrap(dataToSend);
|
||||
ByteBuffer dataReceivedBuffer = ByteBuffer.allocate(1);
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
|
||||
aborted = HALLibrary
|
||||
.doI2CTransactionWithModule((byte) m_module.m_moduleNumber,
|
||||
(byte) m_deviceAddress, (byte) (m_compatibilityMode ? 1
|
||||
: 0), dataToSendBuffer, (byte) sendSize,
|
||||
dataReceivedBuffer, (byte) receiveSize, status) != 0;
|
||||
if (status.get() == HALLibrary.PARAMETER_OUT_OF_RANGE) {
|
||||
if (sendSize > 6) {
|
||||
throw new BoundaryException(BoundaryException.getMessage(
|
||||
sendSize, 0, 6));
|
||||
} else if (receiveSize > 7) {
|
||||
throw new BoundaryException(BoundaryException.getMessage(
|
||||
receiveSize, 0, 7));
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
HALLibrary.PARAMETER_OUT_OF_RANGE_MESSAGE);
|
||||
}
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
dataReceivedBuffer.get(dataReceived);
|
||||
return aborted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to address a device on the I2C bus.
|
||||
*
|
||||
* This allows you to figure out if there is a device on the I2C bus that
|
||||
* responds to the address specified in the constructor.
|
||||
*
|
||||
* @return Transfer Aborted... false for success, true for aborted.
|
||||
*/
|
||||
public boolean addressOnly() {
|
||||
return transaction(null, (byte) 0, null, (byte) 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a write transaction with the device.
|
||||
*
|
||||
* Write a single byte to a register on a device and wait until the
|
||||
* transaction is complete.
|
||||
*
|
||||
* @param registerAddress
|
||||
* The address of the register on the device to be written.
|
||||
* @param data
|
||||
* The byte to write to the register on the device.
|
||||
*/
|
||||
public synchronized boolean write(int registerAddress, int data) {
|
||||
byte[] buffer = new byte[2];
|
||||
buffer[0] = (byte) registerAddress;
|
||||
buffer[1] = (byte) data;
|
||||
return transaction(buffer, buffer.length, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a read transaction with the device.
|
||||
*
|
||||
* Read 1 to 7 bytes from a device. Most I2C devices will auto-increment the
|
||||
* register pointer internally allowing you to read up to 7 consecutive
|
||||
* registers on a device in a single transaction.
|
||||
*
|
||||
* @param registerAddress
|
||||
* The register to read first in the transaction.
|
||||
* @param count
|
||||
* The number of bytes to read in the transaction. [1..7]
|
||||
* @param buffer
|
||||
* A pointer to the array of bytes to store the data read from
|
||||
* the device.
|
||||
* @return Transfer Aborted... false for success, true for aborted.
|
||||
*/
|
||||
public boolean read(int registerAddress, int count, byte[] buffer) {
|
||||
BoundaryException.assertWithinBounds(count, 1, 7);
|
||||
if (buffer == null) {
|
||||
throw new NullPointerException("Null return buffer was given");
|
||||
}
|
||||
byte[] registerAddressArray = new byte[1];
|
||||
registerAddressArray[0] = (byte) registerAddress;
|
||||
|
||||
return transaction(registerAddressArray, registerAddressArray.length,
|
||||
buffer, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a broadcast write to all devices on the I2C bus.
|
||||
*
|
||||
* This is not currently implemented!
|
||||
*
|
||||
* @param registerAddress
|
||||
* The register to write on all devices on the bus.
|
||||
* @param data
|
||||
* The value to write to the devices.
|
||||
*/
|
||||
public void broadcast(int registerAddress, int data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* SetCompatabilityMode
|
||||
*
|
||||
* Enables bitwise clock skewing detection. This will reduce the I2C
|
||||
* interface speed, but will allow you to communicate with devices that skew
|
||||
* the clock at abnormal times. Compatability mode is enabled by default.
|
||||
*
|
||||
* @param enable
|
||||
* Enable compatability mode for this sensor or not.
|
||||
*/
|
||||
public void setCompatabilityMode(boolean enable) {
|
||||
m_compatibilityMode = enable;
|
||||
UsageReporting.report(tResourceType.kResourceType_I2C,
|
||||
m_deviceAddress, m_module.getModuleNumber() - 1, "C");
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a device's registers contain expected values.
|
||||
*
|
||||
* Most devices will have a set of registers that contain a known value that
|
||||
* can be used to identify them. This allows an I2C device driver to easily
|
||||
* verify that the device contains the expected value.
|
||||
*
|
||||
* @pre The device must support and be configured to use register
|
||||
* auto-increment.
|
||||
*
|
||||
* @param registerAddress
|
||||
* The base register to start reading from the device.
|
||||
* @param count
|
||||
* The size of the field to be verified.
|
||||
* @param expected
|
||||
* A buffer containing the values expected from the device.
|
||||
* @return true if the sensor was verified to be connected
|
||||
*/
|
||||
public boolean verifySensor(int registerAddress, int count, byte[] expected) {
|
||||
// TODO: Make use of all 7 read bytes
|
||||
byte[] deviceData = new byte[4];
|
||||
for (int i = 0, curRegisterAddress = registerAddress; i < count; i += 4, curRegisterAddress += 4) {
|
||||
int toRead = count - i < 4 ? count - i : 4;
|
||||
// Read the chunk of data. Return false if the sensor does not
|
||||
// respond.
|
||||
if (read(curRegisterAddress, toRead, deviceData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (byte j = 0; j < toRead; j++) {
|
||||
if (deviceData[j] != expected[i + j]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
* Represents a Dashboard which can provide data to be sent by the DriverStation
|
||||
* class.
|
||||
* @author pmalmsten
|
||||
*/
|
||||
public interface IDashboard {
|
||||
/**
|
||||
* Gets a reference to the current data to be sent to the dashboard.
|
||||
* @return Byte array of data.
|
||||
*/
|
||||
public byte[] getBytes();
|
||||
|
||||
/**
|
||||
* Gets the length of the current data to be sent to the
|
||||
* dashboard.
|
||||
* @return The length of the data array to be sent to the dashboard.
|
||||
*/
|
||||
public int getBytesLength();
|
||||
|
||||
/**
|
||||
* If the dashboard had data buffered to be sent, calling this method
|
||||
* will reset the output buffer.
|
||||
*/
|
||||
public void flush();
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary.InterruptHandlerFunction;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
|
||||
/**
|
||||
* Base for sensors to be used with interrupts
|
||||
*/
|
||||
public abstract class InterruptableSensorBase extends SensorBase {
|
||||
|
||||
/**
|
||||
* The interrupt resource
|
||||
*/
|
||||
protected Pointer m_interrupt;
|
||||
/**
|
||||
* The interrupt manager resource
|
||||
*/
|
||||
protected InterruptHandlerFunction m_manager;
|
||||
/**
|
||||
* The index of the interrupt
|
||||
*/
|
||||
protected int m_interruptIndex;
|
||||
/**
|
||||
* Resource manager
|
||||
*/
|
||||
protected static Resource interrupts = new Resource(HALLibrary.interrupt_kNumSystems.get());
|
||||
|
||||
/**
|
||||
* Create a new InterrupatableSensorBase
|
||||
*/
|
||||
public InterruptableSensorBase() {
|
||||
m_manager = null;
|
||||
m_interrupt = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the interrupt
|
||||
*
|
||||
* @param watcher
|
||||
*/
|
||||
public void allocateInterrupts(boolean watcher) {
|
||||
if (!watcher) {
|
||||
throw new IllegalArgumentException(
|
||||
"Interrupt callbacks not yet supported");
|
||||
}
|
||||
// Expects the calling leaf class to allocate an interrupt index.
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
m_interrupt = HALLibrary.initializeInterrupts(m_interruptIndex,
|
||||
(byte) (watcher ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel interrupts on this device. This deallocates all the chipobject
|
||||
* structures and disables any interrupts.
|
||||
*/
|
||||
public void cancelInterrupts() {
|
||||
if (m_interrupt == null || m_manager == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.cleanInterrupts(m_interrupt, status);
|
||||
HALUtil.checkStatus(status);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In synchronous mode, wait for the defined interrupt to occur.
|
||||
*
|
||||
* @param timeout
|
||||
* Timeout in seconds
|
||||
*/
|
||||
public void waitForInterrupt(double timeout) {
|
||||
if (m_interrupt == null || m_manager == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.waitForInterrupt(m_interrupt, (float) timeout, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable interrupts to occur on this input. Interrupts are disabled when
|
||||
* the RequestInterrupt call is made. This gives time to do the setup of the
|
||||
* other options before starting to field interrupts.
|
||||
*/
|
||||
public void enableInterrupts() {
|
||||
if (m_interrupt == null || m_manager == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.enableInterrupts(m_interrupt, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Interrupts without without deallocating structures.
|
||||
*/
|
||||
public void disableInterrupts() {
|
||||
if (m_interrupt == null || m_manager == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.disableInterrupts(m_interrupt, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timestamp for the interrupt that occurred most recently. This
|
||||
* is in the same time domain as getClock().
|
||||
*
|
||||
* @return Timestamp in seconds since boot.
|
||||
*/
|
||||
public double readInterruptTimestamp() {
|
||||
if (m_interrupt == null || m_manager == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
double timestamp = HALLibrary.readInterruptTimestamp(m_interrupt, status);
|
||||
HALUtil.checkStatus(status);
|
||||
return timestamp;
|
||||
}
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tInstances;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* IterativeRobot implements a specific type of Robot Program framework, extending the RobotBase class.
|
||||
*
|
||||
* The IterativeRobot class is intended to be subclassed by a user creating a robot program.
|
||||
*
|
||||
* This class is intended to implement the "old style" default code, by providing
|
||||
* the following functions which are called by the main loop, startCompetition(), at the appropriate times:
|
||||
*
|
||||
* robotInit() -- provide for initialization at robot power-on
|
||||
*
|
||||
* init() functions -- each of the following functions is called once when the
|
||||
* appropriate mode is entered:
|
||||
* - DisabledInit() -- called only when first disabled
|
||||
* - AutonomousInit() -- called each and every time autonomous is entered from another mode
|
||||
* - TeleopInit() -- called each and every time teleop is entered from another mode
|
||||
* - TestInit() -- called each and every time test mode is entered from anothermode
|
||||
*
|
||||
* Periodic() functions -- each of these functions is called iteratively at the
|
||||
* appropriate periodic rate (aka the "slow loop"). The period of
|
||||
* the iterative robot is synced to the driver station control packets,
|
||||
* giving a periodic frequency of about 50Hz (50 times per second).
|
||||
* - disabledPeriodic()
|
||||
* - autonomousPeriodic()
|
||||
* - teleopPeriodic()
|
||||
* - testPeriodoc()
|
||||
*
|
||||
*/
|
||||
public class IterativeRobot extends RobotBase {
|
||||
private boolean m_disabledInitialized;
|
||||
private boolean m_autonomousInitialized;
|
||||
private boolean m_teleopInitialized;
|
||||
private boolean m_testInitialized;
|
||||
|
||||
/**
|
||||
* Constructor for RobotIterativeBase
|
||||
*
|
||||
* The constructor initializes the instance variables for the robot to indicate
|
||||
* the status of initialization for disabled, autonomous, and teleop code.
|
||||
*/
|
||||
public IterativeRobot() {
|
||||
// set status for initialization of disabled, autonomous, and teleop code.
|
||||
m_disabledInitialized = false;
|
||||
m_autonomousInitialized = false;
|
||||
m_teleopInitialized = false;
|
||||
m_testInitialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an alternate "main loop" via startCompetition().
|
||||
*
|
||||
*/
|
||||
public void startCompetition() {
|
||||
UsageReporting.report(tResourceType.kResourceType_Framework, tInstances.kFramework_Iterative);
|
||||
|
||||
robotInit();
|
||||
|
||||
// tracing support:
|
||||
final int TRACE_LOOP_MAX = 100;
|
||||
int loopCount = TRACE_LOOP_MAX;
|
||||
Object marker = null;
|
||||
boolean didDisabledPeriodic = false;
|
||||
boolean didAutonomousPeriodic = false;
|
||||
boolean didTeleopPeriodic = false;
|
||||
boolean didTestPeriodic = false;
|
||||
|
||||
// loop forever, calling the appropriate mode-dependent function
|
||||
LiveWindow.setEnabled(false);
|
||||
while (true) {
|
||||
// Call the appropriate function depending upon the current robot mode
|
||||
if (isDisabled()) {
|
||||
// call DisabledInit() if we are now just entering disabled mode from
|
||||
// either a different mode or from power-on
|
||||
if (!m_disabledInitialized) {
|
||||
LiveWindow.setEnabled(false);
|
||||
disabledInit();
|
||||
m_disabledInitialized = true;
|
||||
// reset the initialization flags for the other modes
|
||||
m_autonomousInitialized = false;
|
||||
m_teleopInitialized = false;
|
||||
m_testInitialized = false;
|
||||
}
|
||||
if (nextPeriodReady()) {
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramDisabled();
|
||||
disabledPeriodic();
|
||||
didDisabledPeriodic = true;
|
||||
}
|
||||
} else if (isTest()) {
|
||||
// call TestInit() if we are now just entering test mode from either
|
||||
// a different mode or from power-on
|
||||
if (!m_testInitialized) {
|
||||
LiveWindow.setEnabled(true);
|
||||
testInit();
|
||||
m_testInitialized = true;
|
||||
m_autonomousInitialized = false;
|
||||
m_teleopInitialized = false;
|
||||
m_disabledInitialized = false;
|
||||
}
|
||||
if (nextPeriodReady()) {
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramTest();
|
||||
testPeriodic();
|
||||
didTestPeriodic = true;
|
||||
}
|
||||
} else if (isAutonomous()) {
|
||||
// call Autonomous_Init() if this is the first time
|
||||
// we've entered autonomous_mode
|
||||
if (!m_autonomousInitialized) {
|
||||
LiveWindow.setEnabled(false);
|
||||
// KBS NOTE: old code reset all PWMs and relays to "safe values"
|
||||
// whenever entering autonomous mode, before calling
|
||||
// "Autonomous_Init()"
|
||||
autonomousInit();
|
||||
m_autonomousInitialized = true;
|
||||
m_testInitialized = false;
|
||||
m_teleopInitialized = false;
|
||||
m_disabledInitialized = false;
|
||||
}
|
||||
if (nextPeriodReady()) {
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramAutonomous();
|
||||
autonomousPeriodic();
|
||||
didAutonomousPeriodic = true;
|
||||
}
|
||||
} else {
|
||||
// call Teleop_Init() if this is the first time
|
||||
// we've entered teleop_mode
|
||||
if (!m_teleopInitialized) {
|
||||
LiveWindow.setEnabled(false);
|
||||
teleopInit();
|
||||
m_teleopInitialized = true;
|
||||
m_testInitialized = false;
|
||||
m_autonomousInitialized = false;
|
||||
m_disabledInitialized = false;
|
||||
}
|
||||
if (nextPeriodReady()) {
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramTeleop();
|
||||
teleopPeriodic();
|
||||
didTeleopPeriodic = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the appropriate next periodic function should be called.
|
||||
* Call the periodic functions whenever a packet is received from the Driver Station, or about every 20ms.
|
||||
*/
|
||||
private boolean nextPeriodReady() {
|
||||
return m_ds.isNewControlData();
|
||||
}
|
||||
|
||||
/* ----------- Overridable initialization code -----------------*/
|
||||
|
||||
/**
|
||||
* Robot-wide initialization code should go here.
|
||||
*
|
||||
* Users should override this method for default Robot-wide initialization which will
|
||||
* be called when the robot is first powered on. It will be called exactly 1 time.
|
||||
*/
|
||||
public void robotInit() {
|
||||
System.out.println("Default IterativeRobot.robotInit() method... Overload me!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization code for disabled mode should go here.
|
||||
*
|
||||
* Users should override this method for initialization code which will be called each time
|
||||
* the robot enters disabled mode.
|
||||
*/
|
||||
public void disabledInit() {
|
||||
System.out.println("Default IterativeRobot.disabledInit() method... Overload me!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization code for autonomous mode should go here.
|
||||
*
|
||||
* Users should override this method for initialization code which will be called each time
|
||||
* the robot enters autonomous mode.
|
||||
*/
|
||||
public void autonomousInit() {
|
||||
System.out.println("Default IterativeRobot.autonomousInit() method... Overload me!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization code for teleop mode should go here.
|
||||
*
|
||||
* Users should override this method for initialization code which will be called each time
|
||||
* the robot enters teleop mode.
|
||||
*/
|
||||
public void teleopInit() {
|
||||
System.out.println("Default IterativeRobot.teleopInit() method... Overload me!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization code for test mode should go here.
|
||||
*
|
||||
* Users should override this method for initialization code which will be called each time
|
||||
* the robot enters test mode.
|
||||
*/
|
||||
public void testInit() {
|
||||
System.out.println("Default IterativeRobot.testInit() method... Overload me!");
|
||||
}
|
||||
|
||||
/* ----------- Overridable periodic code -----------------*/
|
||||
|
||||
private boolean dpFirstRun = true;
|
||||
/**
|
||||
* Periodic code for disabled mode should go here.
|
||||
*
|
||||
* Users should override this method for code which will be called periodically at a regular
|
||||
* rate while the robot is in disabled mode.
|
||||
*/
|
||||
public void disabledPeriodic() {
|
||||
if (dpFirstRun) {
|
||||
System.out.println("Default IterativeRobot.disabledPeriodic() method... Overload me!");
|
||||
dpFirstRun = false;
|
||||
}
|
||||
Timer.delay(0.001);
|
||||
}
|
||||
|
||||
private boolean apFirstRun = true;
|
||||
|
||||
/**
|
||||
* Periodic code for autonomous mode should go here.
|
||||
*
|
||||
* Users should override this method for code which will be called periodically at a regular
|
||||
* rate while the robot is in autonomous mode.
|
||||
*/
|
||||
public void autonomousPeriodic() {
|
||||
if (apFirstRun) {
|
||||
System.out.println("Default IterativeRobot.autonomousPeriodic() method... Overload me!");
|
||||
apFirstRun = false;
|
||||
}
|
||||
Timer.delay(0.001);
|
||||
}
|
||||
|
||||
private boolean tpFirstRun = true;
|
||||
|
||||
/**
|
||||
* Periodic code for teleop mode should go here.
|
||||
*
|
||||
* Users should override this method for code which will be called periodically at a regular
|
||||
* rate while the robot is in teleop mode.
|
||||
*/
|
||||
public void teleopPeriodic() {
|
||||
if (tpFirstRun) {
|
||||
System.out.println("Default IterativeRobot.teleopPeriodic() method... Overload me!");
|
||||
tpFirstRun = false;
|
||||
}
|
||||
Timer.delay(0.001);
|
||||
}
|
||||
|
||||
private boolean tmpFirstRun = true;
|
||||
|
||||
/**
|
||||
* Periodic code for test mode should go here
|
||||
*
|
||||
* Users should override this method for code which will be called periodically at a regular rate
|
||||
* while the robot is in test mode.
|
||||
*/
|
||||
public void testPeriodic() {
|
||||
if (tmpFirstRun) {
|
||||
System.out.println("Default IterativeRobot.testPeriodic() method... Overload me!");
|
||||
tmpFirstRun = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.parsing.IDeviceController;
|
||||
|
||||
/**
|
||||
* VEX Robotics Jaguar Speed Control
|
||||
*/
|
||||
public class Jaguar extends SafePWM implements SpeedController, IDeviceController {
|
||||
|
||||
/**
|
||||
* Common initialization code called by all constructors.
|
||||
*/
|
||||
private void initJaguar() {
|
||||
/*
|
||||
* Input profile defined by Luminary Micro.
|
||||
*
|
||||
* Full reverse ranges from 0.671325ms to 0.6972211ms
|
||||
* Proportional reverse ranges from 0.6972211ms to 1.4482078ms
|
||||
* Neutral ranges from 1.4482078ms to 1.5517922ms
|
||||
* Proportional forward ranges from 1.5517922ms to 2.3027789ms
|
||||
* Full forward ranges from 2.3027789ms to 2.328675ms
|
||||
*/
|
||||
setBounds(2.31, 1.55, 1.507, 1.454, .697);
|
||||
setPeriodMultiplier(PeriodMultiplier.k1X);
|
||||
setRaw(m_centerPwm);
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Jaguar, getChannel(), getModuleNumber()-1);
|
||||
LiveWindow.addActuator("Jaguar", getModuleNumber(), getChannel(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that assumes the default digital module.
|
||||
*
|
||||
* @param channel The PWM channel on the digital module that the Jaguar is attached to.
|
||||
*/
|
||||
public Jaguar(final int channel) {
|
||||
super(channel);
|
||||
initJaguar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that specifies the digital module.
|
||||
*
|
||||
* @param slot The slot in the chassis that the digital module is plugged into.
|
||||
* @param channel The PWM channel on the digital module that the Jaguar is attached to.
|
||||
*/
|
||||
public Jaguar(final int slot, final int channel) {
|
||||
super(slot, channel);
|
||||
initJaguar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value.
|
||||
*
|
||||
* @deprecated For compatibility with CANJaguar
|
||||
*
|
||||
* The PWM value is set using a range of -1.0 to 1.0, appropriately
|
||||
* scaling the value for the FPGA.
|
||||
*
|
||||
* @param speed The speed to set. Value should be between -1.0 and 1.0.
|
||||
* @param syncGroup The update group to add this Set() to, pending UpdateSyncGroup(). If 0, update immediately.
|
||||
*/
|
||||
public void set(double speed, byte syncGroup) {
|
||||
setSpeed(speed);
|
||||
Feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value.
|
||||
*
|
||||
* The PWM value is set using a range of -1.0 to 1.0, appropriately
|
||||
* scaling the value for the FPGA.
|
||||
*
|
||||
* @param speed The speed value between -1.0 and 1.0 to set.
|
||||
*/
|
||||
public void set(double speed) {
|
||||
setSpeed(speed);
|
||||
Feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the recently set value of the PWM.
|
||||
*
|
||||
* @return The most recently set value for the PWM between -1.0 and 1.0.
|
||||
*/
|
||||
public double get() {
|
||||
return getSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write out the PID value as seen in the PIDOutput base object.
|
||||
*
|
||||
* @param output Write out the PWM value as was found in the PIDController
|
||||
*/
|
||||
public void pidWrite(double output) {
|
||||
set(output);
|
||||
}
|
||||
}
|
||||
@@ -1,354 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.parsing.IInputOutput;
|
||||
|
||||
/**
|
||||
* Handle input from standard Joysticks connected to the Driver Station.
|
||||
* This class handles standard input that comes from the Driver Station. Each time a value is requested
|
||||
* the most recent value is returned. There is a single class instance for each joystick and the mapping
|
||||
* of ports to hardware buttons depends on the code in the driver station.
|
||||
*/
|
||||
public class Joystick extends GenericHID implements IInputOutput {
|
||||
|
||||
static final byte kDefaultXAxis = 1;
|
||||
static final byte kDefaultYAxis = 2;
|
||||
static final byte kDefaultZAxis = 3;
|
||||
static final byte kDefaultTwistAxis = 3;
|
||||
static final byte kDefaultThrottleAxis = 4;
|
||||
static final int kDefaultTriggerButton = 1;
|
||||
static final int kDefaultTopButton = 2;
|
||||
|
||||
/**
|
||||
* Represents an analog axis on a joystick.
|
||||
*/
|
||||
public static class AxisType {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kX_val = 0;
|
||||
static final int kY_val = 1;
|
||||
static final int kZ_val = 2;
|
||||
static final int kTwist_val = 3;
|
||||
static final int kThrottle_val = 4;
|
||||
static final int kNumAxis_val = 5;
|
||||
/**
|
||||
* axis: x-axis
|
||||
*/
|
||||
public static final AxisType kX = new AxisType(kX_val);
|
||||
/**
|
||||
* axis: y-axis
|
||||
*/
|
||||
public static final AxisType kY = new AxisType(kY_val);
|
||||
/**
|
||||
* axis: z-axis
|
||||
*/
|
||||
public static final AxisType kZ = new AxisType(kZ_val);
|
||||
/**
|
||||
* axis: twist
|
||||
*/
|
||||
public static final AxisType kTwist = new AxisType(kTwist_val);
|
||||
/**
|
||||
* axis: throttle
|
||||
*/
|
||||
public static final AxisType kThrottle = new AxisType(kThrottle_val);
|
||||
/**
|
||||
* axis: number of axis
|
||||
*/
|
||||
public static final AxisType kNumAxis = new AxisType(kNumAxis_val);
|
||||
|
||||
private AxisType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a digital button on the JoyStick
|
||||
*/
|
||||
public static class ButtonType {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kTrigger_val = 0;
|
||||
static final int kTop_val = 1;
|
||||
static final int kNumButton_val = 2;
|
||||
/**
|
||||
* button: trigger
|
||||
*/
|
||||
public static final ButtonType kTrigger = new ButtonType((kTrigger_val));
|
||||
/**
|
||||
* button: top button
|
||||
*/
|
||||
public static final ButtonType kTop = new ButtonType(kTop_val);
|
||||
/**
|
||||
* button: num button types
|
||||
*/
|
||||
public static final ButtonType kNumButton = new ButtonType((kNumButton_val));
|
||||
|
||||
private ButtonType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
private DriverStation m_ds;
|
||||
private final int m_port;
|
||||
private final byte[] m_axes;
|
||||
private final byte[] m_buttons;
|
||||
|
||||
/**
|
||||
* Construct an instance of a joystick.
|
||||
* The joystick index is the usb port on the drivers station.
|
||||
*
|
||||
* @param port The port on the driver station that the joystick is plugged into.
|
||||
*/
|
||||
public Joystick(final int port) {
|
||||
this(port, AxisType.kNumAxis.value, ButtonType.kNumButton.value);
|
||||
|
||||
m_axes[AxisType.kX.value] = kDefaultXAxis;
|
||||
m_axes[AxisType.kY.value] = kDefaultYAxis;
|
||||
m_axes[AxisType.kZ.value] = kDefaultZAxis;
|
||||
m_axes[AxisType.kTwist.value] = kDefaultTwistAxis;
|
||||
m_axes[AxisType.kThrottle.value] = kDefaultThrottleAxis;
|
||||
|
||||
m_buttons[ButtonType.kTrigger.value] = kDefaultTriggerButton;
|
||||
m_buttons[ButtonType.kTop.value] = kDefaultTopButton;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Joystick, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected version of the constructor to be called by sub-classes.
|
||||
*
|
||||
* This constructor allows the subclass to configure the number of constants
|
||||
* for axes and buttons.
|
||||
*
|
||||
* @param port The port on the driver station that the joystick is plugged into.
|
||||
* @param numAxisTypes The number of axis types in the enum.
|
||||
* @param numButtonTypes The number of button types in the enum.
|
||||
*/
|
||||
protected Joystick(int port, int numAxisTypes, int numButtonTypes) {
|
||||
m_ds = DriverStation.getInstance();
|
||||
m_axes = new byte[numAxisTypes];
|
||||
m_buttons = new byte[numButtonTypes];
|
||||
m_port = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the X value of the joystick.
|
||||
* This depends on the mapping of the joystick connected to the current port.
|
||||
*
|
||||
* @param hand Unused
|
||||
* @return The X value of the joystick.
|
||||
*/
|
||||
public double getX(Hand hand) {
|
||||
return getRawAxis(m_axes[AxisType.kX.value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Y value of the joystick.
|
||||
* This depends on the mapping of the joystick connected to the current port.
|
||||
*
|
||||
* @param hand Unused
|
||||
* @return The Y value of the joystick.
|
||||
*/
|
||||
public double getY(Hand hand) {
|
||||
return getRawAxis(m_axes[AxisType.kY.value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Z value of the joystick.
|
||||
* This depends on the mapping of the joystick connected to the current port.
|
||||
*
|
||||
* @param hand Unused
|
||||
* @return The Z value of the joystick.
|
||||
*/
|
||||
public double getZ(Hand hand) {
|
||||
return getRawAxis(m_axes[AxisType.kZ.value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the twist value of the current joystick.
|
||||
* This depends on the mapping of the joystick connected to the current port.
|
||||
*
|
||||
* @return The Twist value of the joystick.
|
||||
*/
|
||||
public double getTwist() {
|
||||
return getRawAxis(m_axes[AxisType.kTwist.value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the throttle value of the current joystick.
|
||||
* This depends on the mapping of the joystick connected to the current port.
|
||||
*
|
||||
* @return The Throttle value of the joystick.
|
||||
*/
|
||||
public double getThrottle() {
|
||||
return getRawAxis(m_axes[AxisType.kThrottle.value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the axis.
|
||||
*
|
||||
* @param axis The axis to read [1-6].
|
||||
* @return The value of the axis.
|
||||
*/
|
||||
public double getRawAxis(final int axis) {
|
||||
return m_ds.getStickAxis(m_port, axis);
|
||||
}
|
||||
|
||||
/**
|
||||
* For the current joystick, return the axis determined by the argument.
|
||||
*
|
||||
* This is for cases where the joystick axis is returned programatically, otherwise one of the
|
||||
* previous functions would be preferable (for example getX()).
|
||||
*
|
||||
* @param axis The axis to read.
|
||||
* @return The value of the axis.
|
||||
*/
|
||||
public double getAxis(final AxisType axis) {
|
||||
switch (axis.value) {
|
||||
case AxisType.kX_val:
|
||||
return getX();
|
||||
case AxisType.kY_val:
|
||||
return getY();
|
||||
case AxisType.kZ_val:
|
||||
return getZ();
|
||||
case AxisType.kTwist_val:
|
||||
return getTwist();
|
||||
case AxisType.kThrottle_val:
|
||||
return getThrottle();
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the state of the trigger on the joystick.
|
||||
*
|
||||
* Look up which button has been assigned to the trigger and read its state.
|
||||
*
|
||||
* @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
|
||||
* @return The state of the trigger.
|
||||
*/
|
||||
public boolean getTrigger(Hand hand) {
|
||||
return getRawButton(m_buttons[ButtonType.kTrigger.value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the state of the top button on the joystick.
|
||||
*
|
||||
* Look up which button has been assigned to the top and read its state.
|
||||
*
|
||||
* @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
|
||||
* @return The state of the top button.
|
||||
*/
|
||||
public boolean getTop(Hand hand) {
|
||||
return getRawButton(m_buttons[ButtonType.kTop.value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is not supported for the Joystick.
|
||||
* This method is only here to complete the GenericHID interface.
|
||||
*
|
||||
* @param hand This parameter is ignored for the Joystick class and is only here to complete the GenericHID interface.
|
||||
* @return The state of the bumper (always false)
|
||||
*/
|
||||
public boolean getBumper(Hand hand) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the button value for buttons 1 through 12.
|
||||
*
|
||||
* The buttons are returned in a single 16 bit value with one bit representing the state
|
||||
* of each button. The appropriate button is returned as a boolean value.
|
||||
*
|
||||
* @param button The button number to be read.
|
||||
* @return The state of the button.
|
||||
*/
|
||||
public boolean getRawButton(final int button) {
|
||||
return ((0x1 << (button - 1)) & m_ds.getStickButtons(m_port)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get buttons based on an enumerated type.
|
||||
*
|
||||
* The button type will be looked up in the list of buttons and then read.
|
||||
*
|
||||
* @param button The type of button to read.
|
||||
* @return The state of the button.
|
||||
*/
|
||||
public boolean getButton(ButtonType button) {
|
||||
switch (button.value) {
|
||||
case ButtonType.kTrigger_val:
|
||||
return getTrigger();
|
||||
case ButtonType.kTop_val:
|
||||
return getTop();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the magnitude of the direction vector formed by the joystick's
|
||||
* current position relative to its origin
|
||||
*
|
||||
* @return The magnitude of the direction vector
|
||||
*/
|
||||
public double getMagnitude() {
|
||||
return Math.sqrt(Math.pow(getX(), 2) + Math.pow(getY(), 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the direction of the vector formed by the joystick and its origin
|
||||
* in radians
|
||||
*
|
||||
* @return The direction of the vector in radians
|
||||
*/
|
||||
public double getDirectionRadians() {
|
||||
return Math.atan2(getX(), -getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the direction of the vector formed by the joystick and its origin
|
||||
* in degrees
|
||||
*
|
||||
* uses acos(-1) to represent Pi due to absence of readily accessable Pi
|
||||
* constant in C++
|
||||
*
|
||||
* @return The direction of the vector in degrees
|
||||
*/
|
||||
public double getDirectionDegrees() {
|
||||
return Math.toDegrees(getDirectionRadians());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channel currently associated with the specified axis.
|
||||
*
|
||||
* @param axis The axis to look up the channel for.
|
||||
* @return The channel fr the axis.
|
||||
*/
|
||||
public int getAxisChannel(AxisType axis) {
|
||||
return m_axes[axis.value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the channel associated with a specified axis.
|
||||
*
|
||||
* @param axis The axis to set the channel for.
|
||||
* @param channel The channel to set the axis to.
|
||||
*/
|
||||
public void setAxisChannel(AxisType axis, int channel) {
|
||||
m_axes[axis.value] = (byte) channel;
|
||||
}
|
||||
}
|
||||
@@ -1,456 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
import edu.wpi.first.wpilibj.communication.FRCControl;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
|
||||
/**
|
||||
* @author bradmiller
|
||||
* Handles raw data input from the FRC Kinect Server
|
||||
* when used with a Kinect device connected to the Driver Station.
|
||||
* Each time a value is requested the most recent value is returned.
|
||||
* See Getting Started with Microsoft Kinect for FRC and the Kinect
|
||||
* for Windows SDK API reference for more information
|
||||
*
|
||||
*/
|
||||
public class Kinect {
|
||||
|
||||
private static Kinect m_instance;
|
||||
|
||||
/**
|
||||
* Gets an instance of the Kinect device
|
||||
*
|
||||
* @return The Kinect.
|
||||
*/
|
||||
public static synchronized Kinect getInstance() {
|
||||
if(m_instance == null)
|
||||
m_instance = new Kinect();
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of 4 coordinates (x,y,z,w) bundled into one object
|
||||
*/
|
||||
public class Point4 {
|
||||
public float x, y, z, w;
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
public float getY() {
|
||||
return y;
|
||||
}
|
||||
public float getZ() {
|
||||
return z;
|
||||
}
|
||||
public float getW() {
|
||||
return w;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
||||
static class header_t extends Structure {
|
||||
|
||||
byte[] version = new byte[11];
|
||||
byte players;
|
||||
int flags;
|
||||
float[] floorClipPlane = new float[4];
|
||||
float[] gravityNormalVector = new float[3];
|
||||
|
||||
final static int size = 44;
|
||||
|
||||
header_t(Pointer backingMemory) {
|
||||
useMemory(backingMemory);
|
||||
}
|
||||
|
||||
public void read() {
|
||||
backingNativeMemory.getBytes(0, version, 0, version.length);
|
||||
players = backingNativeMemory.getByte(11);
|
||||
flags = backingNativeMemory.getInt(12);
|
||||
backingNativeMemory.getFloats(16, floorClipPlane, 0, floorClipPlane.length);
|
||||
backingNativeMemory.getFloats(32, gravityNormalVector, 0, gravityNormalVector.length);
|
||||
}
|
||||
|
||||
public void write() {
|
||||
backingNativeMemory.setBytes(0, version, 0, version.length);
|
||||
backingNativeMemory.setByte(11, players);
|
||||
backingNativeMemory.setInt(12, flags);
|
||||
backingNativeMemory.setFloats(16, floorClipPlane, 0, floorClipPlane.length);
|
||||
backingNativeMemory.setFloats(32, gravityNormalVector, 0, gravityNormalVector.length);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
static class skeletonExtra_t extends Structure {
|
||||
byte[] trackingState = new byte[20];
|
||||
float[] position = new float[3];
|
||||
int quality;
|
||||
int trackState;
|
||||
|
||||
final static int size = 40;
|
||||
|
||||
skeletonExtra_t(Pointer backingMemory) {
|
||||
useMemory(backingMemory);
|
||||
}
|
||||
|
||||
public void read() {
|
||||
backingNativeMemory.getBytes(0, trackingState, 0, trackingState.length);
|
||||
backingNativeMemory.getFloats(20, position, 0, position.length);
|
||||
quality = backingNativeMemory.getInt(32);
|
||||
trackState = backingNativeMemory.getInt(36);
|
||||
}
|
||||
|
||||
public void write() {
|
||||
backingNativeMemory.setBytes(0, trackingState, 0, trackingState.length);
|
||||
backingNativeMemory.setFloats(20, position, 0, position.length);
|
||||
backingNativeMemory.setInt(32, quality);
|
||||
backingNativeMemory.setInt(36, trackState);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
static class skeleton_t extends Structure {
|
||||
float[] vertices = new float[60];
|
||||
|
||||
final static int size = 240;
|
||||
|
||||
skeleton_t(Pointer backingMemory) {
|
||||
useMemory(backingMemory);
|
||||
}
|
||||
|
||||
public void read() {
|
||||
backingNativeMemory.getFloats(0, vertices, 0, vertices.length);
|
||||
}
|
||||
|
||||
public void write() {
|
||||
backingNativeMemory.setFloats(0, vertices, 0, vertices.length);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
class header_block_t extends FRCControl.DynamicControlData {
|
||||
byte size = 45;
|
||||
byte id = kHeaderBlockID;
|
||||
header_t data;
|
||||
|
||||
{
|
||||
allocateMemory();
|
||||
data = new header_t(
|
||||
new Pointer(backingNativeMemory.address().toUWord().toPrimitive() + 2,
|
||||
header_t.size));
|
||||
}
|
||||
|
||||
public void read() {
|
||||
|
||||
size = backingNativeMemory.getByte(0);
|
||||
id = backingNativeMemory.getByte(1);
|
||||
data.read();
|
||||
}
|
||||
|
||||
public void write() {
|
||||
backingNativeMemory.setByte(0, size);
|
||||
backingNativeMemory.setByte(1, id);
|
||||
data.write();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return 46;
|
||||
}
|
||||
|
||||
public void copy(header_block_t dest) {
|
||||
write();
|
||||
Pointer.copyBytes(backingNativeMemory, 0, dest.backingNativeMemory, 0, size());
|
||||
dest.read();
|
||||
}
|
||||
}
|
||||
|
||||
class skeletonExtra_block_t extends FRCControl.DynamicControlData {
|
||||
byte size = 41;
|
||||
byte id = kSkeletonExtraBlockID;
|
||||
skeletonExtra_t data;
|
||||
|
||||
{
|
||||
allocateMemory();
|
||||
data = new skeletonExtra_t(
|
||||
new Pointer(backingNativeMemory.address().toUWord().toPrimitive() + 2,
|
||||
skeletonExtra_t.size));
|
||||
}
|
||||
|
||||
public void read() {
|
||||
|
||||
size = backingNativeMemory.getByte(0);
|
||||
id = backingNativeMemory.getByte(1);
|
||||
data.read();
|
||||
}
|
||||
|
||||
public void write() {
|
||||
backingNativeMemory.setByte(0, size);
|
||||
backingNativeMemory.setByte(1, id);
|
||||
data.write();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public void copy(skeletonExtra_block_t dest) {
|
||||
write();
|
||||
Pointer.copyBytes(backingNativeMemory, 0, dest.backingNativeMemory, 0, size());
|
||||
dest.read();
|
||||
}
|
||||
}
|
||||
|
||||
class skeleton_block_t extends FRCControl.DynamicControlData {
|
||||
byte size = -15; //temporary hack for 241
|
||||
byte id = kSkeletonBlockID;
|
||||
skeleton_t data;
|
||||
|
||||
{
|
||||
allocateMemory();
|
||||
data = new skeleton_t(
|
||||
new Pointer(backingNativeMemory.address().toUWord().toPrimitive() + 2,
|
||||
skeleton_t.size));
|
||||
}
|
||||
|
||||
public void read() {
|
||||
size = backingNativeMemory.getByte(0);
|
||||
id = backingNativeMemory.getByte(1);
|
||||
data.read();
|
||||
}
|
||||
|
||||
public void write() {
|
||||
backingNativeMemory.setByte(0, size);
|
||||
backingNativeMemory.setByte(1, id);
|
||||
data.write();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return 242;
|
||||
}
|
||||
|
||||
public void copy(skeleton_block_t dest) {
|
||||
write();
|
||||
Pointer.copyBytes(backingNativeMemory, 0, dest.backingNativeMemory, 0, size());
|
||||
dest.read();
|
||||
}
|
||||
}
|
||||
|
||||
static final byte kHeaderBlockID = 19;
|
||||
static final byte kSkeletonExtraBlockID = 20;
|
||||
static final byte kSkeletonBlockID = 21;
|
||||
|
||||
header_block_t m_headerData;
|
||||
skeletonExtra_block_t m_skeletonExtraData;
|
||||
skeleton_block_t m_skeletonData;
|
||||
boolean m_headerValid = false;
|
||||
boolean m_skeletonExtraValid = false;
|
||||
boolean m_skeletonValid = false;
|
||||
final Object m_headerDataSemaphore;
|
||||
final Object m_skeletonExtraDataSemaphore;
|
||||
final Object m_skeletonDataSemaphore;
|
||||
int m_recentPacketNumber = 0;
|
||||
|
||||
/**
|
||||
* Kinect constructor.
|
||||
*
|
||||
* This is only called once on the first call of getInstance()
|
||||
*/
|
||||
Kinect() {
|
||||
m_headerData = new header_block_t();
|
||||
m_skeletonExtraData = new skeletonExtra_block_t();
|
||||
m_skeletonData = new skeleton_block_t();
|
||||
m_headerDataSemaphore = new Object();
|
||||
m_skeletonExtraDataSemaphore = new Object();
|
||||
m_skeletonDataSemaphore = new Object();
|
||||
|
||||
UsageReporting.report(UsageReporting.kResourceType_Kinect, 0);
|
||||
}
|
||||
header_block_t tempHeaderData = new header_block_t();
|
||||
skeletonExtra_block_t tempSkeletonExtraData = new skeletonExtra_block_t();
|
||||
skeleton_block_t tempSkeletonData = new skeleton_block_t();
|
||||
|
||||
|
||||
/**
|
||||
* Called by the other Kinect functions to check for the latest data
|
||||
* This function will update the internal data structures
|
||||
* with the most recent Kinect input
|
||||
*/
|
||||
void updateData() {
|
||||
int retVal;
|
||||
|
||||
if (m_recentPacketNumber != DriverStation.getInstance().getPacketNumber()) {
|
||||
m_recentPacketNumber = DriverStation.getInstance().getPacketNumber();
|
||||
synchronized (m_headerDataSemaphore) {
|
||||
retVal = FRCControl.getDynamicControlData(kHeaderBlockID, tempHeaderData, tempHeaderData.size(), 5);
|
||||
if (retVal == 0) {
|
||||
tempHeaderData.copy(m_headerData);
|
||||
m_headerValid = true;
|
||||
} else {
|
||||
m_headerValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (m_skeletonExtraDataSemaphore) {
|
||||
retVal = FRCControl.getDynamicControlData(kSkeletonExtraBlockID, tempSkeletonExtraData, tempSkeletonExtraData.size(), 5);
|
||||
if (retVal == 0) {
|
||||
tempSkeletonExtraData.copy(m_skeletonExtraData);
|
||||
m_skeletonExtraValid = true;
|
||||
} else {
|
||||
m_skeletonExtraValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (m_skeletonDataSemaphore) {
|
||||
retVal = FRCControl.getDynamicControlData(kSkeletonBlockID, tempSkeletonData, tempSkeletonData.size(), 5);
|
||||
if (retVal == 0) {
|
||||
tempSkeletonData.copy(m_skeletonData);
|
||||
m_skeletonValid = true;
|
||||
} else {
|
||||
m_skeletonValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the number of players detected by the Kinect
|
||||
*
|
||||
* @return The current number of players
|
||||
*/
|
||||
public int getNumberOfPlayers() {
|
||||
updateData();
|
||||
if (!m_headerValid) {
|
||||
return 0;
|
||||
}
|
||||
synchronized (m_headerDataSemaphore) {
|
||||
return (int)m_headerData.data.players;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the FloorClipPlane from the Kinect device
|
||||
*
|
||||
* @return The FloorClipPlane
|
||||
*/
|
||||
public Point4 getFloorClipPlane() {
|
||||
updateData();
|
||||
Point4 tempClipPlane = new Point4();
|
||||
|
||||
if (!m_headerValid) {
|
||||
return tempClipPlane;
|
||||
}
|
||||
|
||||
synchronized(m_headerDataSemaphore) {
|
||||
tempClipPlane.x = m_headerData.data.floorClipPlane[0];
|
||||
tempClipPlane.y = m_headerData.data.floorClipPlane[1];
|
||||
tempClipPlane.z = m_headerData.data.floorClipPlane[2];
|
||||
tempClipPlane.w = m_headerData.data.floorClipPlane[3];
|
||||
}
|
||||
return tempClipPlane;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the GravityNormal vector from the Kinect device
|
||||
* The w value returned from this method is always 0
|
||||
* @return The GravityNormal vector
|
||||
*/
|
||||
public Point4 getGravityNormal() {
|
||||
updateData();
|
||||
Point4 tempGravityNormal = new Point4();
|
||||
|
||||
if (!m_headerValid) {
|
||||
return tempGravityNormal;
|
||||
}
|
||||
|
||||
synchronized(m_headerDataSemaphore) {
|
||||
tempGravityNormal.x = m_headerData.data.gravityNormalVector[0];
|
||||
tempGravityNormal.y = m_headerData.data.gravityNormalVector[1];
|
||||
tempGravityNormal.z = m_headerData.data.gravityNormalVector[2];
|
||||
tempGravityNormal.w = 0;
|
||||
}
|
||||
return tempGravityNormal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the position of the detected skeleton
|
||||
* The w value returned from this method is always 1
|
||||
* @return The position of the skeleton
|
||||
*/
|
||||
public Point4 getPosition() {
|
||||
updateData();
|
||||
Point4 tempPosition = new Point4();
|
||||
|
||||
if (!m_skeletonExtraValid) {
|
||||
return tempPosition;
|
||||
}
|
||||
|
||||
synchronized(m_headerDataSemaphore) {
|
||||
tempPosition.x = m_skeletonExtraData.data.position[0];
|
||||
tempPosition.y = m_skeletonExtraData.data.position[1];
|
||||
tempPosition.z = m_skeletonExtraData.data.position[2];
|
||||
tempPosition.w = 1;
|
||||
}
|
||||
return tempPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the detected skeleton from the Kinect device
|
||||
*
|
||||
* @return The skeleton
|
||||
*/
|
||||
public Skeleton getSkeleton() {
|
||||
updateData();
|
||||
Skeleton tempSkeleton = new Skeleton();
|
||||
|
||||
if (!m_skeletonValid) {
|
||||
return tempSkeleton;
|
||||
}
|
||||
|
||||
synchronized (m_skeletonDataSemaphore) {
|
||||
for(int i=0; i<20; i++) {
|
||||
tempSkeleton.skeleton[i].x = m_skeletonData.data.vertices[i*3];
|
||||
tempSkeleton.skeleton[i].y = m_skeletonData.data.vertices[i*3+1];
|
||||
tempSkeleton.skeleton[i].z = m_skeletonData.data.vertices[i*3+2];
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (m_skeletonExtraDataSemaphore) {
|
||||
for(int i=0; i<20; i++) {
|
||||
tempSkeleton.skeleton[i].trackingState = m_skeletonExtraData.data.trackingState[i];
|
||||
}
|
||||
switch(m_skeletonExtraData.data.trackState) {
|
||||
case 0:
|
||||
tempSkeleton.trackState = Skeleton.tTrackState.kNotTracked;
|
||||
break;
|
||||
case 1:
|
||||
tempSkeleton.trackState = Skeleton.tTrackState.kPositionOnly;
|
||||
break;
|
||||
case 2:
|
||||
tempSkeleton.trackState = Skeleton.tTrackState.kTracked;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return tempSkeleton;
|
||||
}
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 com.sun.jna.Pointer;
|
||||
import com.sun.jna.Structure;
|
||||
import edu.wpi.first.wpilibj.communication.FRCControl;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
|
||||
/**
|
||||
* @author bradmiller
|
||||
* Handles input from the Joystick data sent by the FRC Kinect Server
|
||||
* when used with a Kinect device connected to the Driver Station.
|
||||
* Each time a value is requested the most recent value is returned.
|
||||
* Default gestures embedded in the FRC Kinect Server are described
|
||||
* in the document Getting Started with Microsoft Kinect for FRC.
|
||||
*/
|
||||
public class KinectStick extends GenericHID {
|
||||
|
||||
private final static byte kJoystickDataID = 24;
|
||||
private final static byte kJoystickDataSize = 18;
|
||||
private int m_recentPacketNumber;
|
||||
|
||||
private int m_id;
|
||||
|
||||
static class JoystickDataBlock extends Structure {
|
||||
|
||||
byte joystick1[] = new byte[6];
|
||||
short button1;
|
||||
byte joystick2[] = new byte[6];
|
||||
short button2;
|
||||
|
||||
public static final int size = kJoystickDataSize - 2;
|
||||
|
||||
JoystickDataBlock(Pointer backingMemory) {
|
||||
useMemory(backingMemory);
|
||||
}
|
||||
|
||||
public void read() {
|
||||
backingNativeMemory.getBytes(0, joystick1, 0, 6);
|
||||
button1 = backingNativeMemory.getShort(6);
|
||||
backingNativeMemory.getBytes(8, joystick2, 0, 6);
|
||||
button2 = backingNativeMemory.getShort(14);
|
||||
}
|
||||
|
||||
public void write() {
|
||||
backingNativeMemory.setBytes(0, joystick1, 0, 6);
|
||||
backingNativeMemory.setShort(6, button1);
|
||||
backingNativeMemory.setBytes(8, joystick2, 0, 6);
|
||||
backingNativeMemory.setShort(14, button2);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
class JoystickData extends FRCControl.DynamicControlData {
|
||||
|
||||
JoystickDataBlock data;
|
||||
|
||||
{
|
||||
allocateMemory();
|
||||
data = new JoystickDataBlock(
|
||||
new Pointer(backingNativeMemory.address().toUWord().toPrimitive() + 2,
|
||||
JoystickDataBlock.size));
|
||||
}
|
||||
|
||||
public void read() {
|
||||
data.read();
|
||||
}
|
||||
|
||||
public void write() {
|
||||
data.write();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return kJoystickDataSize;
|
||||
}
|
||||
|
||||
public void copy(JoystickData dest) {
|
||||
write();
|
||||
Pointer.copyBytes(backingNativeMemory, 0, dest.backingNativeMemory, 0, size());
|
||||
dest.read();
|
||||
}
|
||||
}
|
||||
JoystickData tempOutputData = new JoystickData();
|
||||
|
||||
/**
|
||||
* Construct an instance of a KinectStick.
|
||||
* @param id which KinectStick to read, in the default gestures
|
||||
* an id of 1 corresponds to the left arm and 2 to the right arm.
|
||||
*/
|
||||
public KinectStick(int id) {
|
||||
m_id = id;
|
||||
|
||||
UsageReporting.report(UsageReporting.kResourceType_KinectStick, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the data in this class with the latest data from the
|
||||
* Driver Station.
|
||||
*/
|
||||
private void getData() {
|
||||
if (m_recentPacketNumber != DriverStation.getInstance().getPacketNumber()) {
|
||||
m_recentPacketNumber = DriverStation.getInstance().getPacketNumber();
|
||||
int retVal = FRCControl.getDynamicControlData(kJoystickDataID, tempOutputData, tempOutputData.size(), 5);
|
||||
if (retVal != 0) {
|
||||
System.err.println("Bad retval: " + retVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a value from a byte to a double in the
|
||||
* -1 to 1 range
|
||||
* @param rawValue the value to convert
|
||||
* @return the normalized value
|
||||
*/
|
||||
private double normalize(byte rawValue) {
|
||||
if(rawValue >= 0)
|
||||
return rawValue / 127.0;
|
||||
else
|
||||
return rawValue / 128.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the X value of the KinectStick. This axis
|
||||
* is unimplemented in the default gestures but can
|
||||
* be populated by teams editing the Kinect Server.
|
||||
* See (@link Joystick for axis number mapping)
|
||||
* @param hand Unused
|
||||
* @return The X value of the KinectStick
|
||||
*/
|
||||
public double getX(Hand hand) {
|
||||
getData();
|
||||
return getRawAxis(Joystick.kDefaultXAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Y value of the KinectStick. This axis
|
||||
* represents arm angle in the default gestures
|
||||
* See (@link Joystick for axis number mapping)
|
||||
* @param hand Unused
|
||||
* @return The Y value of the KinectStick
|
||||
*/
|
||||
public double getY(Hand hand) {
|
||||
getData();
|
||||
return getRawAxis(Joystick.kDefaultYAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Z value of the KinectStick. This axis
|
||||
* is unimplemented in the default gestures but can
|
||||
* be populated by teams editing the Kinect Server.
|
||||
* See (@link Joystick for axis number mapping)
|
||||
* @param hand Unused
|
||||
* @return The Z value of the KinectStick
|
||||
*/
|
||||
public double getZ(Hand hand) {
|
||||
getData();
|
||||
return getRawAxis(Joystick.kDefaultZAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Twist value of the KinectStick. This axis
|
||||
* is unimplemented in the default gestures but can
|
||||
* be populated by teams editing the Kinect Server.
|
||||
* See (@link Joystick for axis number mapping)
|
||||
* @return The Twist value of the KinectStick
|
||||
*/
|
||||
public double getTwist() {
|
||||
getData();
|
||||
return getRawAxis(Joystick.kDefaultTwistAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Throttle value of the KinectStick. This axis
|
||||
* is unimplemented in the default gestures but can
|
||||
* be populated by teams editing the Kinect Server.
|
||||
* See (@link Joystick for axis number mapping)
|
||||
* @return The Throttle value of the KinectStick
|
||||
*/
|
||||
public double getThrottle() {
|
||||
getData();
|
||||
return getRawAxis(Joystick.kDefaultThrottleAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the KinectStick axis.
|
||||
*
|
||||
* @param axis The axis to read [1-6].
|
||||
* @return The value of the axis
|
||||
*/
|
||||
public double getRawAxis(int axis) {
|
||||
if (axis < 1 || axis > DriverStation.kJoystickAxes)
|
||||
return 0.0;
|
||||
|
||||
getData();
|
||||
if (m_id == 1) {
|
||||
return normalize(tempOutputData.data.joystick1[axis-1]);
|
||||
} else {
|
||||
return normalize(tempOutputData.data.joystick2[axis-1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the button value for the button set as the default trigger in
|
||||
* (@link Joystick)
|
||||
*
|
||||
* @param hand Unused
|
||||
* @return The state of the button.
|
||||
*/
|
||||
public boolean getTrigger(Hand hand) {
|
||||
getData();
|
||||
return (tempOutputData.data.button1 & (short) Joystick.kDefaultTriggerButton) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the button value for the button set as the default top in
|
||||
* (@link Joystick)
|
||||
*
|
||||
* @param hand Unused
|
||||
* @return The state of the button.
|
||||
*/
|
||||
public boolean getTop(Hand hand) {
|
||||
getData();
|
||||
return (tempOutputData.data.button1 & (short) Joystick.kDefaultTopButton) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the button value for the button set as the default bumper in
|
||||
* (@link Joystick)
|
||||
*
|
||||
* @param hand Unused
|
||||
* @return The state of the button.
|
||||
*/
|
||||
public boolean getBumper(Hand hand) {
|
||||
getData();
|
||||
return (tempOutputData.data.button1 & (short) 4) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the button value for buttons 1 through 12. The default gestures
|
||||
* implement only 9 buttons.
|
||||
*
|
||||
* The appropriate button is returned as a boolean value.
|
||||
*
|
||||
* @param button The button number to be read.
|
||||
* @return The state of the button.
|
||||
*/
|
||||
public boolean getRawButton(int button) {
|
||||
getData();
|
||||
return (tempOutputData.data.button1 & (short) (1 << (button - 1))) != 0;
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tModuleType;
|
||||
|
||||
/**
|
||||
* Base class for AnalogModule and DigitalModule.
|
||||
*
|
||||
* @author dtjones
|
||||
*/
|
||||
public class Module extends SensorBase {
|
||||
|
||||
/**
|
||||
* An array holding the object representing each module
|
||||
*/
|
||||
protected static Module[] m_modules = new Module[tModuleType.kModuleType_Solenoid * FRC_NetworkCommunicationsLibrary.kMaxModuleNumber + (FRC_NetworkCommunicationsLibrary.kMaxModuleNumber - 1)];
|
||||
/**
|
||||
* The module number of the module
|
||||
*/
|
||||
protected int m_moduleNumber;
|
||||
protected int m_moduleType;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param moduleNumber The number of this module (1 or 2).
|
||||
*/
|
||||
protected Module(int moduleType, final int moduleNumber) {
|
||||
m_modules[toIndex(moduleType, moduleNumber)] = this;
|
||||
m_moduleNumber = moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the module number associated with a module.
|
||||
*
|
||||
* @return The module's number.
|
||||
*/
|
||||
public int getModuleNumber() {
|
||||
return m_moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the module type associated with a module.
|
||||
*
|
||||
* @return The module's type.
|
||||
*/
|
||||
public int getModuleType() {
|
||||
return m_moduleType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static module singleton factory.
|
||||
*
|
||||
* @param moduleType The type of the module represented.
|
||||
* @param moduleNumber The module index within the module type.
|
||||
* @return the module
|
||||
*/
|
||||
public static Module getModule(int moduleType, int moduleNumber) {
|
||||
if(m_modules[toIndex(moduleType, moduleNumber)] == null) {
|
||||
if(moduleType == tModuleType.kModuleType_Analog) {
|
||||
new AnalogModule(moduleNumber);
|
||||
} else if (moduleType == tModuleType.kModuleType_Digital) {
|
||||
new DigitalModule(moduleNumber);
|
||||
/* } else if (moduleType.equals(ModulePresence.ModuleType.kSolenoid)) {
|
||||
new Sol
|
||||
*/
|
||||
} else {
|
||||
throw new RuntimeException("A module of type "+moduleType+" with module index "+moduleNumber);
|
||||
}
|
||||
}
|
||||
return m_modules[toIndex(moduleType, moduleNumber)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an index into m_modules based on type and number
|
||||
*
|
||||
* @param moduleType The type of the module represented.
|
||||
* @param moduleNumber The module index within the module type.
|
||||
* @return The index into m_modules.
|
||||
*/
|
||||
private static int toIndex(int moduleType, int moduleNumber) {
|
||||
if(moduleNumber == 0 || moduleNumber > FRC_NetworkCommunicationsLibrary.kMaxModuleNumber)
|
||||
return 0;
|
||||
return moduleType * FRC_NetworkCommunicationsLibrary.kMaxModuleNumber + (moduleNumber - 1);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author brad
|
||||
*/
|
||||
public interface MotorSafety {
|
||||
public static final double DEFAULT_SAFETY_EXPIRATION = 0.1;
|
||||
void setExpiration(double timeout);
|
||||
double getExpiration();
|
||||
boolean isAlive();
|
||||
void stopMotor();
|
||||
void setSafetyEnabled(boolean enabled);
|
||||
boolean isSafetyEnabled();
|
||||
String getDescription();
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 MotorSafetyHelper object is constructed for every object that wants to implement the Motor
|
||||
* Safety protocol. The helper object has the code to actually do the timing and call the
|
||||
* motors Stop() method when the timeout expires. The motor object is expected to call the
|
||||
* Feed() method whenever the motors value is updated.
|
||||
*
|
||||
* @author brad
|
||||
*/
|
||||
public class MotorSafetyHelper {
|
||||
|
||||
double m_expiration;
|
||||
boolean m_enabled;
|
||||
double m_stopTime;
|
||||
MotorSafety m_safeObject;
|
||||
MotorSafetyHelper m_nextHelper;
|
||||
static MotorSafetyHelper m_headHelper = null;
|
||||
|
||||
/**
|
||||
* The constructor for a MotorSafetyHelper object.
|
||||
* The helper object is constructed for every object that wants to implement the Motor
|
||||
* Safety protocol. The helper object has the code to actually do the timing and call the
|
||||
* motors Stop() method when the timeout expires. The motor object is expected to call the
|
||||
* Feed() method whenever the motors value is updated.
|
||||
*
|
||||
* @param safeObject a pointer to the motor object implementing MotorSafety. This is used
|
||||
* to call the Stop() method on the motor.
|
||||
*/
|
||||
public MotorSafetyHelper(MotorSafety safeObject) {
|
||||
m_safeObject = safeObject;
|
||||
m_enabled = false;
|
||||
m_expiration = MotorSafety.DEFAULT_SAFETY_EXPIRATION;
|
||||
m_stopTime = Timer.getFPGATimestamp();
|
||||
m_nextHelper = m_headHelper;
|
||||
m_headHelper = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Feed the motor safety object.
|
||||
* Resets the timer on this object that is used to do the timeouts.
|
||||
*/
|
||||
public void feed() {
|
||||
m_stopTime = Timer.getFPGATimestamp() + m_expiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expiration time for the corresponding motor safety object.
|
||||
* @param expirationTime The timeout value in seconds.
|
||||
*/
|
||||
public void setExpiration(double expirationTime) {
|
||||
m_expiration = expirationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the timeout value for the corresponding motor safety object.
|
||||
* @return the timeout value in seconds.
|
||||
*/
|
||||
public double getExpiration() {
|
||||
return m_expiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine of the motor is still operating or has timed out.
|
||||
* @return a true value if the motor is still operating normally and hasn't timed out.
|
||||
*/
|
||||
public boolean isAlive() {
|
||||
return !m_enabled || m_stopTime > Timer.getFPGATimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this motor has exceeded its timeout.
|
||||
* This method is called periodically to determine if this motor has exceeded its timeout
|
||||
* value. If it has, the stop method is called, and the motor is shut down until its value is
|
||||
* updated again.
|
||||
*/
|
||||
public void check() {
|
||||
DriverStation ds = DriverStation.getInstance();
|
||||
if (!m_enabled || ds.isDisabled() || ds.isTest())
|
||||
return;
|
||||
if (m_stopTime < Timer.getFPGATimestamp()) {
|
||||
System.err.println(m_safeObject.getDescription() + "... Output not updated often enough.");
|
||||
|
||||
m_safeObject.stopMotor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable motor safety for this device
|
||||
* Turn on and off the motor safety option for this PWM object.
|
||||
* @param enabled True if motor safety is enforced for this object
|
||||
*/
|
||||
public void setSafetyEnabled(boolean enabled) {
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the state of the motor safety enabled flag
|
||||
* Return if the motor safety is currently enabled for this devicce.
|
||||
* @return True if motor safety is enforced for this device
|
||||
*/
|
||||
public boolean isSafetyEnabled() {
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the motors to see if any have timed out.
|
||||
* This static method is called periodically to poll all the motors and stop any that have
|
||||
* timed out.
|
||||
*/
|
||||
//TODO: these should be synchronized with the setting methods in case it's called from a different thread
|
||||
public static void checkMotors() {
|
||||
for (MotorSafetyHelper msh = m_headHelper; msh != null; msh = msh.m_nextHelper) {
|
||||
msh.check();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
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 {
|
||||
|
||||
/**
|
||||
* @return the name of the subtable of SmartDashboard that the Sendable object will use
|
||||
*/
|
||||
public String getName();
|
||||
}
|
||||
@@ -1,591 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.util.TimerTask;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.IUtility;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
|
||||
/**
|
||||
* Class implements a PID Control Loop.
|
||||
*
|
||||
* Creates a separate thread which reads the given PIDSource and takes
|
||||
* care of the integral calculations, as well as writing the given
|
||||
* PIDOutput
|
||||
*/
|
||||
public class PIDController implements IUtility, LiveWindowSendable, Controller {
|
||||
|
||||
public static final double kDefaultPeriod = .05;
|
||||
private static int instances = 0;
|
||||
private double m_P; // factor for "proportional" control
|
||||
private double m_I; // factor for "integral" control
|
||||
private double m_D; // factor for "derivative" control
|
||||
private double m_F; // factor for feedforward term
|
||||
private double m_maximumOutput = 1.0; // |maximum output|
|
||||
private double m_minimumOutput = -1.0; // |minimum output|
|
||||
private double m_maximumInput = 0.0; // maximum input - limit setpoint to this
|
||||
private double m_minimumInput = 0.0; // minimum input - limit setpoint to this
|
||||
private boolean m_continuous = false; // do the endpoints wrap around? eg. Absolute encoder
|
||||
private boolean m_enabled = false; //is the pid controller enabled
|
||||
private double m_prevError = 0.0; // the prior sensor input (used to compute velocity)
|
||||
private double m_totalError = 0.0; //the sum of the errors for use in the integral calc
|
||||
private Tolerance m_tolerance; //the tolerance object used to check if on target
|
||||
private double m_setpoint = 0.0;
|
||||
private double m_error = 0.0;
|
||||
private double m_result = 0.0;
|
||||
private double m_period = kDefaultPeriod;
|
||||
PIDSource m_pidInput;
|
||||
PIDOutput m_pidOutput;
|
||||
java.util.Timer m_controlLoop;
|
||||
private boolean m_usingPercentTolerance;
|
||||
|
||||
/**
|
||||
* Tolerance is the type of tolerance used to specify if the PID controller is on target.
|
||||
* The various implementations of this class such as PercentageTolerance and AbsoluteTolerance
|
||||
* specify types of tolerance specifications to use.
|
||||
*/
|
||||
public interface Tolerance {
|
||||
public boolean onTarget();
|
||||
}
|
||||
|
||||
public class PercentageTolerance implements Tolerance {
|
||||
double percentage;
|
||||
|
||||
PercentageTolerance(double value) {
|
||||
percentage = value;
|
||||
}
|
||||
|
||||
public boolean onTarget() {
|
||||
return (Math.abs(getError()) < percentage / 100
|
||||
* (m_maximumInput - m_minimumInput));
|
||||
}
|
||||
}
|
||||
|
||||
public class AbsoluteTolerance implements Tolerance {
|
||||
double value;
|
||||
|
||||
AbsoluteTolerance(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean onTarget() {
|
||||
return Math.abs(getError()) < value;
|
||||
}
|
||||
}
|
||||
|
||||
public class NullTolerance implements Tolerance {
|
||||
|
||||
public boolean onTarget() {
|
||||
throw new RuntimeException("No tolerance value set when using PIDController.onTarget()");
|
||||
}
|
||||
}
|
||||
|
||||
private class PIDTask extends TimerTask {
|
||||
|
||||
private PIDController m_controller;
|
||||
|
||||
public PIDTask(PIDController controller) {
|
||||
if (controller == null) {
|
||||
throw new NullPointerException("Given PIDController was null");
|
||||
}
|
||||
m_controller = controller;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
m_controller.calculate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a PID object with the given constants for P, I, D, and F
|
||||
* @param Kp the proportional coefficient
|
||||
* @param Ki the integral coefficient
|
||||
* @param Kd the derivative coefficient
|
||||
* @param Kf the feed forward term
|
||||
* @param source The PIDSource object that is used to get values
|
||||
* @param output The PIDOutput object that is set to the output percentage
|
||||
* @param period the loop time for doing calculations. This particularly effects calculations of the
|
||||
* integral and differential terms. The default is 50ms.
|
||||
*/
|
||||
public PIDController(double Kp, double Ki, double Kd, double Kf,
|
||||
PIDSource source, PIDOutput output,
|
||||
double period) {
|
||||
|
||||
if (source == null) {
|
||||
throw new NullPointerException("Null PIDSource was given");
|
||||
}
|
||||
if (output == null) {
|
||||
throw new NullPointerException("Null PIDOutput was given");
|
||||
}
|
||||
|
||||
m_controlLoop = new java.util.Timer();
|
||||
|
||||
|
||||
m_P = Kp;
|
||||
m_I = Ki;
|
||||
m_D = Kd;
|
||||
m_F = Kf;
|
||||
|
||||
m_pidInput = source;
|
||||
m_pidOutput = output;
|
||||
m_period = period;
|
||||
|
||||
m_controlLoop.schedule(new PIDTask(this), 0L, (long) (m_period * 1000));
|
||||
|
||||
instances++;
|
||||
UsageReporting.report(tResourceType.kResourceType_PIDController, instances);
|
||||
m_tolerance = new NullTolerance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a PID object with the given constants for P, I, D and period
|
||||
* @param Kp
|
||||
* @param Ki
|
||||
* @param Kd
|
||||
* @param source
|
||||
* @param output
|
||||
* @param period
|
||||
*/
|
||||
public PIDController(double Kp, double Ki, double Kd,
|
||||
PIDSource source, PIDOutput output,
|
||||
double period) {
|
||||
this(Kp, Ki, Kd, 0.0, source, output, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a PID object with the given constants for P, I, D, using a 50ms period.
|
||||
* @param Kp the proportional coefficient
|
||||
* @param Ki the integral coefficient
|
||||
* @param Kd the derivative coefficient
|
||||
* @param source The PIDSource object that is used to get values
|
||||
* @param output The PIDOutput object that is set to the output percentage
|
||||
*/
|
||||
public PIDController(double Kp, double Ki, double Kd,
|
||||
PIDSource source, PIDOutput output) {
|
||||
this(Kp, Ki, Kd, source, output, kDefaultPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a PID object with the given constants for P, I, D, using a 50ms period.
|
||||
* @param Kp the proportional coefficient
|
||||
* @param Ki the integral coefficient
|
||||
* @param Kd the derivative coefficient
|
||||
* @param source The PIDSource object that is used to get values
|
||||
* @param output The PIDOutput object that is set to the output percentage
|
||||
*/
|
||||
public PIDController(double Kp, double Ki, double Kd, double Kf,
|
||||
PIDSource source, PIDOutput output) {
|
||||
this(Kp, Ki, Kd, Kf, source, output, kDefaultPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the PID object
|
||||
*/
|
||||
public void free() {
|
||||
m_controlLoop.cancel();
|
||||
m_controlLoop = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the input, calculate the output accordingly, and write to the output.
|
||||
* This should only be called by the PIDTask
|
||||
* and is created during initialization.
|
||||
*/
|
||||
protected void calculate() {
|
||||
boolean enabled;
|
||||
PIDSource pidInput;
|
||||
|
||||
synchronized (this) {
|
||||
if (m_pidInput == null) {
|
||||
return;
|
||||
}
|
||||
if (m_pidOutput == null) {
|
||||
return;
|
||||
}
|
||||
enabled = m_enabled; // take snapshot of these values...
|
||||
pidInput = m_pidInput;
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
double input = pidInput.pidGet();
|
||||
double result;
|
||||
PIDOutput pidOutput = null;
|
||||
|
||||
synchronized (this) {
|
||||
m_error = m_setpoint - input;
|
||||
if (m_continuous) {
|
||||
if (Math.abs(m_error)
|
||||
> (m_maximumInput - m_minimumInput) / 2) {
|
||||
if (m_error > 0) {
|
||||
m_error = m_error - m_maximumInput + m_minimumInput;
|
||||
} else {
|
||||
m_error = m_error
|
||||
+ m_maximumInput - m_minimumInput;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_I != 0) {
|
||||
double potentialIGain = (m_totalError + m_error) * m_I;
|
||||
if (potentialIGain < m_maximumOutput) {
|
||||
if (potentialIGain > m_minimumOutput) {
|
||||
m_totalError += m_error;
|
||||
} else {
|
||||
m_totalError = m_minimumOutput / m_I;
|
||||
}
|
||||
} else {
|
||||
m_totalError = m_maximumOutput / m_I;
|
||||
}
|
||||
}
|
||||
|
||||
m_result = m_P * m_error + m_I * m_totalError + m_D * (m_error - m_prevError) + m_setpoint * m_F;
|
||||
m_prevError = m_error;
|
||||
|
||||
if (m_result > m_maximumOutput) {
|
||||
m_result = m_maximumOutput;
|
||||
} else if (m_result < m_minimumOutput) {
|
||||
m_result = m_minimumOutput;
|
||||
}
|
||||
pidOutput = m_pidOutput;
|
||||
result = m_result;
|
||||
}
|
||||
|
||||
pidOutput.pidWrite(result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PID Controller gain parameters.
|
||||
* Set the proportional, integral, and differential coefficients.
|
||||
* @param p Proportional coefficient
|
||||
* @param i Integral coefficient
|
||||
* @param d Differential coefficient
|
||||
*/
|
||||
public synchronized void setPID(double p, double i, double d) {
|
||||
m_P = p;
|
||||
m_I = i;
|
||||
m_D = d;
|
||||
|
||||
if (table != null) {
|
||||
table.putNumber("p", p);
|
||||
table.putNumber("i", i);
|
||||
table.putNumber("d", d);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PID Controller gain parameters.
|
||||
* Set the proportional, integral, and differential coefficients.
|
||||
* @param p Proportional coefficient
|
||||
* @param i Integral coefficient
|
||||
* @param d Differential coefficient
|
||||
* @param f Feed forward coefficient
|
||||
*/
|
||||
public synchronized void setPID(double p, double i, double d, double f) {
|
||||
m_P = p;
|
||||
m_I = i;
|
||||
m_D = d;
|
||||
m_F = f;
|
||||
|
||||
if (table != null) {
|
||||
table.putNumber("p", p);
|
||||
table.putNumber("i", i);
|
||||
table.putNumber("d", d);
|
||||
table.putNumber("f", f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Proportional coefficient
|
||||
* @return proportional coefficient
|
||||
*/
|
||||
public double getP() {
|
||||
return m_P;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Integral coefficient
|
||||
* @return integral coefficient
|
||||
*/
|
||||
public double getI() {
|
||||
return m_I;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Differential coefficient
|
||||
* @return differential coefficient
|
||||
*/
|
||||
public synchronized double getD() {
|
||||
return m_D;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Feed forward coefficient
|
||||
* @return feed forward coefficient
|
||||
*/
|
||||
public synchronized double getF() {
|
||||
return m_F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current PID result
|
||||
* This is always centered on zero and constrained the the max and min outs
|
||||
* @return the latest calculated output
|
||||
*/
|
||||
public synchronized double get() {
|
||||
return m_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PID controller to consider the input to be continuous,
|
||||
* Rather then using the max and min in as constraints, it considers them to
|
||||
* be the same point and automatically calculates the shortest route to
|
||||
* the setpoint.
|
||||
* @param continuous Set to true turns on continuous, false turns off continuous
|
||||
*/
|
||||
public synchronized void setContinuous(boolean continuous) {
|
||||
m_continuous = continuous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PID controller to consider the input to be continuous,
|
||||
* Rather then using the max and min in as constraints, it considers them to
|
||||
* be the same point and automatically calculates the shortest route to
|
||||
* the setpoint.
|
||||
*/
|
||||
public synchronized void setContinuous() {
|
||||
this.setContinuous(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum and minimum values expected from the input.
|
||||
*
|
||||
* @param minimumInput the minimum percentage expected from the input
|
||||
* @param maximumInput the maximum percentage expected from the output
|
||||
*/
|
||||
public synchronized void setInputRange(double minimumInput, double maximumInput) {
|
||||
if (minimumInput > maximumInput) {
|
||||
throw new BoundaryException("Lower bound is greater than upper bound");
|
||||
}
|
||||
m_minimumInput = minimumInput;
|
||||
m_maximumInput = maximumInput;
|
||||
setSetpoint(m_setpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum and maximum values to write.
|
||||
*
|
||||
* @param minimumOutput the minimum percentage to write to the output
|
||||
* @param maximumOutput the maximum percentage to write to the output
|
||||
*/
|
||||
public synchronized void setOutputRange(double minimumOutput, double maximumOutput) {
|
||||
if (minimumOutput > maximumOutput) {
|
||||
throw new BoundaryException("Lower bound is greater than upper bound");
|
||||
}
|
||||
m_minimumOutput = minimumOutput;
|
||||
m_maximumOutput = maximumOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the setpoint for the PIDController
|
||||
* @param setpoint the desired setpoint
|
||||
*/
|
||||
public synchronized void setSetpoint(double setpoint) {
|
||||
if (m_maximumInput > m_minimumInput) {
|
||||
if (setpoint > m_maximumInput) {
|
||||
m_setpoint = m_maximumInput;
|
||||
} else if (setpoint < m_minimumInput) {
|
||||
m_setpoint = m_minimumInput;
|
||||
} else {
|
||||
m_setpoint = setpoint;
|
||||
}
|
||||
} else {
|
||||
m_setpoint = setpoint;
|
||||
}
|
||||
|
||||
if (table != null)
|
||||
table.putNumber("setpoint", m_setpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current setpoint of the PIDController
|
||||
* @return the current setpoint
|
||||
*/
|
||||
public synchronized double getSetpoint() {
|
||||
return m_setpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current difference of the input from the setpoint
|
||||
* @return the current error
|
||||
*/
|
||||
public synchronized double getError() {
|
||||
//return m_error;
|
||||
return getSetpoint() - m_pidInput.pidGet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the percentage error which is considered tolerable for use with
|
||||
* OnTarget. (Input of 15.0 = 15 percent)
|
||||
* @param percent error which is tolerable
|
||||
* @deprecated Use setTolerance(Tolerance), i.e. setTolerance(new PIDController.PercentageTolerance(15))
|
||||
*/
|
||||
public synchronized void setTolerance(double percent) {
|
||||
m_tolerance = new PercentageTolerance(percent);
|
||||
}
|
||||
|
||||
/** Set the PID tolerance using a Tolerance object.
|
||||
* Tolerance can be specified as a percentage of the range or as an absolute
|
||||
* value. The Tolerance object encapsulates those options in an object. Use it by
|
||||
* creating the type of tolerance that you want to use: setTolerance(new PIDController.AbsoluteTolerance(0.1))
|
||||
* @param tolerance a tolerance object of the right type, e.g. PercentTolerance
|
||||
* or AbsoluteTolerance
|
||||
*/
|
||||
private void setTolerance(Tolerance tolerance) {
|
||||
m_tolerance = tolerance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the absolute error which is considered tolerable for use with
|
||||
* OnTarget.
|
||||
* @param absolute error which is tolerable in the units of the input object
|
||||
*/
|
||||
public synchronized void setAbsoluteTolerance(double absvalue) {
|
||||
m_tolerance = new AbsoluteTolerance(absvalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the percentage error which is considered tolerable for use with
|
||||
* OnTarget. (Input of 15.0 = 15 percent)
|
||||
* @param percent error which is tolerable
|
||||
*/
|
||||
public synchronized void setPercentTolerance(double percentage) {
|
||||
m_tolerance = new PercentageTolerance(percentage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the error is within the percentage of the total input range,
|
||||
* determined by setTolerance. This assumes that the maximum and minimum input
|
||||
* were set using setInput.
|
||||
* @return true if the error is less than the tolerance
|
||||
*/
|
||||
public synchronized boolean onTarget() {
|
||||
return m_tolerance.onTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin running the PIDController
|
||||
*/
|
||||
public synchronized void enable() {
|
||||
m_enabled = true;
|
||||
|
||||
if (table != null) {
|
||||
table.putBoolean("enabled", true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop running the PIDController, this sets the output to zero before stopping.
|
||||
*/
|
||||
public synchronized void disable() {
|
||||
m_pidOutput.pidWrite(0);
|
||||
m_enabled = false;
|
||||
|
||||
if (table != null) {
|
||||
table.putBoolean("enabled", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if PIDController is enabled.
|
||||
*/
|
||||
public synchronized boolean isEnable() {
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the previous error,, the integral term, and disable the controller.
|
||||
*/
|
||||
public synchronized void reset() {
|
||||
disable();
|
||||
m_prevError = 0;
|
||||
m_totalError = 0;
|
||||
m_result = 0;
|
||||
}
|
||||
|
||||
public String getSmartDashboardType() {
|
||||
return "PIDController";
|
||||
}
|
||||
|
||||
private ITableListener listener = new ITableListener() {
|
||||
public void valueChanged(ITable table, String key, Object value, boolean isNew) {
|
||||
if (key.equals("p") || key.equals("i") || key.equals("d") || key.equals("f")) {
|
||||
if (m_P != table.getNumber("p", 0.0) || m_I != table.getNumber("i", 0.0) ||
|
||||
m_D != table.getNumber("d", 0.0) || m_F != table.getNumber("f", 0.0))
|
||||
setPID(table.getNumber("p", 0.0), table.getNumber("i", 0.0), table.getNumber("d", 0.0), table.getNumber("f", 0.0));
|
||||
} else if (key.equals("setpoint")) {
|
||||
if (m_setpoint != ((Double) value).doubleValue())
|
||||
setSetpoint(((Double) value).doubleValue());
|
||||
} else if (key.equals("enabled")) {
|
||||
if (m_enabled != ((Boolean) value).booleanValue()) {
|
||||
if (((Boolean) value).booleanValue()) {
|
||||
enable();
|
||||
} else {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
private ITable table;
|
||||
public void initTable(ITable table) {
|
||||
if(this.table!=null)
|
||||
this.table.removeTableListener(listener);
|
||||
this.table = table;
|
||||
if(table!=null) {
|
||||
table.putNumber("p", getP());
|
||||
table.putNumber("i", getI());
|
||||
table.putNumber("d", getD());
|
||||
table.putNumber("f", getF());
|
||||
table.putNumber("setpoint", getSetpoint());
|
||||
table.putBoolean("enabled", isEnable());
|
||||
table.addTableListener(listener, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
* This interface allows PIDController to write it's results to its output.
|
||||
* @author dtjones
|
||||
*/
|
||||
public interface PIDOutput {
|
||||
|
||||
/**
|
||||
* Set the output to the value calculated by PIDController
|
||||
* @param output the value calculated by PIDController
|
||||
*/
|
||||
public void pidWrite(double output);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
* This interface allows for PIDController to automatically read from this
|
||||
* object
|
||||
* @author dtjones
|
||||
*/
|
||||
public interface PIDSource {
|
||||
|
||||
/**
|
||||
* A description for the type of output value to provide to a PIDController
|
||||
*/
|
||||
public static class PIDSourceParameter {
|
||||
public final int value;
|
||||
static final int kDistance_val = 0;
|
||||
static final int kRate_val = 1;
|
||||
static final int kAngle_val = 2;
|
||||
public static final PIDSourceParameter kDistance = new PIDSourceParameter(kDistance_val);
|
||||
public static final PIDSourceParameter kRate = new PIDSourceParameter(kRate_val);
|
||||
public static final PIDSourceParameter kAngle = new PIDSourceParameter(kAngle_val);
|
||||
|
||||
private PIDSourceParameter(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result to use in PIDController
|
||||
* @return the result to use in PIDController
|
||||
*/
|
||||
public double pidGet();
|
||||
}
|
||||
@@ -1,481 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
|
||||
/**
|
||||
* Class implements the PWM generation in the FPGA.
|
||||
* Values supplied as arguments for PWM outputs range from -1.0 to 1.0. They are mapped
|
||||
* to the hardware dependent values, in this case 0-255 for the FPGA.
|
||||
* Changes are immediately sent to the FPGA, and the update occurs at the next
|
||||
* FPGA cycle. There is no delay.
|
||||
*
|
||||
* As of revision 0.1.4 of the FPGA, the FPGA interprets the 0-255 values as follows:
|
||||
* 255 = full "forward"
|
||||
* 254 to 129 = linear scaling from "full forward" to "center"
|
||||
* 128 = center value
|
||||
* 127 to 2 = linear scaling from "center" to "full reverse"
|
||||
* 1 = full "reverse"
|
||||
* 0 = disabled (i.e. PWM output is held low)
|
||||
*/
|
||||
public class PWM extends SensorBase implements LiveWindowSendable {
|
||||
|
||||
/*
|
||||
* XXX: Refactor to no longer depend on the DigitalModule, and move all
|
||||
* resource tracking into the HAL. This will wait until we get the unit
|
||||
* tests running for the first time.
|
||||
*/
|
||||
|
||||
private static Resource allocated = new Resource((HALLibrary.dio_kNumSystems.get() * kPwmChannels));
|
||||
|
||||
/**
|
||||
* Represents the amount to multiply the minimum servo-pulse pwm period by.
|
||||
*/
|
||||
public static class PeriodMultiplier {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int k1X_val = 1;
|
||||
static final int k2X_val = 2;
|
||||
static final int k4X_val = 4;
|
||||
/**
|
||||
* Period Multiplier: don't skip pulses
|
||||
*/
|
||||
public static final PeriodMultiplier k1X = new PeriodMultiplier(k1X_val);
|
||||
/**
|
||||
* Period Multiplier: skip every other pulse
|
||||
*/
|
||||
public static final PeriodMultiplier k2X = new PeriodMultiplier(k2X_val);
|
||||
/**
|
||||
* Period Multiplier: skip three out of four pulses
|
||||
*/
|
||||
public static final PeriodMultiplier k4X = new PeriodMultiplier(k4X_val);
|
||||
|
||||
private PeriodMultiplier(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
private int m_channel;
|
||||
private DigitalModule m_module;
|
||||
/**
|
||||
* kDefaultPwmPeriod is in ms
|
||||
*
|
||||
* - 20ms periods (50 Hz) are the "safest" setting in that this works for all devices
|
||||
* - 20ms periods seem to be desirable for Vex Motors
|
||||
* - 20ms periods are the specified period for HS-322HD servos, but work reliably down
|
||||
* to 10.0 ms; starting at about 8.5ms, the servo sometimes hums and get hot;
|
||||
* by 5.0ms the hum is nearly continuous
|
||||
* - 10ms periods work well for Victor 884
|
||||
* - 5ms periods allows higher update rates for Luminary Micro Jaguar speed controllers.
|
||||
* Due to the shipping firmware on the Jaguar, we can't run the update period less
|
||||
* than 5.05 ms.
|
||||
*
|
||||
* kDefaultPwmPeriod is the 1x period (5.05 ms). In hardware, the period scaling is implemented as an
|
||||
* output squelch to get longer periods for old devices.
|
||||
*/
|
||||
protected static final double kDefaultPwmPeriod = 5.05;
|
||||
/**
|
||||
* kDefaultPwmCenter is the PWM range center in ms
|
||||
*/
|
||||
protected static final double kDefaultPwmCenter = 1.5;
|
||||
/**
|
||||
* kDefaultPWMStepsDown is the number of PWM steps below the centerpoint
|
||||
*/
|
||||
protected static final int kDefaultPwmStepsDown = 1000;
|
||||
public static final int kPwmDisabled = 0;
|
||||
boolean m_eliminateDeadband;
|
||||
int m_maxPwm;
|
||||
int m_deadbandMaxPwm;
|
||||
int m_centerPwm;
|
||||
int m_deadbandMinPwm;
|
||||
int m_minPwm;
|
||||
|
||||
/**
|
||||
* Initialize PWMs given an module and channel.
|
||||
*
|
||||
* This method is private and is the common path for all the constructors for creating PWM
|
||||
* instances. Checks module and channel value ranges and allocates the appropriate channel.
|
||||
* The allocation is only done to help users ensure that they don't double assign channels.
|
||||
*/
|
||||
private void initPWM(final int moduleNumber, final int channel) {
|
||||
checkPWMModule(moduleNumber);
|
||||
checkPWMChannel(channel);
|
||||
try {
|
||||
allocated.allocate((moduleNumber - 1) * kPwmChannels + channel - 1);
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException(
|
||||
"PWM channel " + channel + " on module " + moduleNumber + " is already allocated");
|
||||
}
|
||||
m_channel = channel;
|
||||
m_module = DigitalModule.getInstance(moduleNumber);
|
||||
m_module.setPWM(m_channel, kPwmDisabled);
|
||||
m_eliminateDeadband = false;
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_PWM, channel, moduleNumber-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a PWM given a module and channel.
|
||||
* Allocate a PWM using a module and channel number.
|
||||
*
|
||||
* @param moduleNumber The module number of the digital module to use.
|
||||
* @param channel The PWM channel on the digital module.
|
||||
*/
|
||||
public PWM(final int moduleNumber, final int channel) {
|
||||
initPWM(moduleNumber, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a PWM in the default module given a channel.
|
||||
*
|
||||
* Using a default module allocate a PWM given the channel number.
|
||||
*
|
||||
* @param channel The PWM channel on the digital module.
|
||||
*/
|
||||
public PWM(final int channel) {
|
||||
initPWM(getDefaultDigitalModule(), channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the PWM channel.
|
||||
*
|
||||
* Free the resource associated with the PWM channel and set the value to 0.
|
||||
*/
|
||||
public void free() {
|
||||
m_module.setPWM(m_channel, kPwmDisabled);
|
||||
m_module.freeDIO(m_channel);
|
||||
allocated.free((m_module.getModuleNumber() - 1) * kPwmChannels + m_channel - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally eliminate the deadband from a speed controller.
|
||||
* @param eliminateDeadband If true, set the motor curve on the Jaguar to eliminate
|
||||
* the deadband in the middle of the range. Otherwise, keep the full range without
|
||||
* modifying any values.
|
||||
*/
|
||||
public void enableDeadbandElimination(boolean eliminateDeadband) {
|
||||
m_eliminateDeadband = eliminateDeadband;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bounds on the PWM values.
|
||||
* This sets the bounds on the PWM values for a particular each type of controller. The values
|
||||
* determine the upper and lower speeds as well as the deadband bracket.
|
||||
* @deprecated Recommended to set bounds in ms using {@link #setBounds(double, double, double, double, double)}
|
||||
* @param max The Minimum pwm value
|
||||
* @param deadbandMax The high end of the deadband range
|
||||
* @param center The center speed (off)
|
||||
* @param deadbandMin The low end of the deadband range
|
||||
* @param min The minimum pwm value
|
||||
*/
|
||||
public void setBounds(final int max, final int deadbandMax, final int center, final int deadbandMin, final int min) {
|
||||
m_maxPwm = max;
|
||||
m_deadbandMaxPwm = deadbandMax;
|
||||
m_centerPwm = center;
|
||||
m_deadbandMinPwm = deadbandMin;
|
||||
m_minPwm = min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bounds on the PWM pulse widths.
|
||||
* This sets the bounds on the PWM values for a particular type of controller. The values
|
||||
* determine the upper and lower speeds as well as the deadband bracket.
|
||||
* @param max The max PWM pulse width in ms
|
||||
* @param deadbandMax The high end of the deadband range pulse width in ms
|
||||
* @param center The center (off) pulse width in ms
|
||||
* @param deadbandMin The low end of the deadband pulse width in ms
|
||||
* @param min The minimum pulse width in ms
|
||||
*/
|
||||
void setBounds(double max, double deadbandMax, double center, double deadbandMin, double min) {
|
||||
double loopTime = m_module.getLoopTiming()/(kSystemClockTicksPerMicrosecond*1e3);
|
||||
|
||||
m_maxPwm = (int)((max-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_deadbandMaxPwm = (int)((deadbandMax-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_centerPwm = (int)((center-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_deadbandMinPwm = (int)((deadbandMin-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
m_minPwm = (int)((min-kDefaultPwmCenter)/loopTime+kDefaultPwmStepsDown-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the module number associated with the PWM Object.
|
||||
*
|
||||
* @return The module's number.
|
||||
*/
|
||||
public int getModuleNumber() {
|
||||
return m_module.getModuleNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the channel number associated with the PWM Object.
|
||||
*
|
||||
* @return The channel number.
|
||||
*/
|
||||
public int getChannel() {
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a position.
|
||||
*
|
||||
* This is intended to be used by servos.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @param pos The position to set the servo between 0.0 and 1.0.
|
||||
*/
|
||||
public void setPosition(double pos) {
|
||||
if (pos < 0.0) {
|
||||
pos = 0.0;
|
||||
} else if (pos > 1.0) {
|
||||
pos = 1.0;
|
||||
}
|
||||
|
||||
int rawValue;
|
||||
// note, need to perform the multiplication below as floating point before converting to int
|
||||
rawValue = (int) ((pos * (double)getFullRangeScaleFactor()) + getMinNegativePwm());
|
||||
|
||||
// send the computed pwm value to the FPGA
|
||||
setRaw(rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of a position.
|
||||
*
|
||||
* This is intended to be used by servos.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @return The position the servo is set to between 0.0 and 1.0.
|
||||
*/
|
||||
public double getPosition() {
|
||||
int value = getRaw();
|
||||
if (value < getMinNegativePwm()) {
|
||||
return 0.0;
|
||||
} else if (value > getMaxPositivePwm()) {
|
||||
return 1.0;
|
||||
} else {
|
||||
return (double)(value - getMinNegativePwm()) / (double)getFullRangeScaleFactor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a speed.
|
||||
*
|
||||
* This is intended to be used by speed controllers.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinPositivePwm() called.
|
||||
* @pre SetCenterPwm() called.
|
||||
* @pre SetMaxNegativePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @param speed The speed to set the speed controller between -1.0 and 1.0.
|
||||
*/
|
||||
final void setSpeed(double speed) {
|
||||
// clamp speed to be in the range 1.0 >= speed >= -1.0
|
||||
if (speed < -1.0) {
|
||||
speed = -1.0;
|
||||
} else if (speed > 1.0) {
|
||||
speed = 1.0;
|
||||
}
|
||||
|
||||
// calculate the desired output pwm value by scaling the speed appropriately
|
||||
int rawValue;
|
||||
if (speed == 0.0) {
|
||||
rawValue = getCenterPwm();
|
||||
} else if (speed > 0.0) {
|
||||
rawValue = (int) (speed * ((double)getPositiveScaleFactor()) +
|
||||
((double)getMinPositivePwm()) + 0.5);
|
||||
} else {
|
||||
rawValue = (int) (speed * ((double)getNegativeScaleFactor()) +
|
||||
((double)getMaxNegativePwm()) + 0.5);
|
||||
}
|
||||
|
||||
// send the computed pwm value to the FPGA
|
||||
setRaw(rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of speed.
|
||||
*
|
||||
* This is intended to be used by speed controllers.
|
||||
*
|
||||
* @pre SetMaxPositivePwm() called.
|
||||
* @pre SetMinPositivePwm() called.
|
||||
* @pre SetMaxNegativePwm() called.
|
||||
* @pre SetMinNegativePwm() called.
|
||||
*
|
||||
* @return The most recently set speed between -1.0 and 1.0.
|
||||
*/
|
||||
public double getSpeed() {
|
||||
int value = getRaw();
|
||||
if (value > getMaxPositivePwm()) {
|
||||
return 1.0;
|
||||
} else if (value < getMinNegativePwm()) {
|
||||
return -1.0;
|
||||
} else if (value > getMinPositivePwm()) {
|
||||
return (double) (value - getMinPositivePwm()) / (double)getPositiveScaleFactor();
|
||||
} else if (value < getMaxNegativePwm()) {
|
||||
return (double) (value - getMaxNegativePwm()) / (double)getNegativeScaleFactor();
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value directly to the hardware.
|
||||
*
|
||||
* Write a raw value to a PWM channel.
|
||||
*
|
||||
* @param value Raw PWM value. Range 0 - 255.
|
||||
*/
|
||||
public void setRaw(int value) {
|
||||
m_module.setPWM(m_channel, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value directly from the hardware.
|
||||
*
|
||||
* Read a raw value from a PWM channel.
|
||||
*
|
||||
* @return Raw PWM control value. Range: 0 - 255.
|
||||
*/
|
||||
public int getRaw() {
|
||||
return m_module.getPWM(m_channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Slow down the PWM signal for old devices.
|
||||
*
|
||||
* @param mult The period multiplier to apply to this channel
|
||||
*/
|
||||
public void setPeriodMultiplier(PeriodMultiplier mult) {
|
||||
switch (mult.value) {
|
||||
case PeriodMultiplier.k4X_val:
|
||||
m_module.setPWMPeriodScale(m_channel, 3); // Squelch 3 out of 4 outputs
|
||||
break;
|
||||
case PeriodMultiplier.k2X_val:
|
||||
m_module.setPWMPeriodScale(m_channel, 1); // Squelch 1 out of 2 outputs
|
||||
break;
|
||||
case PeriodMultiplier.k1X_val:
|
||||
m_module.setPWMPeriodScale(m_channel, 0); // Don't squelch any outputs
|
||||
break;
|
||||
default:
|
||||
//Cannot hit this, limited by PeriodMultiplier enum
|
||||
}
|
||||
}
|
||||
|
||||
private int getMaxPositivePwm() {
|
||||
return m_maxPwm;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getMinPositivePwm() {
|
||||
return m_eliminateDeadband ? m_deadbandMaxPwm : m_centerPwm + 1;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getCenterPwm() {
|
||||
return m_centerPwm;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getMaxNegativePwm() {
|
||||
return m_eliminateDeadband ? m_deadbandMinPwm : m_centerPwm - 1;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getMinNegativePwm() {
|
||||
return m_minPwm;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
private int getPositiveScaleFactor() {
|
||||
return getMaxPositivePwm() - getMinPositivePwm();
|
||||
} ///< The scale for positive speeds.
|
||||
|
||||
private int getNegativeScaleFactor() {
|
||||
return getMaxNegativePwm() - getMinNegativePwm();
|
||||
} ///< The scale for negative speeds.
|
||||
|
||||
private int getFullRangeScaleFactor() {
|
||||
return getMaxPositivePwm() - getMinNegativePwm();
|
||||
} ///< The scale for positions.
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Speed Controller";
|
||||
}
|
||||
private ITable m_table;
|
||||
private ITableListener m_table_listener;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getSpeed());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
setSpeed(0); // Stop for safety
|
||||
m_table_listener = new ITableListener() {
|
||||
public void valueChanged(ITable itable, String key, Object value, boolean bln) {
|
||||
setSpeed(((Double) value).doubleValue());
|
||||
}
|
||||
};
|
||||
m_table.addTableListener("Value", m_table_listener, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
setSpeed(0); // Stop for safety
|
||||
// TODO: Broken, should only remove the listener from "Value" only.
|
||||
m_table.removeTableListener(m_table_listener);
|
||||
}
|
||||
}
|
||||
@@ -1,828 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.networktables.NetworkTable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
|
||||
/**
|
||||
* The preferences class provides a relatively simple way to save important
|
||||
* values to the cRIO to access the next time the cRIO is booted.
|
||||
*
|
||||
* <p>This class loads and saves from a file inside the cRIO. The user can not
|
||||
* access the file directly, but may modify values at specific fields which will
|
||||
* then be saved to the file when {@link Preferences#save() save()} is
|
||||
* called.</p>
|
||||
*
|
||||
* <p>This class is thread safe.</p>
|
||||
*
|
||||
* <p>This will also interact with {@link NetworkTable} by creating a table
|
||||
* called "Preferences" with all the key-value pairs. To save using
|
||||
* {@link NetworkTable}, simply set the boolean at position ~S A V E~ to true.
|
||||
* Also, if the value of any variable is " in the {@link NetworkTable}, then
|
||||
* that represents non-existence in the {@link Preferences} table</p>
|
||||
*
|
||||
* @author Joe Grinstead
|
||||
*/
|
||||
public class Preferences {
|
||||
|
||||
/**
|
||||
* The Preferences table name
|
||||
*/
|
||||
private static final String TABLE_NAME = "Preferences";
|
||||
/**
|
||||
* The value of the save field
|
||||
*/
|
||||
private static final String SAVE_FIELD = "~S A V E~";
|
||||
/**
|
||||
* The file to save to
|
||||
*/
|
||||
private static final String FILE_NAME = "file:///wpilib-preferences.ini";
|
||||
/**
|
||||
* The characters to put between a field and value
|
||||
*/
|
||||
private static final byte[] VALUE_PREFIX = {'=', '\"'};
|
||||
/**
|
||||
* The characters to put after the value
|
||||
*/
|
||||
private static final byte[] VALUE_SUFFIX = {'\"', '\n'};
|
||||
/**
|
||||
* The newline character
|
||||
*/
|
||||
private static final byte[] NEW_LINE = {'\n'};
|
||||
/**
|
||||
* The singleton instance
|
||||
*/
|
||||
private static Preferences instance;
|
||||
|
||||
/**
|
||||
* Returns the preferences instance.
|
||||
*
|
||||
* @return the preferences instance
|
||||
*/
|
||||
public synchronized static Preferences getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Preferences();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
/**
|
||||
* The semaphore for beginning reads and writes to the file
|
||||
*/
|
||||
private final Object fileLock = new Object();
|
||||
/**
|
||||
* The semaphore for reading from the table
|
||||
*/
|
||||
private final Object lock = new Object();
|
||||
/**
|
||||
* The actual values (String->String)
|
||||
*/
|
||||
private Hashtable values;
|
||||
/**
|
||||
* The keys in the order they were read from the file
|
||||
*/
|
||||
private Vector keys;
|
||||
/**
|
||||
* The comments that were in the file sorted by which key they appeared over
|
||||
* (String->Comment)
|
||||
*/
|
||||
private Hashtable comments;
|
||||
/**
|
||||
* The comment at the end of the file
|
||||
*/
|
||||
private Comment endComment;
|
||||
|
||||
/**
|
||||
* Creates a preference class that will automatically read the file in a
|
||||
* different thread. Any call to its methods will be blocked until the
|
||||
* thread is finished reading.
|
||||
*/
|
||||
private Preferences() {
|
||||
values = new Hashtable();
|
||||
keys = new Vector();
|
||||
|
||||
// We synchronized on fileLock and then wait
|
||||
// for it to know that the reading thread has started
|
||||
synchronized (fileLock) {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
read();
|
||||
}
|
||||
} .start();
|
||||
try {
|
||||
fileLock.wait();
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Preferences, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a vector of the keys
|
||||
*/
|
||||
public Vector getKeys() {
|
||||
synchronized (lock) {
|
||||
return keys;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given value into the given key position
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @throws ImproperPreferenceKeyException if the key contains an illegal
|
||||
* character
|
||||
*/
|
||||
private void put(String key, String value) {
|
||||
synchronized (lock) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
ImproperPreferenceKeyException.confirmString(key);
|
||||
if (values.put(key, value) == null) {
|
||||
keys.addElement(key);
|
||||
}
|
||||
NetworkTable.getTable(TABLE_NAME).putString(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given string into the preferences table.
|
||||
*
|
||||
* <p>The value may not have quotation marks, nor may the key have any
|
||||
* whitespace nor an equals sign</p>
|
||||
*
|
||||
* <p>This will <b>NOT</b> save the value to memory between power cycles, to
|
||||
* do that you must call {@link Preferences#save() save()} (which must be
|
||||
* used with care). at some point after calling this.</p>
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @throws NullPointerException if value is null
|
||||
* @throws IllegalArgumentException if value contains a quotation mark
|
||||
* @throws ImproperPreferenceKeyException if the key contains any whitespace
|
||||
* or an equals sign
|
||||
*/
|
||||
public void putString(String key, String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (value.indexOf('"') != -1) {
|
||||
throw new IllegalArgumentException("Can not put string:" + value + " because it contains quotation marks");
|
||||
}
|
||||
put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given int into the preferences table.
|
||||
*
|
||||
* <p>The key may not have any whitespace nor an equals sign</p>
|
||||
*
|
||||
* <p>This will <b>NOT</b> save the value to memory between power cycles, to
|
||||
* do that you must call {@link Preferences#save() save()} (which must be
|
||||
* used with care) at some point after calling this.</p>
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @throws ImproperPreferenceKeyException if the key contains any whitespace
|
||||
* or an equals sign
|
||||
*/
|
||||
public void putInt(String key, int value) {
|
||||
put(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given double into the preferences table.
|
||||
*
|
||||
* <p>The key may not have any whitespace nor an equals sign</p>
|
||||
*
|
||||
* <p>This will <b>NOT</b> save the value to memory between power cycles, to
|
||||
* do that you must call {@link Preferences#save() save()} (which must be
|
||||
* used with care) at some point after calling this.</p>
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @throws ImproperPreferenceKeyException if the key contains any whitespace
|
||||
* or an equals sign
|
||||
*/
|
||||
public void putDouble(String key, double value) {
|
||||
put(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given float into the preferences table.
|
||||
*
|
||||
* <p>The key may not have any whitespace nor an equals sign</p>
|
||||
*
|
||||
* <p>This will <b>NOT</b> save the value to memory between power cycles, to
|
||||
* do that you must call {@link Preferences#save() save()} (which must be
|
||||
* used with care) at some point after calling this.</p>
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @throws ImproperPreferenceKeyException if the key contains any whitespace
|
||||
* or an equals sign
|
||||
*/
|
||||
public void putFloat(String key, float value) {
|
||||
put(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given boolean into the preferences table.
|
||||
*
|
||||
* <p>The key may not have any whitespace nor an equals sign</p>
|
||||
*
|
||||
* <p>This will <b>NOT</b> save the value to memory between power cycles, to
|
||||
* do that you must call {@link Preferences#save() save()} (which must be
|
||||
* used with care) at some point after calling this.</p>
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @throws ImproperPreferenceKeyException if the key contains any whitespace
|
||||
* or an equals sign
|
||||
*/
|
||||
public void putBoolean(String key, boolean value) {
|
||||
put(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given long into the preferences table.
|
||||
*
|
||||
* <p>The key may not have any whitespace nor an equals sign</p>
|
||||
*
|
||||
* <p>This will <b>NOT</b> save the value to memory between power cycles, to
|
||||
* do that you must call {@link Preferences#save() save()} (which must be
|
||||
* used with care) at some point after calling this.</p>
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @throws ImproperPreferenceKeyException if the key contains any whitespace
|
||||
* or an equals sign
|
||||
*/
|
||||
public void putLong(String key, long value) {
|
||||
put(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value at the given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @return the value (or null if none exists)
|
||||
* @throws NullPointerException if the key is null
|
||||
*/
|
||||
private String get(String key) {
|
||||
synchronized (lock) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return (String) values.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not there is a key with the given name.
|
||||
*
|
||||
* @param key the key
|
||||
* @return if there is a value at the given key
|
||||
* @throws NullPointerException if key is null
|
||||
*/
|
||||
public boolean containsKey(String key) {
|
||||
return get(key) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a preference
|
||||
*
|
||||
* @param key the key
|
||||
* @throws NullPointerException if key is null
|
||||
*/
|
||||
public void remove(String key) {
|
||||
synchronized (lock) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
values.remove(key);
|
||||
keys.removeElement(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string at the given key. If this table does not have a value
|
||||
* for that position, then the given backup value will be returned.
|
||||
*
|
||||
* @param key the key
|
||||
* @param backup the value to return if none exists in the table
|
||||
* @return either the value in the table, or the backup
|
||||
* @throws NullPointerException if the key is null
|
||||
*/
|
||||
public String getString(String key, String backup) {
|
||||
String value = get(key);
|
||||
return value == null ? backup : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the int at the given key. If this table does not have a value for
|
||||
* that position, then the given backup value will be returned.
|
||||
*
|
||||
* @param key the key
|
||||
* @param backup the value to return if none exists in the table
|
||||
* @return either the value in the table, or the backup
|
||||
* @throws IncompatibleTypeException if the value in the table can not be
|
||||
* converted to an int
|
||||
*/
|
||||
public int getInt(String key, int backup) {
|
||||
String value = get(key);
|
||||
if (value == null) {
|
||||
return backup;
|
||||
} else {
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IncompatibleTypeException(value, "int");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the double at the given key. If this table does not have a value
|
||||
* for that position, then the given backup value will be returned.
|
||||
*
|
||||
* @param key the key
|
||||
* @param backup the value to return if none exists in the table
|
||||
* @return either the value in the table, or the backup
|
||||
* @throws IncompatibleTypeException if the value in the table can not be
|
||||
* converted to an double
|
||||
*/
|
||||
public double getDouble(String key, double backup) {
|
||||
String value = get(key);
|
||||
if (value == null) {
|
||||
return backup;
|
||||
} else {
|
||||
try {
|
||||
return Double.parseDouble(value);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IncompatibleTypeException(value, "double");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the boolean at the given key. If this table does not have a value
|
||||
* for that position, then the given backup value will be returned.
|
||||
*
|
||||
* @param key the key
|
||||
* @param backup the value to return if none exists in the table
|
||||
* @return either the value in the table, or the backup
|
||||
* @throws IncompatibleTypeException if the value in the table can not be
|
||||
* converted to a boolean
|
||||
*/
|
||||
public boolean getBoolean(String key, boolean backup) {
|
||||
String value = get(key);
|
||||
if (value == null) {
|
||||
return backup;
|
||||
} else {
|
||||
if (value.equalsIgnoreCase("true")) {
|
||||
return true;
|
||||
} else if (value.equalsIgnoreCase("false")) {
|
||||
return false;
|
||||
} else {
|
||||
throw new IncompatibleTypeException(value, "boolean");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the float at the given key. If this table does not have a value
|
||||
* for that position, then the given backup value will be returned.
|
||||
*
|
||||
* @param key the key
|
||||
* @param backup the value to return if none exists in the table
|
||||
* @return either the value in the table, or the backup
|
||||
* @throws IncompatibleTypeException if the value in the table can not be
|
||||
* converted to a float
|
||||
*/
|
||||
public float getFloat(String key, float backup) {
|
||||
String value = get(key);
|
||||
if (value == null) {
|
||||
return backup;
|
||||
} else {
|
||||
try {
|
||||
return Float.parseFloat(value);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IncompatibleTypeException(value, "float");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long at the given key. If this table does not have a value
|
||||
* for that position, then the given backup value will be returned.
|
||||
*
|
||||
* @param key the key
|
||||
* @param backup the value to return if none exists in the table
|
||||
* @return either the value in the table, or the backup
|
||||
* @throws IncompatibleTypeException if the value in the table can not be
|
||||
* converted to a long
|
||||
*/
|
||||
public long getLong(String key, long backup) {
|
||||
String value = get(key);
|
||||
if (value == null) {
|
||||
put(key, String.valueOf(backup));
|
||||
return backup;
|
||||
} else {
|
||||
try {
|
||||
return Long.parseLong(value);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IncompatibleTypeException(value, "long");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the preferences to a file on the cRIO.
|
||||
*
|
||||
* <p>This should <b>NOT</b> be called often. Too many writes can damage the
|
||||
* cRIO's flash memory. While it is ok to save once or twice a match, this
|
||||
* should never be called every run of
|
||||
* {@link IterativeRobot#teleopPeriodic()}.</p>
|
||||
*
|
||||
* <p>The actual writing of the file is done in a separate thread. However,
|
||||
* any call to a get or put method will wait until the table is fully saved
|
||||
* before continuing.</p>
|
||||
*/
|
||||
public void save() {
|
||||
synchronized (fileLock) {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
write();
|
||||
}
|
||||
} .start();
|
||||
try {
|
||||
fileLock.wait();
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method that actually writes the table to a file. This is called
|
||||
* in its own thread when {@link Preferences#save() save()} is called.
|
||||
*/
|
||||
private void write() {
|
||||
synchronized (lock) {
|
||||
synchronized (fileLock) {
|
||||
fileLock.notifyAll();
|
||||
}
|
||||
|
||||
File file = null;
|
||||
FileOutputStream output = null;
|
||||
try {
|
||||
file = new File(FILE_NAME);
|
||||
|
||||
if (file.exists())
|
||||
file.delete();
|
||||
|
||||
file.createNewFile();
|
||||
|
||||
output = new FileOutputStream(file);
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = (String) keys.elementAt(i);
|
||||
String value = (String) values.get(key);
|
||||
|
||||
if (comments != null) {
|
||||
Comment comment = (Comment) comments.get(key);
|
||||
if (comment != null) {
|
||||
comment.write(output);
|
||||
}
|
||||
}
|
||||
|
||||
output.write(key.getBytes());
|
||||
output.write(VALUE_PREFIX);
|
||||
output.write(value.getBytes());
|
||||
output.write(VALUE_SUFFIX);
|
||||
}
|
||||
|
||||
if (endComment != null) {
|
||||
endComment.write(output);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
if (output != null) {
|
||||
try {
|
||||
output.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
NetworkTable.getTable(TABLE_NAME).putBoolean(SAVE_FIELD, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The internal method to read from a file. This will be called in its own
|
||||
* thread when the preferences singleton is first created.
|
||||
*/
|
||||
private void read() {
|
||||
class EndOfStreamException extends Exception {
|
||||
}
|
||||
|
||||
class Reader {
|
||||
|
||||
InputStream stream;
|
||||
|
||||
Reader(InputStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public char read() throws IOException, EndOfStreamException {
|
||||
int input = stream.read();
|
||||
if (input == -1) {
|
||||
throw new EndOfStreamException();
|
||||
} else {
|
||||
// Check for carriage returns
|
||||
return input == '\r' ? '\n' : (char) input;
|
||||
}
|
||||
}
|
||||
|
||||
char readWithoutWhitespace() throws IOException, EndOfStreamException {
|
||||
while (true) {
|
||||
char value = read();
|
||||
switch (value) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
continue;
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (lock) {
|
||||
synchronized (fileLock) {
|
||||
fileLock.notifyAll();
|
||||
}
|
||||
|
||||
Comment comment = null;
|
||||
|
||||
|
||||
|
||||
File file = null;
|
||||
FileInputStream input = null;
|
||||
try {
|
||||
file = new File(FILE_NAME);
|
||||
|
||||
if (file.exists()) {
|
||||
input = new FileInputStream(file);
|
||||
Reader reader = new Reader(input);
|
||||
|
||||
StringBuffer buffer;
|
||||
|
||||
while (true) {
|
||||
char value = reader.readWithoutWhitespace();
|
||||
|
||||
if (value == '\n' || value == ';') {
|
||||
if (comment == null) {
|
||||
comment = new Comment();
|
||||
}
|
||||
|
||||
if (value == '\n') {
|
||||
comment.addBytes(NEW_LINE);
|
||||
} else {
|
||||
buffer = new StringBuffer(30);
|
||||
for (; value != '\n'; value = reader.read()) {
|
||||
buffer.append(value);
|
||||
}
|
||||
buffer.append('\n');
|
||||
comment.addBytes(buffer.toString().getBytes());
|
||||
}
|
||||
} else {
|
||||
buffer = new StringBuffer(30);
|
||||
for (; value != '='; value = reader.readWithoutWhitespace()) {
|
||||
buffer.append(value);
|
||||
}
|
||||
String name = buffer.toString();
|
||||
buffer = new StringBuffer(30);
|
||||
|
||||
boolean shouldBreak = false;
|
||||
|
||||
value = reader.readWithoutWhitespace();
|
||||
if (value == '"') {
|
||||
for (value = reader.read(); value != '"'; value = reader.read()) {
|
||||
buffer.append(value);
|
||||
}
|
||||
// Clear the line
|
||||
while (reader.read() != '\n');
|
||||
} else {
|
||||
try {
|
||||
for (; value != '\n'; value = reader.readWithoutWhitespace()) {
|
||||
buffer.append(value);
|
||||
}
|
||||
} catch (EndOfStreamException e) {
|
||||
shouldBreak = true;
|
||||
}
|
||||
}
|
||||
|
||||
String result = buffer.toString();
|
||||
|
||||
keys.addElement(name);
|
||||
values.put(name, result);
|
||||
NetworkTable.getTable(TABLE_NAME).putString(name, result);
|
||||
|
||||
if (comment != null) {
|
||||
if (comments == null) {
|
||||
comments = new Hashtable();
|
||||
}
|
||||
comments.put(name, comment);
|
||||
comment = null;
|
||||
}
|
||||
|
||||
System.out.println(name + "=" + values.get(name));
|
||||
|
||||
if (shouldBreak) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
} catch (EndOfStreamException ex) {
|
||||
System.out.println("Done Reading");
|
||||
}
|
||||
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
if (comment != null) {
|
||||
endComment = comment;
|
||||
}
|
||||
}
|
||||
|
||||
NetworkTable.getTable(TABLE_NAME).putBoolean(SAVE_FIELD, false);
|
||||
// TODO: Verify that this works even though it changes with subtables.
|
||||
// Should work since preferences shouldn't have subtables.
|
||||
NetworkTable.getTable(TABLE_NAME).addTableListener(new ITableListener() {
|
||||
public void valueChanged(ITable source, String key, Object value, boolean isNew) {
|
||||
if (key.equals(SAVE_FIELD)) {
|
||||
if (((Boolean) value).booleanValue()) {
|
||||
save();
|
||||
}
|
||||
} else {
|
||||
synchronized (lock) {
|
||||
if (!ImproperPreferenceKeyException.isAcceptable(key) || value.toString().indexOf('"') != -1) {
|
||||
if (values.contains(key) || keys.contains(key)) {
|
||||
values.remove(key);
|
||||
keys.removeElement(key);
|
||||
NetworkTable.getTable(TABLE_NAME).putString(key, "\"");
|
||||
}
|
||||
} else {
|
||||
if (values.put(key, value.toString()) == null) {
|
||||
keys.addElement(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A class representing some comment lines in the ini file. This is used so
|
||||
* that if a programmer ever directly modifies the ini file, then his/her
|
||||
* comments will still be there after {@link Preferences#save() save()} is
|
||||
* called.
|
||||
*/
|
||||
private static class Comment {
|
||||
|
||||
/**
|
||||
* A vector of byte arrays. Each array represents a line to write
|
||||
*/
|
||||
private Vector bytes = new Vector();
|
||||
|
||||
/**
|
||||
* Appends the given bytes to the comment.
|
||||
*
|
||||
* @param bytes the bytes to add
|
||||
*/
|
||||
private void addBytes(byte[] bytes) {
|
||||
this.bytes.addElement(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes this comment to the given stream
|
||||
*
|
||||
* @param stream the stream to write to
|
||||
* @throws IOException if the stream has a problem
|
||||
*/
|
||||
private void write(OutputStream stream) throws IOException {
|
||||
for (int i = 0; i < bytes.size(); i++) {
|
||||
stream.write((byte[]) bytes.elementAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This exception is thrown if the a value requested cannot be converted to
|
||||
* the requested type.
|
||||
*/
|
||||
public static class IncompatibleTypeException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Creates an exception with a description based on the input
|
||||
*
|
||||
* @param value the value that can not be converted
|
||||
* @param type the type that the value can not be converted to
|
||||
*/
|
||||
public IncompatibleTypeException(String value, String type) {
|
||||
super("Cannot convert \"" + value + "\" into " + type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be thrown if a string can not be used as a key in the preferences
|
||||
* file. This happens if the string contains a new line, a space, a tab, or
|
||||
* an equals sign.
|
||||
*/
|
||||
public static class ImproperPreferenceKeyException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Instantiates an exception with a descriptive message based on the
|
||||
* input.
|
||||
*
|
||||
* @param value the illegal key
|
||||
* @param letter the specific character that made it illegal
|
||||
*/
|
||||
public ImproperPreferenceKeyException(String value, char letter) {
|
||||
super("Preference key \""
|
||||
+ value + "\" is not allowed to contain letter with ASCII code:" + (byte) letter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the given string is ok to use as a key in the preference
|
||||
* table. If not, then a {@link ImproperPreferenceKeyException} will be
|
||||
* thrown.
|
||||
*
|
||||
* @param value the value to test
|
||||
*/
|
||||
public static void confirmString(String value) {
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char letter = value.charAt(i);
|
||||
switch (letter) {
|
||||
case '=':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case ' ':
|
||||
case '\t':
|
||||
throw new ImproperPreferenceKeyException(value, letter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the given string is ok to use in the
|
||||
* preference table.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static boolean isAcceptable(String value) {
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char letter = value.charAt(i);
|
||||
switch (letter) {
|
||||
case '=':
|
||||
case '\n':
|
||||
case '\r':
|
||||
case ' ':
|
||||
case '\t':
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,440 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.IDeviceController;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
|
||||
/**
|
||||
* Class for VEX Robotics Spike style relay outputs. Relays are intended to be
|
||||
* connected to Spikes or similar relays. The relay channels controls a pair of
|
||||
* pins that are either both off, one on, the other on, or both on. This
|
||||
* translates into two Spike outputs at 0v, one at 12v and one at 0v, one at 0v
|
||||
* and the other at 12v, or two Spike outputs at 12V. This allows off, full
|
||||
* forward, or full reverse control of motors without variable speed. It also
|
||||
* allows the two 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 IDeviceController,
|
||||
LiveWindowSendable {
|
||||
|
||||
/*
|
||||
* XXX: Refactor to no longer depend on the DigitalModule, and move all
|
||||
* resource tracking into the HAL. This will wait until we get the unit
|
||||
* tests running for the first time.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class represents errors in trying to set relay values contradictory
|
||||
* to the direction to which the relay is set.
|
||||
*/
|
||||
public class InvalidValueException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new exception with the given message
|
||||
*
|
||||
* @param message
|
||||
* the message to pass with the exception
|
||||
*/
|
||||
public InvalidValueException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The state to drive a Relay to.
|
||||
*/
|
||||
public static class Value {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kOff_val = 0;
|
||||
static final int kOn_val = 1;
|
||||
static final int kForward_val = 2;
|
||||
static final int kReverse_val = 3;
|
||||
/**
|
||||
* value: off
|
||||
*/
|
||||
public static final Value kOff = new Value(kOff_val);
|
||||
/**
|
||||
* value: on for relays with defined direction
|
||||
*/
|
||||
public static final Value kOn = new Value(kOn_val);
|
||||
/**
|
||||
* value: forward
|
||||
*/
|
||||
public static final Value kForward = new Value(kForward_val);
|
||||
/**
|
||||
* value: reverse
|
||||
*/
|
||||
public static final Value kReverse = new Value(kReverse_val);
|
||||
|
||||
private Value(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Direction(s) that a relay is configured to operate in.
|
||||
*/
|
||||
public static class Direction {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kBoth_val = 0;
|
||||
static final int kForward_val = 1;
|
||||
static final int kReverse_val = 2;
|
||||
/**
|
||||
* direction: both directions are valid
|
||||
*/
|
||||
public static final Direction kBoth = new Direction(kBoth_val);
|
||||
/**
|
||||
* direction: Only forward is valid
|
||||
*/
|
||||
public static final Direction kForward = new Direction(kForward_val);
|
||||
/**
|
||||
* direction: only reverse is valid
|
||||
*/
|
||||
public static final Direction kReverse = new Direction(kReverse_val);
|
||||
|
||||
private Direction(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int m_channel;
|
||||
private Direction m_direction;
|
||||
private DigitalModule m_module;
|
||||
private static Resource relayChannels = new Resource(
|
||||
HALLibrary.dio_kNumSystems.get() * kRelayChannels * 2);
|
||||
|
||||
/**
|
||||
* Common relay initialization method. This code is common to all Relay
|
||||
* constructors and initializes the relay and reserves all resources that
|
||||
* need to be locked. Initially the relay is set to both lines at 0v.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the digital module to use.
|
||||
*/
|
||||
private void initRelay(final int moduleNumber) {
|
||||
SensorBase.checkRelayModule(moduleNumber);
|
||||
SensorBase.checkRelayChannel(m_channel);
|
||||
try {
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kForward) {
|
||||
relayChannels.allocate(((moduleNumber - 1) * kRelayChannels
|
||||
+ m_channel - 1) * 2);
|
||||
UsageReporting.report(tResourceType.kResourceType_Relay,
|
||||
m_channel, moduleNumber - 1);
|
||||
}
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kReverse) {
|
||||
relayChannels.allocate(((moduleNumber - 1) * kRelayChannels
|
||||
+ m_channel - 1) * 2 + 1);
|
||||
UsageReporting.report(tResourceType.kResourceType_Relay,
|
||||
m_channel + 128, moduleNumber - 1);
|
||||
}
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException("Relay channel " + m_channel
|
||||
+ " on module " + moduleNumber + " is already allocated");
|
||||
}
|
||||
m_module = DigitalModule.getInstance(moduleNumber);
|
||||
m_module.setRelayForward(m_channel, false);
|
||||
m_module.setRelayReverse(m_channel, false);
|
||||
LiveWindow.addActuator("Relay", moduleNumber, m_channel, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Relay constructor given the module and the channel.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the digital module to use.
|
||||
* @param channel
|
||||
* The channel number within the module for this relay.
|
||||
* @param direction
|
||||
* The direction that the Relay object will control.
|
||||
*/
|
||||
public Relay(final int moduleNumber, final int channel, Direction direction) {
|
||||
if (direction == null)
|
||||
throw new NullPointerException("Null Direction was given");
|
||||
m_channel = channel;
|
||||
m_direction = direction;
|
||||
initRelay(moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Relay constructor given a channel only where the default digital module
|
||||
* is used.
|
||||
*
|
||||
* @param channel
|
||||
* The channel number within the default module for this relay.
|
||||
* @param direction
|
||||
* The direction that the Relay object will control.
|
||||
*/
|
||||
public Relay(final int channel, Direction direction) {
|
||||
if (direction == null)
|
||||
throw new NullPointerException("Null Direction was given");
|
||||
m_channel = channel;
|
||||
m_direction = direction;
|
||||
initRelay(getDefaultDigitalModule());
|
||||
}
|
||||
|
||||
/**
|
||||
* Relay constructor given the module and the channel, allowing both
|
||||
* directions.
|
||||
*
|
||||
* @param moduleNumber
|
||||
* The number of the digital module to use.
|
||||
* @param channel
|
||||
* The channel number within the module for this relay.
|
||||
*/
|
||||
public Relay(final int moduleNumber, final int channel) {
|
||||
m_channel = channel;
|
||||
m_direction = Direction.kBoth;
|
||||
initRelay(moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Relay constructor given a channel only where the default digital module
|
||||
* is used, allowing both directions.
|
||||
*
|
||||
* @param channel
|
||||
* The channel number within the default module for this relay.
|
||||
*/
|
||||
public Relay(final int channel) {
|
||||
m_channel = channel;
|
||||
m_direction = Direction.kBoth;
|
||||
initRelay(getDefaultDigitalModule());
|
||||
}
|
||||
|
||||
public void free() {
|
||||
m_module.setRelayForward(m_channel, false);
|
||||
m_module.setRelayReverse(m_channel, false);
|
||||
|
||||
if (m_direction == Direction.kBoth || m_direction == Direction.kForward) {
|
||||
relayChannels.free(((m_module.getModuleNumber() - 1)
|
||||
* kRelayChannels + m_channel - 1) * 2);
|
||||
m_module.freeDIO(((m_module.getModuleNumber() - 1) * kRelayChannels
|
||||
+ m_channel - 1) * 2);
|
||||
}
|
||||
if (m_direction == Direction.kBoth || m_direction == Direction.kReverse) {
|
||||
relayChannels.free(((m_module.getModuleNumber() - 1)
|
||||
* kRelayChannels + m_channel - 1) * 2 + 1);
|
||||
m_module.freeDIO(((m_module.getModuleNumber() - 1) * kRelayChannels
|
||||
+ m_channel - 1) * 2 + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relay state.
|
||||
*
|
||||
* Valid values depend on which directions of the relay are controlled by
|
||||
* the object.
|
||||
*
|
||||
* When set to kBothDirections, the relay can be set to any of the four
|
||||
* states: 0v-0v, 12v-0v, 0v-12v, 12v-12v
|
||||
*
|
||||
* When set to kForwardOnly or kReverseOnly, you can specify the constant
|
||||
* for the direction or you can simply specify kOff_val and kOn_val. Using
|
||||
* only kOff_val and kOn_val is recommended.
|
||||
*
|
||||
* @param value
|
||||
* The state to set the relay.
|
||||
*/
|
||||
public void set(Value value) {
|
||||
switch (value.value) {
|
||||
case Value.kOff_val:
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kForward) {
|
||||
m_module.setRelayForward(m_channel, false);
|
||||
}
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kReverse) {
|
||||
m_module.setRelayReverse(m_channel, false);
|
||||
}
|
||||
break;
|
||||
case Value.kOn_val:
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kForward) {
|
||||
m_module.setRelayForward(m_channel, true);
|
||||
}
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kReverse) {
|
||||
m_module.setRelayReverse(m_channel, true);
|
||||
}
|
||||
break;
|
||||
case Value.kForward_val:
|
||||
if (m_direction == Direction.kReverse)
|
||||
throw new InvalidValueException(
|
||||
"A relay configured for reverse cannot be set to forward");
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kForward) {
|
||||
m_module.setRelayForward(m_channel, true);
|
||||
}
|
||||
if (m_direction == Direction.kBoth) {
|
||||
m_module.setRelayReverse(m_channel, false);
|
||||
}
|
||||
break;
|
||||
case Value.kReverse_val:
|
||||
if (m_direction == Direction.kForward)
|
||||
throw new InvalidValueException(
|
||||
"A relay configured for forward cannot be set to reverse");
|
||||
if (m_direction == Direction.kBoth) {
|
||||
m_module.setRelayForward(m_channel, false);
|
||||
}
|
||||
if (m_direction == Direction.kBoth
|
||||
|| m_direction == Direction.kReverse) {
|
||||
m_module.setRelayReverse(m_channel, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Cannot hit this, limited by Value enum
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Relay State
|
||||
*
|
||||
* Gets the current state of the relay.
|
||||
*
|
||||
* When set to kForwardOnly or kReverseOnly, value is returned as kOn/kOff
|
||||
* not kForward/kReverse (per the recommendation in Set)
|
||||
*
|
||||
* @return The current state of the relay as a Relay::Value
|
||||
*/
|
||||
public Value get() {
|
||||
if (m_module.getRelayForward(m_channel)) {
|
||||
if (m_module.getRelayReverse(m_channel)) {
|
||||
return Value.kOn;
|
||||
} else {
|
||||
if (m_direction == Direction.kForward) {
|
||||
return Value.kOn;
|
||||
} else {
|
||||
return Value.kForward;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_module.getRelayReverse(m_channel)) {
|
||||
if (m_direction == Direction.kForward) {
|
||||
return Value.kOn;
|
||||
} else {
|
||||
return Value.kReverse;
|
||||
}
|
||||
} else {
|
||||
return Value.kOff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Relay Direction
|
||||
*
|
||||
* Changes which values the relay can be set to depending on which direction
|
||||
* is used
|
||||
*
|
||||
* Valid inputs are kBothDirections, kForwardOnly, and kReverseOnly
|
||||
*
|
||||
* @param direction
|
||||
* The direction for the relay to operate in
|
||||
*/
|
||||
public void setDirection(Direction direction) {
|
||||
if (direction == null)
|
||||
throw new NullPointerException("Null Direction was given");
|
||||
if (m_direction == direction) {
|
||||
return;
|
||||
}
|
||||
|
||||
free();
|
||||
|
||||
m_direction = direction;
|
||||
|
||||
initRelay(m_module.getModuleNumber());
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Relay";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
private ITableListener m_table_listener;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
if (get() == Value.kOn) {
|
||||
m_table.putString("Value", "On");
|
||||
} else if (get() == Value.kForward) {
|
||||
m_table.putString("Value", "Forward");
|
||||
} else if (get() == Value.kReverse) {
|
||||
m_table.putString("Value", "Reverse");
|
||||
} else {
|
||||
m_table.putString("Value", "Off");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
m_table_listener = new ITableListener() {
|
||||
public void valueChanged(ITable itable, String key, Object value,
|
||||
boolean bln) {
|
||||
String val = ((String) value);
|
||||
if (val.equals("Off")) {
|
||||
set(Value.kOff);
|
||||
} else if (val.equals("Forward")) {
|
||||
set(Value.kForward);
|
||||
} else if (val.equals("Reverse")) {
|
||||
set(Value.kReverse);
|
||||
}
|
||||
}
|
||||
};
|
||||
m_table.addTableListener("Value", m_table_listener, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
// TODO: Broken, should only remove the listener from "Value" only.
|
||||
m_table.removeTableListener(m_table_listener);
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
|
||||
/**
|
||||
* Track resources in the program.
|
||||
* The Resource class is a convenient way of keeping track of allocated arbitrary resources
|
||||
* in the program. Resources are just indicies that have an lower and upper bound that are
|
||||
* tracked by this class. In the library they are used for tracking allocation of hardware channels
|
||||
* but this is purely arbitrary. The resource class does not do any actual allocation, but
|
||||
* simply tracks if a given index is currently in use.
|
||||
*
|
||||
* WARNING: this should only be statically allocated. When the program loads into memory all the
|
||||
* static constructors are called. At that time a linked list of all the "Resources" is created.
|
||||
* Then when the program actually starts - in the Robot constructor, all resources are initialized.
|
||||
* This ensures that the program is restartable in memory without having to unload/reload.
|
||||
*/
|
||||
public class Resource {
|
||||
|
||||
private static Resource m_resourceList = null;
|
||||
private final boolean m_numAllocated[];
|
||||
private final int m_size;
|
||||
private final Resource m_nextResource;
|
||||
|
||||
/**
|
||||
* Clears all allocated resources
|
||||
*/
|
||||
public static void restartProgram() {
|
||||
for (Resource r = Resource.m_resourceList; r != null; r = r.m_nextResource) {
|
||||
for (int i = 0; i < r.m_size; i++) {
|
||||
r.m_numAllocated[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate storage for a new instance of Resource.
|
||||
* Allocate a bool array of values that will get initialized to indicate that no resources
|
||||
* have been allocated yet. The indicies of the resources are 0..size-1.
|
||||
*
|
||||
* @param size The number of blocks to allocate
|
||||
*/
|
||||
public Resource(final int size) {
|
||||
m_size = size;
|
||||
m_numAllocated = new boolean[m_size];
|
||||
for (int i = 0; i < m_size; i++) {
|
||||
m_numAllocated[i] = false;
|
||||
}
|
||||
m_nextResource = Resource.m_resourceList;
|
||||
Resource.m_resourceList = this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a resource.
|
||||
* When a resource is requested, mark it allocated. In this case, a free resource value
|
||||
* within the range is located and returned after it is marked allocated.
|
||||
*
|
||||
* @return The index of the allocated block.
|
||||
* @throws CheckedAllocationException If there are no resources available to be allocated.
|
||||
*/
|
||||
public int allocate() throws CheckedAllocationException {
|
||||
for (int i = 0; i < m_size; i++) {
|
||||
if (m_numAllocated[i] == false) {
|
||||
m_numAllocated[i] = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
throw new CheckedAllocationException("No available resources");
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a specific resource value.
|
||||
* The user requests a specific resource value, i.e. channel number and it is verified
|
||||
* unallocated, then returned.
|
||||
*
|
||||
* @param index The resource to allocate
|
||||
* @return The index of the allocated block
|
||||
* @throws CheckedAllocationException If there are no resources available to be allocated.
|
||||
*/
|
||||
public int allocate(final int index) throws CheckedAllocationException {
|
||||
if (index >= m_size) {
|
||||
throw new CheckedAllocationException("Index " + index + " out of range");
|
||||
}
|
||||
if (m_numAllocated[index] == true) {
|
||||
throw new CheckedAllocationException("Resource at index " + index + " already allocated");
|
||||
}
|
||||
m_numAllocated[index] = true;
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free an allocated resource.
|
||||
* After a resource is no longer needed, for example a destructor is called for a channel assignment
|
||||
* class, Free will release the resource value so it can be reused somewhere else in the program.
|
||||
*
|
||||
* @param index The index of the resource to free.
|
||||
*/
|
||||
public void free(final int index) {
|
||||
if (m_numAllocated[index] == false)
|
||||
throw new AllocationException("No resource available to be freed");
|
||||
m_numAllocated[index] = false;
|
||||
}
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tInstances;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.networktables.NetworkTable;
|
||||
|
||||
/**
|
||||
* Implement a Robot Program framework.
|
||||
* The RobotBase class is intended to be subclassed by a user creating a robot program.
|
||||
* Overridden autonomous() and operatorControl() methods are called at the appropriate time
|
||||
* as the match proceeds. In the current implementation, the Autonomous code will run to
|
||||
* completion before the OperatorControl code could start. In the future the Autonomous code
|
||||
* might be spawned as a task, then killed at the end of the Autonomous period.
|
||||
*/
|
||||
public abstract class RobotBase {
|
||||
/**
|
||||
* The VxWorks priority that robot code should work at (so Java code should run at)
|
||||
*/
|
||||
public static final int ROBOT_TASK_PRIORITY = 101;
|
||||
|
||||
/**
|
||||
* Boolean System property. If true (default), send System.err messages to the driver station.
|
||||
*/
|
||||
public final static String ERRORS_TO_DRIVERSTATION_PROP = "first.driverstation.senderrors";
|
||||
|
||||
protected final DriverStation m_ds;
|
||||
|
||||
/**
|
||||
* Constructor for a generic robot program.
|
||||
* User code should be placed in the constructor that runs before the Autonomous or Operator
|
||||
* Control period starts. The constructor will run to completion before Autonomous is entered.
|
||||
*
|
||||
* This must be used to ensure that the communications code starts. In the future it would be
|
||||
* nice to put this code into it's own task that loads on boot so ensure that it runs.
|
||||
*/
|
||||
protected RobotBase() {
|
||||
// TODO: StartCAPI();
|
||||
// TODO: See if the next line is necessary
|
||||
// Resource.RestartProgram();
|
||||
|
||||
// if (getBooleanProperty(ERRORS_TO_DRIVERSTATION_PROP, true)) {
|
||||
// Utility.sendErrorStreamToDriverStation(true);
|
||||
// }
|
||||
NetworkTable.setServerMode();//must be before b
|
||||
m_ds = DriverStation.getInstance();
|
||||
NetworkTable.getTable(""); // forces network tables to initialize
|
||||
NetworkTable.getTable("LiveWindow").getSubTable("~STATUS~").putBoolean("LW Enabled", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resources for a RobotBase class.
|
||||
*/
|
||||
public void free() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This has been deprecated in favor of {@link #isEnabled()}
|
||||
* Check on the overall status of the system.
|
||||
*
|
||||
* @return Is the system active (i.e. PWM motor outputs, etc. enabled)?
|
||||
*/
|
||||
public boolean isSystemActive() {
|
||||
return isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the Robot is currently disabled.
|
||||
* @return True if the Robot is currently disabled by the field controls.
|
||||
*/
|
||||
public boolean isDisabled() {
|
||||
return m_ds.isDisabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the Robot is currently enabled.
|
||||
* @return True if the Robot is currently enabled by the field controls.
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return m_ds.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the robot is currently in Autonomous mode.
|
||||
* @return True if the robot is currently operating Autonomously as determined by the field controls.
|
||||
*/
|
||||
public boolean isAutonomous() {
|
||||
return m_ds.isAutonomous();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the robot is currently in Test mode
|
||||
* @return True if the robot is currently operating in Test mode as determined by the driver station.
|
||||
*/
|
||||
public boolean isTest() {
|
||||
return m_ds.isTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the robot is currently in Operator Control mode.
|
||||
* @return True if the robot is currently operating in Tele-Op mode as determined by the field controls.
|
||||
*/
|
||||
public boolean isOperatorControl() {
|
||||
return m_ds.isOperatorControl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if new data is available from the driver station.
|
||||
* @return Has new data arrived over the network since the last time this function was called?
|
||||
*/
|
||||
public boolean isNewDataAvailable() {
|
||||
return m_ds.isNewControlData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an alternate "main loop" via startCompetition().
|
||||
*/
|
||||
public abstract void startCompetition();
|
||||
|
||||
public static boolean getBooleanProperty(String name, boolean defaultValue) {
|
||||
String propVal = System.getProperty(name);
|
||||
if (propVal == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (propVal.equalsIgnoreCase("false")) {
|
||||
return false;
|
||||
} else if (propVal.equalsIgnoreCase("true")) {
|
||||
return true;
|
||||
} else {
|
||||
throw new IllegalStateException(propVal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting point for the applications. Starts the OtaServer and then runs
|
||||
* the robot.
|
||||
* @throws javax.microedition.midlet.MIDletStateChangeException
|
||||
*/
|
||||
public static void main(String args[]) { // TODO: expose main to teams?{
|
||||
boolean errorOnExit = false;
|
||||
|
||||
HALLibrary.FRC_NetworkCommunication_Reserve();
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramStarting();
|
||||
|
||||
UsageReporting.report(tResourceType.kResourceType_Language, tInstances.kLanguage_Java);
|
||||
|
||||
String robotName = "";
|
||||
Enumeration<URL> resources = null;
|
||||
try {
|
||||
resources = RobotBase.class.getClassLoader().getResources("META-INF/MANIFEST.MF");
|
||||
} catch (IOException e) {e.printStackTrace();}
|
||||
while (resources != null && resources.hasMoreElements()) {
|
||||
try {
|
||||
Manifest manifest = new Manifest(resources.nextElement().openStream());
|
||||
robotName = manifest.getMainAttributes().getValue("Robot-Class");
|
||||
} catch (IOException e) {e.printStackTrace();}
|
||||
}
|
||||
|
||||
RobotBase robot;
|
||||
try {
|
||||
robot = (RobotBase) Class.forName(robotName).newInstance();
|
||||
} catch (InstantiationException|IllegalAccessException|ClassNotFoundException e) {
|
||||
System.err.println("WARNING: Robots don't quit!");
|
||||
System.err.println("ERROR: Could not instantiate robot "+robotName+"!");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
robot.startCompetition();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
errorOnExit = true;
|
||||
} finally {
|
||||
// startCompetition never returns unless exception occurs....
|
||||
System.err.println("WARNING: Robots don't quit!");
|
||||
if (errorOnExit) {
|
||||
System.err.println("---> The startCompetition() method (or methods called by it) should have handled the exception above.");
|
||||
} else {
|
||||
System.err.println("---> Unexpected return from startCompetition() method.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,760 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.can.CANNotInitializedException;
|
||||
import edu.wpi.first.wpilibj.can.CANTimeoutException;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tInstances;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.parsing.IUtility;
|
||||
|
||||
/**
|
||||
* Utility class for handling Robot drive based on a definition of the motor configuration.
|
||||
* The robot drive class handles basic driving for a robot. Currently, 2 and 4 motor standard
|
||||
* drive trains are supported. In the future other drive types like swerve and meccanum might
|
||||
* be implemented. Motor channel numbers are passed supplied on creation of the class. Those are
|
||||
* used for either the drive function (intended for hand created drive code, such as autonomous)
|
||||
* or with the Tank/Arcade functions intended to be used for Operator Control driving.
|
||||
*/
|
||||
public class RobotDrive implements MotorSafety, IUtility {
|
||||
|
||||
protected MotorSafetyHelper m_safetyHelper;
|
||||
|
||||
/**
|
||||
* The location of a motor on the robot for the purpose of driving
|
||||
*/
|
||||
public static class MotorType {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kFrontLeft_val = 0;
|
||||
static final int kFrontRight_val = 1;
|
||||
static final int kRearLeft_val = 2;
|
||||
static final int kRearRight_val = 3;
|
||||
/**
|
||||
* motortype: front left
|
||||
*/
|
||||
public static final MotorType kFrontLeft = new MotorType(kFrontLeft_val);
|
||||
/**
|
||||
* motortype: front right
|
||||
*/
|
||||
public static final MotorType kFrontRight = new MotorType(kFrontRight_val);
|
||||
/**
|
||||
* motortype: rear left
|
||||
*/
|
||||
public static final MotorType kRearLeft = new MotorType(kRearLeft_val);
|
||||
/**
|
||||
* motortype: rear right
|
||||
*/
|
||||
public static final MotorType kRearRight = new MotorType(kRearRight_val);
|
||||
|
||||
private MotorType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
public static final double kDefaultExpirationTime = 0.1;
|
||||
public static final double kDefaultSensitivity = 0.5;
|
||||
public static final double kDefaultMaxOutput = 1.0;
|
||||
protected static final int kMaxNumberOfMotors = 4;
|
||||
protected final int m_invertedMotors[] = new int[4];
|
||||
protected double m_sensitivity;
|
||||
protected double m_maxOutput;
|
||||
protected SpeedController m_frontLeftMotor;
|
||||
protected SpeedController m_frontRightMotor;
|
||||
protected SpeedController m_rearLeftMotor;
|
||||
protected SpeedController m_rearRightMotor;
|
||||
protected boolean m_allocatedSpeedControllers;
|
||||
protected boolean m_isCANInitialized = true;
|
||||
protected static boolean kArcadeRatioCurve_Reported = false;
|
||||
protected static boolean kTank_Reported = false;
|
||||
protected static boolean kArcadeStandard_Reported = false;
|
||||
protected static boolean kMecanumCartesian_Reported = false;
|
||||
protected static boolean kMecanumPolar_Reported = false;
|
||||
|
||||
/** Constructor for RobotDrive with 2 motors specified with channel numbers.
|
||||
* Set up parameters for a two wheel drive system where the
|
||||
* left and right motor pwm channels are specified in the call.
|
||||
* This call assumes Jaguars for controlling the motors.
|
||||
* @param leftMotorChannel The PWM channel number on the default digital module that drives the left motor.
|
||||
* @param rightMotorChannel The PWM channel number on the default digital module that drives the right motor.
|
||||
*/
|
||||
public RobotDrive(final int leftMotorChannel, final int rightMotorChannel) {
|
||||
m_sensitivity = kDefaultSensitivity;
|
||||
m_maxOutput = kDefaultMaxOutput;
|
||||
m_frontLeftMotor = null;
|
||||
m_rearLeftMotor = new Jaguar(leftMotorChannel);
|
||||
m_frontRightMotor = null;
|
||||
m_rearRightMotor = new Jaguar(rightMotorChannel);
|
||||
for (int i = 0; i < kMaxNumberOfMotors; i++) {
|
||||
m_invertedMotors[i] = 1;
|
||||
}
|
||||
m_allocatedSpeedControllers = true;
|
||||
setupMotorSafety();
|
||||
drive(0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for RobotDrive with 4 motors specified with channel numbers.
|
||||
* Set up parameters for a four wheel drive system where all four motor
|
||||
* pwm channels are specified in the call.
|
||||
* This call assumes Jaguars for controlling the motors.
|
||||
* @param frontLeftMotor Front left motor channel number on the default digital module
|
||||
* @param rearLeftMotor Rear Left motor channel number on the default digital module
|
||||
* @param frontRightMotor Front right motor channel number on the default digital module
|
||||
* @param rearRightMotor Rear Right motor channel number on the default digital module
|
||||
*/
|
||||
public RobotDrive(final int frontLeftMotor, final int rearLeftMotor,
|
||||
final int frontRightMotor, final int rearRightMotor) {
|
||||
m_sensitivity = kDefaultSensitivity;
|
||||
m_maxOutput = kDefaultMaxOutput;
|
||||
m_rearLeftMotor = new Jaguar(rearLeftMotor);
|
||||
m_rearRightMotor = new Jaguar(rearRightMotor);
|
||||
m_frontLeftMotor = new Jaguar(frontLeftMotor);
|
||||
m_frontRightMotor = new Jaguar(frontRightMotor);
|
||||
for (int i = 0; i < kMaxNumberOfMotors; i++) {
|
||||
m_invertedMotors[i] = 1;
|
||||
}
|
||||
m_allocatedSpeedControllers = true;
|
||||
setupMotorSafety();
|
||||
drive(0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for RobotDrive with 2 motors specified as SpeedController objects.
|
||||
* The SpeedController version of the constructor enables programs to use the RobotDrive classes with
|
||||
* subclasses of the SpeedController objects, for example, versions with ramping or reshaping of
|
||||
* the curve to suit motor bias or dead-band elimination.
|
||||
* @param leftMotor The left SpeedController object used to drive the robot.
|
||||
* @param rightMotor the right SpeedController object used to drive the robot.
|
||||
*/
|
||||
public RobotDrive(SpeedController leftMotor, SpeedController rightMotor) {
|
||||
if (leftMotor == null || rightMotor == null) {
|
||||
m_rearLeftMotor = m_rearRightMotor = null;
|
||||
throw new NullPointerException("Null motor provided");
|
||||
}
|
||||
m_frontLeftMotor = null;
|
||||
m_rearLeftMotor = leftMotor;
|
||||
m_frontRightMotor = null;
|
||||
m_rearRightMotor = rightMotor;
|
||||
m_sensitivity = kDefaultSensitivity;
|
||||
m_maxOutput = kDefaultMaxOutput;
|
||||
for (int i = 0; i < kMaxNumberOfMotors; i++) {
|
||||
m_invertedMotors[i] = 1;
|
||||
}
|
||||
m_allocatedSpeedControllers = false;
|
||||
setupMotorSafety();
|
||||
drive(0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for RobotDrive with 4 motors specified as SpeedController objects.
|
||||
* Speed controller input version of RobotDrive (see previous comments).
|
||||
* @param rearLeftMotor The back left SpeedController object used to drive the robot.
|
||||
* @param frontLeftMotor The front left SpeedController object used to drive the robot
|
||||
* @param rearRightMotor The back right SpeedController object used to drive the robot.
|
||||
* @param frontRightMotor The front right SpeedController object used to drive the robot.
|
||||
*/
|
||||
public RobotDrive(SpeedController frontLeftMotor, SpeedController rearLeftMotor,
|
||||
SpeedController frontRightMotor, SpeedController rearRightMotor) {
|
||||
if (frontLeftMotor == null || rearLeftMotor == null || frontRightMotor == null || rearRightMotor == null) {
|
||||
m_frontLeftMotor = m_rearLeftMotor = m_frontRightMotor = m_rearRightMotor = null;
|
||||
throw new NullPointerException("Null motor provided");
|
||||
}
|
||||
m_frontLeftMotor = frontLeftMotor;
|
||||
m_rearLeftMotor = rearLeftMotor;
|
||||
m_frontRightMotor = frontRightMotor;
|
||||
m_rearRightMotor = rearRightMotor;
|
||||
m_sensitivity = kDefaultSensitivity;
|
||||
m_maxOutput = kDefaultMaxOutput;
|
||||
for (int i = 0; i < kMaxNumberOfMotors; i++) {
|
||||
m_invertedMotors[i] = 1;
|
||||
}
|
||||
m_allocatedSpeedControllers = false;
|
||||
setupMotorSafety();
|
||||
drive(0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drive the motors at "speed" and "curve".
|
||||
*
|
||||
* The speed and curve are -1.0 to +1.0 values where 0.0 represents stopped and
|
||||
* not turning. The algorithm for adding in the direction attempts to provide a constant
|
||||
* turn radius for differing speeds.
|
||||
*
|
||||
* This function will most likely be used in an autonomous routine.
|
||||
*
|
||||
* @param outputMagnitude The forward component of the output magnitude to send to the motors.
|
||||
* @param curve The rate of turn, constant for different forward speeds.
|
||||
*/
|
||||
public void drive(double outputMagnitude, double curve) {
|
||||
double leftOutput, rightOutput;
|
||||
|
||||
if(!kArcadeRatioCurve_Reported) {
|
||||
UsageReporting.report(tResourceType.kResourceType_RobotDrive, getNumMotors(), tInstances.kRobotDrive_ArcadeRatioCurve);
|
||||
kArcadeRatioCurve_Reported = true;
|
||||
}
|
||||
if (curve < 0) {
|
||||
double value = Math.log(-curve);
|
||||
double ratio = (value - m_sensitivity) / (value + m_sensitivity);
|
||||
if (ratio == 0) {
|
||||
ratio = .0000000001;
|
||||
}
|
||||
leftOutput = outputMagnitude / ratio;
|
||||
rightOutput = outputMagnitude;
|
||||
} else if (curve > 0) {
|
||||
double value = Math.log(curve);
|
||||
double ratio = (value - m_sensitivity) / (value + m_sensitivity);
|
||||
if (ratio == 0) {
|
||||
ratio = .0000000001;
|
||||
}
|
||||
leftOutput = outputMagnitude;
|
||||
rightOutput = outputMagnitude / ratio;
|
||||
} else {
|
||||
leftOutput = outputMagnitude;
|
||||
rightOutput = outputMagnitude;
|
||||
}
|
||||
setLeftRightMotorOutputs(leftOutput, rightOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide tank steering using the stored robot configuration.
|
||||
* drive the robot using two joystick inputs. The Y-axis will be selected from
|
||||
* each Joystick object.
|
||||
* @param leftStick The joystick to control the left side of the robot.
|
||||
* @param rightStick The joystick to control the right side of the robot.
|
||||
*/
|
||||
public void tankDrive(GenericHID leftStick, GenericHID rightStick) {
|
||||
if (leftStick == null || rightStick == null) {
|
||||
throw new NullPointerException("Null HID provided");
|
||||
}
|
||||
tankDrive(leftStick.getY(), rightStick.getY(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide tank steering using the stored robot configuration.
|
||||
* drive the robot using two joystick inputs. The Y-axis will be selected from
|
||||
* each Joystick object.
|
||||
* @param leftStick The joystick to control the left side of the robot.
|
||||
* @param rightStick The joystick to control the right side of the robot.
|
||||
* @param squaredInputs Setting this parameter to true decreases the sensitivity at lower speeds
|
||||
*/
|
||||
public void tankDrive(GenericHID leftStick, GenericHID rightStick, boolean squaredInputs) {
|
||||
if (leftStick == null || rightStick == null) {
|
||||
throw new NullPointerException("Null HID provided");
|
||||
}
|
||||
tankDrive(leftStick.getY(), rightStick.getY(), squaredInputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide tank steering using the stored robot configuration.
|
||||
* This function lets you pick the axis to be used on each Joystick object for the left
|
||||
* and right sides of the robot.
|
||||
* @param leftStick The Joystick object to use for the left side of the robot.
|
||||
* @param leftAxis The axis to select on the left side Joystick object.
|
||||
* @param rightStick The Joystick object to use for the right side of the robot.
|
||||
* @param rightAxis The axis to select on the right side Joystick object.
|
||||
*/
|
||||
public void tankDrive(GenericHID leftStick, final int leftAxis,
|
||||
GenericHID rightStick, final int rightAxis) {
|
||||
if (leftStick == null || rightStick == null) {
|
||||
throw new NullPointerException("Null HID provided");
|
||||
}
|
||||
tankDrive(leftStick.getRawAxis(leftAxis), rightStick.getRawAxis(rightAxis), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide tank steering using the stored robot configuration.
|
||||
* This function lets you pick the axis to be used on each Joystick object for the left
|
||||
* and right sides of the robot.
|
||||
* @param leftStick The Joystick object to use for the left side of the robot.
|
||||
* @param leftAxis The axis to select on the left side Joystick object.
|
||||
* @param rightStick The Joystick object to use for the right side of the robot.
|
||||
* @param rightAxis The axis to select on the right side Joystick object.
|
||||
* @param squaredInputs Setting this parameter to true decreases the sensitivity at lower speeds
|
||||
*/
|
||||
public void tankDrive(GenericHID leftStick, final int leftAxis,
|
||||
GenericHID rightStick, final int rightAxis, boolean squaredInputs) {
|
||||
if (leftStick == null || rightStick == null) {
|
||||
throw new NullPointerException("Null HID provided");
|
||||
}
|
||||
tankDrive(leftStick.getRawAxis(leftAxis), rightStick.getRawAxis(rightAxis), squaredInputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide tank steering using the stored robot configuration.
|
||||
* This function lets you directly provide joystick values from any source.
|
||||
* @param leftValue The value of the left stick.
|
||||
* @param rightValue The value of the right stick.
|
||||
* @param squaredInputs Setting this parameter to true decreases the sensitivity at lower speeds
|
||||
*/
|
||||
public void tankDrive(double leftValue, double rightValue, boolean squaredInputs) {
|
||||
|
||||
if(!kTank_Reported) {
|
||||
UsageReporting.report(tResourceType.kResourceType_RobotDrive, getNumMotors(), tInstances.kRobotDrive_Tank);
|
||||
kTank_Reported = true;
|
||||
}
|
||||
|
||||
// square the inputs (while preserving the sign) to increase fine control while permitting full power
|
||||
leftValue = limit(leftValue);
|
||||
rightValue = limit(rightValue);
|
||||
if(squaredInputs) {
|
||||
if (leftValue >= 0.0) {
|
||||
leftValue = (leftValue * leftValue);
|
||||
} else {
|
||||
leftValue = -(leftValue * leftValue);
|
||||
}
|
||||
if (rightValue >= 0.0) {
|
||||
rightValue = (rightValue * rightValue);
|
||||
} else {
|
||||
rightValue = -(rightValue * rightValue);
|
||||
}
|
||||
}
|
||||
setLeftRightMotorOutputs(leftValue, rightValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide tank steering using the stored robot configuration.
|
||||
* This function lets you directly provide joystick values from any source.
|
||||
* @param leftValue The value of the left stick.
|
||||
* @param rightValue The value of the right stick.
|
||||
*/
|
||||
public void tankDrive(double leftValue, double rightValue) {
|
||||
tankDrive(leftValue, rightValue, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Arcade drive implements single stick driving.
|
||||
* Given a single Joystick, the class assumes the Y axis for the move value and the X axis
|
||||
* for the rotate value.
|
||||
* (Should add more information here regarding the way that arcade drive works.)
|
||||
* @param stick The joystick to use for Arcade single-stick driving. The Y-axis will be selected
|
||||
* for forwards/backwards and the X-axis will be selected for rotation rate.
|
||||
* @param squaredInputs If true, the sensitivity will be decreased for small values
|
||||
*/
|
||||
public void arcadeDrive(GenericHID stick, boolean squaredInputs) {
|
||||
// simply call the full-featured arcadeDrive with the appropriate values
|
||||
arcadeDrive(stick.getY(), stick.getX(), squaredInputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Arcade drive implements single stick driving.
|
||||
* Given a single Joystick, the class assumes the Y axis for the move value and the X axis
|
||||
* for the rotate value.
|
||||
* (Should add more information here regarding the way that arcade drive works.)
|
||||
* @param stick The joystick to use for Arcade single-stick driving. The Y-axis will be selected
|
||||
* for forwards/backwards and the X-axis will be selected for rotation rate.
|
||||
*/
|
||||
public void arcadeDrive(GenericHID stick) {
|
||||
this.arcadeDrive(stick, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Arcade drive implements single stick driving.
|
||||
* Given two joystick instances and two axis, compute the values to send to either two
|
||||
* or four motors.
|
||||
* @param moveStick The Joystick object that represents the forward/backward direction
|
||||
* @param moveAxis The axis on the moveStick object to use for forwards/backwards (typically Y_AXIS)
|
||||
* @param rotateStick The Joystick object that represents the rotation value
|
||||
* @param rotateAxis The axis on the rotation object to use for the rotate right/left (typically X_AXIS)
|
||||
* @param squaredInputs Setting this parameter to true decreases the sensitivity at lower speeds
|
||||
*/
|
||||
public void arcadeDrive(GenericHID moveStick, final int moveAxis,
|
||||
GenericHID rotateStick, final int rotateAxis,
|
||||
boolean squaredInputs) {
|
||||
double moveValue = moveStick.getRawAxis(moveAxis);
|
||||
double rotateValue = rotateStick.getRawAxis(rotateAxis);
|
||||
|
||||
arcadeDrive(moveValue, rotateValue, squaredInputs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Arcade drive implements single stick driving.
|
||||
* Given two joystick instances and two axis, compute the values to send to either two
|
||||
* or four motors.
|
||||
* @param moveStick The Joystick object that represents the forward/backward direction
|
||||
* @param moveAxis The axis on the moveStick object to use for forwards/backwards (typically Y_AXIS)
|
||||
* @param rotateStick The Joystick object that represents the rotation value
|
||||
* @param rotateAxis The axis on the rotation object to use for the rotate right/left (typically X_AXIS)
|
||||
*/
|
||||
public void arcadeDrive(GenericHID moveStick, final int moveAxis,
|
||||
GenericHID rotateStick, final int rotateAxis) {
|
||||
this.arcadeDrive(moveStick, moveAxis, rotateStick, rotateAxis, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Arcade drive implements single stick driving.
|
||||
* This function lets you directly provide joystick values from any source.
|
||||
* @param moveValue The value to use for forwards/backwards
|
||||
* @param rotateValue The value to use for the rotate right/left
|
||||
* @param squaredInputs If set, decreases the sensitivity at low speeds
|
||||
*/
|
||||
public void arcadeDrive(double moveValue, double rotateValue, boolean squaredInputs) {
|
||||
// local variables to hold the computed PWM values for the motors
|
||||
if(!kArcadeStandard_Reported) {
|
||||
UsageReporting.report(tResourceType.kResourceType_RobotDrive, getNumMotors(), tInstances.kRobotDrive_ArcadeStandard);
|
||||
kArcadeStandard_Reported = true;
|
||||
}
|
||||
|
||||
double leftMotorSpeed;
|
||||
double rightMotorSpeed;
|
||||
|
||||
moveValue = limit(moveValue);
|
||||
rotateValue = limit(rotateValue);
|
||||
|
||||
if (squaredInputs) {
|
||||
// square the inputs (while preserving the sign) to increase fine control while permitting full power
|
||||
if (moveValue >= 0.0) {
|
||||
moveValue = (moveValue * moveValue);
|
||||
} else {
|
||||
moveValue = -(moveValue * moveValue);
|
||||
}
|
||||
if (rotateValue >= 0.0) {
|
||||
rotateValue = (rotateValue * rotateValue);
|
||||
} else {
|
||||
rotateValue = -(rotateValue * rotateValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (moveValue > 0.0) {
|
||||
if (rotateValue > 0.0) {
|
||||
leftMotorSpeed = moveValue - rotateValue;
|
||||
rightMotorSpeed = Math.max(moveValue, rotateValue);
|
||||
} else {
|
||||
leftMotorSpeed = Math.max(moveValue, -rotateValue);
|
||||
rightMotorSpeed = moveValue + rotateValue;
|
||||
}
|
||||
} else {
|
||||
if (rotateValue > 0.0) {
|
||||
leftMotorSpeed = -Math.max(-moveValue, rotateValue);
|
||||
rightMotorSpeed = moveValue + rotateValue;
|
||||
} else {
|
||||
leftMotorSpeed = moveValue - rotateValue;
|
||||
rightMotorSpeed = -Math.max(-moveValue, -rotateValue);
|
||||
}
|
||||
}
|
||||
|
||||
setLeftRightMotorOutputs(leftMotorSpeed, rightMotorSpeed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Arcade drive implements single stick driving.
|
||||
* This function lets you directly provide joystick values from any source.
|
||||
* @param moveValue The value to use for fowards/backwards
|
||||
* @param rotateValue The value to use for the rotate right/left
|
||||
*/
|
||||
public void arcadeDrive(double moveValue, double rotateValue) {
|
||||
this.arcadeDrive(moveValue, rotateValue, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drive method for Mecanum wheeled robots.
|
||||
*
|
||||
* A method for driving with Mecanum wheeled robots. There are 4 wheels
|
||||
* on the robot, arranged so that the front and back wheels are toed in 45 degrees.
|
||||
* When looking at the wheels from the top, the roller axles should form an X across the robot.
|
||||
*
|
||||
* This is designed to be directly driven by joystick axes.
|
||||
*
|
||||
* @param x The speed that the robot should drive in the X direction. [-1.0..1.0]
|
||||
* @param y The speed that the robot should drive in the Y direction.
|
||||
* This input is inverted to match the forward == -1.0 that joysticks produce. [-1.0..1.0]
|
||||
* @param rotation The rate of rotation for the robot that is completely independent of
|
||||
* the translation. [-1.0..1.0]
|
||||
* @param gyroAngle The current angle reading from the gyro. Use this to implement field-oriented controls.
|
||||
*/
|
||||
public void mecanumDrive_Cartesian(double x, double y, double rotation, double gyroAngle) {
|
||||
if(!kMecanumCartesian_Reported) {
|
||||
UsageReporting.report(tResourceType.kResourceType_RobotDrive, getNumMotors(), tInstances.kRobotDrive_MecanumCartesian);
|
||||
kMecanumCartesian_Reported = true;
|
||||
}
|
||||
double xIn = x;
|
||||
double yIn = y;
|
||||
// Negate y for the joystick.
|
||||
yIn = -yIn;
|
||||
// Compenstate for gyro angle.
|
||||
double rotated[] = rotateVector(xIn, yIn, gyroAngle);
|
||||
xIn = rotated[0];
|
||||
yIn = rotated[1];
|
||||
|
||||
double wheelSpeeds[] = new double[kMaxNumberOfMotors];
|
||||
wheelSpeeds[MotorType.kFrontLeft_val] = xIn + yIn + rotation;
|
||||
wheelSpeeds[MotorType.kFrontRight_val] = -xIn + yIn - rotation;
|
||||
wheelSpeeds[MotorType.kRearLeft_val] = -xIn + yIn + rotation;
|
||||
wheelSpeeds[MotorType.kRearRight_val] = xIn + yIn - rotation;
|
||||
|
||||
normalize(wheelSpeeds);
|
||||
|
||||
byte syncGroup = (byte)0x80;
|
||||
|
||||
m_frontLeftMotor.set(wheelSpeeds[MotorType.kFrontLeft_val] * m_invertedMotors[MotorType.kFrontLeft_val] * m_maxOutput, syncGroup);
|
||||
m_frontRightMotor.set(wheelSpeeds[MotorType.kFrontRight_val] * m_invertedMotors[MotorType.kFrontRight_val] * m_maxOutput, syncGroup);
|
||||
m_rearLeftMotor.set(wheelSpeeds[MotorType.kRearLeft_val] * m_invertedMotors[MotorType.kRearLeft_val] * m_maxOutput, syncGroup);
|
||||
m_rearRightMotor.set(wheelSpeeds[MotorType.kRearRight_val] * m_invertedMotors[MotorType.kRearRight_val] * m_maxOutput, syncGroup);
|
||||
|
||||
if (m_isCANInitialized) {
|
||||
try {
|
||||
CANJaguar.updateSyncGroup(syncGroup);
|
||||
} catch (CANNotInitializedException e) {
|
||||
m_isCANInitialized = false;
|
||||
} catch (CANTimeoutException e) {}
|
||||
}
|
||||
|
||||
if (m_safetyHelper != null) m_safetyHelper.feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drive method for Mecanum wheeled robots.
|
||||
*
|
||||
* A method for driving with Mecanum wheeled robots. There are 4 wheels
|
||||
* on the robot, arranged so that the front and back wheels are toed in 45 degrees.
|
||||
* When looking at the wheels from the top, the roller axles should form an X across the robot.
|
||||
*
|
||||
* @param magnitude The speed that the robot should drive in a given direction.
|
||||
* @param direction The direction the robot should drive in degrees. The direction and maginitute are
|
||||
* independent of the rotation rate.
|
||||
* @param rotation The rate of rotation for the robot that is completely independent of
|
||||
* the magnitute or direction. [-1.0..1.0]
|
||||
*/
|
||||
public void mecanumDrive_Polar(double magnitude, double direction, double rotation) {
|
||||
if(!kMecanumPolar_Reported) {
|
||||
UsageReporting.report(tResourceType.kResourceType_RobotDrive, getNumMotors(), tInstances.kRobotDrive_MecanumPolar);
|
||||
kMecanumPolar_Reported = true;
|
||||
}
|
||||
double frontLeftSpeed, rearLeftSpeed, frontRightSpeed, rearRightSpeed;
|
||||
// Normalized for full power along the Cartesian axes.
|
||||
magnitude = limit(magnitude) * Math.sqrt(2.0);
|
||||
// The rollers are at 45 degree angles.
|
||||
double dirInRad = (direction + 45.0) * 3.14159 / 180.0;
|
||||
double cosD = Math.cos(dirInRad);
|
||||
double sinD = Math.sin(dirInRad);
|
||||
|
||||
double wheelSpeeds[] = new double[kMaxNumberOfMotors];
|
||||
wheelSpeeds[MotorType.kFrontLeft_val] = (sinD * magnitude + rotation);
|
||||
wheelSpeeds[MotorType.kFrontRight_val] = (cosD * magnitude - rotation);
|
||||
wheelSpeeds[MotorType.kRearLeft_val] = (cosD * magnitude + rotation);
|
||||
wheelSpeeds[MotorType.kRearRight_val] = (sinD * magnitude - rotation);
|
||||
|
||||
normalize(wheelSpeeds);
|
||||
|
||||
byte syncGroup = (byte)0x80;
|
||||
|
||||
m_frontLeftMotor.set(wheelSpeeds[MotorType.kFrontLeft_val] * m_invertedMotors[MotorType.kFrontLeft_val] * m_maxOutput, syncGroup);
|
||||
m_frontRightMotor.set(wheelSpeeds[MotorType.kFrontRight_val] * m_invertedMotors[MotorType.kFrontRight_val] * m_maxOutput, syncGroup);
|
||||
m_rearLeftMotor.set(wheelSpeeds[MotorType.kRearLeft_val] * m_invertedMotors[MotorType.kRearLeft_val] * m_maxOutput, syncGroup);
|
||||
m_rearRightMotor.set(wheelSpeeds[MotorType.kRearRight_val] * m_invertedMotors[MotorType.kRearRight_val] * m_maxOutput, syncGroup);
|
||||
|
||||
if (m_isCANInitialized) {
|
||||
try {
|
||||
CANJaguar.updateSyncGroup(syncGroup);
|
||||
} catch (CANNotInitializedException e) {
|
||||
m_isCANInitialized = false;
|
||||
} catch (CANTimeoutException e) {}
|
||||
}
|
||||
|
||||
if (m_safetyHelper != null) m_safetyHelper.feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Holonomic Drive method for Mecanum wheeled robots.
|
||||
*
|
||||
* This is an alias to mecanumDrive_Polar() for backward compatability
|
||||
*
|
||||
* @param magnitude The speed that the robot should drive in a given direction. [-1.0..1.0]
|
||||
* @param direction The direction the robot should drive. The direction and maginitute are
|
||||
* independent of the rotation rate.
|
||||
* @param rotation The rate of rotation for the robot that is completely independent of
|
||||
* the magnitute or direction. [-1.0..1.0]
|
||||
*/
|
||||
void holonomicDrive(float magnitude, float direction, float rotation) {
|
||||
mecanumDrive_Polar(magnitude, direction, rotation);
|
||||
}
|
||||
|
||||
/** Set the speed of the right and left motors.
|
||||
* This is used once an appropriate drive setup function is called such as
|
||||
* twoWheelDrive(). The motors are set to "leftSpeed" and "rightSpeed"
|
||||
* and includes flipping the direction of one side for opposing motors.
|
||||
* @param leftOutput The speed to send to the left side of the robot.
|
||||
* @param rightOutput The speed to send to the right side of the robot.
|
||||
*/
|
||||
public void setLeftRightMotorOutputs(double leftOutput, double rightOutput) {
|
||||
if (m_rearLeftMotor == null || m_rearRightMotor == null) {
|
||||
throw new NullPointerException("Null motor provided");
|
||||
}
|
||||
|
||||
byte syncGroup = (byte)0x80;
|
||||
|
||||
if (m_frontLeftMotor != null) {
|
||||
m_frontLeftMotor.set(limit(leftOutput) * m_invertedMotors[MotorType.kFrontLeft_val] * m_maxOutput, syncGroup);
|
||||
}
|
||||
m_rearLeftMotor.set(limit(leftOutput) * m_invertedMotors[MotorType.kRearLeft_val] * m_maxOutput, syncGroup);
|
||||
|
||||
if (m_frontRightMotor != null) {
|
||||
m_frontRightMotor.set(-limit(rightOutput) * m_invertedMotors[MotorType.kFrontRight_val] * m_maxOutput, syncGroup);
|
||||
}
|
||||
m_rearRightMotor.set(-limit(rightOutput) * m_invertedMotors[MotorType.kRearRight_val] * m_maxOutput, syncGroup);
|
||||
|
||||
if (m_isCANInitialized) {
|
||||
try {
|
||||
CANJaguar.updateSyncGroup(syncGroup);
|
||||
} catch (CANNotInitializedException e) {
|
||||
m_isCANInitialized = false;
|
||||
} catch (CANTimeoutException e) {}
|
||||
}
|
||||
|
||||
if (m_safetyHelper != null) m_safetyHelper.feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit motor values to the -1.0 to +1.0 range.
|
||||
*/
|
||||
protected static double limit(double num) {
|
||||
if (num > 1.0) {
|
||||
return 1.0;
|
||||
}
|
||||
if (num < -1.0) {
|
||||
return -1.0;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize all wheel speeds if the magnitude of any wheel is greater than 1.0.
|
||||
*/
|
||||
protected static void normalize(double wheelSpeeds[]) {
|
||||
double maxMagnitude = Math.abs(wheelSpeeds[0]);
|
||||
int i;
|
||||
for (i=1; i<kMaxNumberOfMotors; i++) {
|
||||
double temp = Math.abs(wheelSpeeds[i]);
|
||||
if (maxMagnitude < temp) maxMagnitude = temp;
|
||||
}
|
||||
if (maxMagnitude > 1.0) {
|
||||
for (i=0; i<kMaxNumberOfMotors; i++) {
|
||||
wheelSpeeds[i] = wheelSpeeds[i] / maxMagnitude;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate a vector in Cartesian space.
|
||||
*/
|
||||
protected static double[] rotateVector(double x, double y, double angle) {
|
||||
double cosA = Math.cos(angle * (3.14159 / 180.0));
|
||||
double sinA = Math.sin(angle * (3.14159 / 180.0));
|
||||
double out[] = new double[2];
|
||||
out[0] = x * cosA - y * sinA;
|
||||
out[1] = x * sinA + y * cosA;
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invert a motor direction.
|
||||
* This is used when a motor should run in the opposite direction as the drive
|
||||
* code would normally run it. Motors that are direct drive would be inverted, the
|
||||
* drive code assumes that the motors are geared with one reversal.
|
||||
* @param motor The motor index to invert.
|
||||
* @param isInverted True if the motor should be inverted when operated.
|
||||
*/
|
||||
public void setInvertedMotor(MotorType motor, boolean isInverted) {
|
||||
m_invertedMotors[motor.value] = isInverted ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the turning sensitivity.
|
||||
*
|
||||
* This only impacts the drive() entry-point.
|
||||
* @param sensitivity Effectively sets the turning sensitivity (or turn radius for a given value)
|
||||
*/
|
||||
public void setSensitivity(double sensitivity) {
|
||||
m_sensitivity = sensitivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the scaling factor for using RobotDrive with motor controllers in a mode other than PercentVbus.
|
||||
* @param maxOutput Multiplied with the output percentage computed by the drive functions.
|
||||
*/
|
||||
public void setMaxOutput(double maxOutput) {
|
||||
m_maxOutput = maxOutput;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free the speed controllers if they were allocated locally
|
||||
*/
|
||||
public void free() {
|
||||
if (m_allocatedSpeedControllers) {
|
||||
if (m_frontLeftMotor != null) {
|
||||
((PWM) m_frontLeftMotor).free();
|
||||
}
|
||||
if (m_frontRightMotor != null) {
|
||||
((PWM) m_frontRightMotor).free();
|
||||
}
|
||||
if (m_rearLeftMotor != null) {
|
||||
((PWM) m_rearLeftMotor).free();
|
||||
}
|
||||
if (m_rearRightMotor != null) {
|
||||
((PWM) m_rearRightMotor).free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setExpiration(double timeout) {
|
||||
m_safetyHelper.setExpiration(timeout);
|
||||
}
|
||||
|
||||
public double getExpiration() {
|
||||
return m_safetyHelper.getExpiration();
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return m_safetyHelper.isAlive();
|
||||
}
|
||||
|
||||
public boolean isSafetyEnabled() {
|
||||
return m_safetyHelper.isSafetyEnabled();
|
||||
}
|
||||
|
||||
public void setSafetyEnabled(boolean enabled) {
|
||||
m_safetyHelper.setSafetyEnabled(enabled);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "Robot Drive";
|
||||
}
|
||||
|
||||
public void stopMotor() {
|
||||
if (m_frontLeftMotor != null) {
|
||||
m_frontLeftMotor.set(0.0);
|
||||
}
|
||||
if (m_frontRightMotor != null) {
|
||||
m_frontRightMotor.set(0.0);
|
||||
}
|
||||
if (m_rearLeftMotor != null) {
|
||||
m_rearLeftMotor.set(0.0);
|
||||
}
|
||||
if (m_rearRightMotor != null) {
|
||||
m_rearRightMotor.set(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMotorSafety() {
|
||||
m_safetyHelper = new MotorSafetyHelper(this);
|
||||
m_safetyHelper.setExpiration(kDefaultExpirationTime);
|
||||
m_safetyHelper.setSafetyEnabled(true);
|
||||
}
|
||||
|
||||
protected int getNumMotors() {
|
||||
int motors = 0;
|
||||
if (m_frontLeftMotor != null) motors++;
|
||||
if (m_frontRightMotor != null) motors++;
|
||||
if (m_rearLeftMotor != null) motors++;
|
||||
if (m_rearRightMotor != null) motors++;
|
||||
return motors;
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author brad
|
||||
*/
|
||||
public class SafePWM extends PWM implements MotorSafety {
|
||||
|
||||
private MotorSafetyHelper m_safetyHelper;
|
||||
|
||||
/**
|
||||
* Initialize a SafePWM object by setting defaults
|
||||
*/
|
||||
void initSafePWM() {
|
||||
m_safetyHelper = new MotorSafetyHelper(this);
|
||||
m_safetyHelper.setExpiration(0.0);
|
||||
m_safetyHelper.setSafetyEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for a SafePWM object taking a channel number
|
||||
* @param channel The channel number to be used for the underlying PWM object
|
||||
*/
|
||||
public SafePWM(final int channel) {
|
||||
super(channel);
|
||||
initSafePWM();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a SafePWM object taking channel and slot numbers.
|
||||
* @param slot The slot number of the digital module for this PWM object
|
||||
* @param channel The channel number in the module for this PWM object
|
||||
*/
|
||||
public SafePWM(final int slot, final int channel) {
|
||||
super(slot, channel);
|
||||
initSafePWM();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the expiration time for the PWM object
|
||||
* @param timeout The timeout (in seconds) for this motor object
|
||||
*/
|
||||
public void setExpiration(double timeout) {
|
||||
m_safetyHelper.setExpiration(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the expiration time for the PWM object.
|
||||
* @return The expiration time value.
|
||||
*/
|
||||
public double getExpiration() {
|
||||
return m_safetyHelper.getExpiration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the PWM object is currently alive or stopped due to a timeout.
|
||||
* @return a bool value that is true if the motor has NOT timed out and should still
|
||||
* be running.
|
||||
*/
|
||||
public boolean isAlive() {
|
||||
return m_safetyHelper.isAlive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the motor associated with this PWM object.
|
||||
* This is called by the MotorSafetyHelper object when it has a timeout for this PWM and needs to
|
||||
* stop it from running.
|
||||
*/
|
||||
public void stopMotor() {
|
||||
disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if motor safety is enabled for this object
|
||||
* @return True if motor safety is enforced for this object
|
||||
*/
|
||||
public boolean isSafetyEnabled() {
|
||||
return m_safetyHelper.isSafetyEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Feed the MotorSafety timer.
|
||||
* This method is called by the subclass motor whenever it updates its speed, thereby reseting
|
||||
* the timeout value.
|
||||
*/
|
||||
public void Feed() {
|
||||
m_safetyHelper.feed();
|
||||
}
|
||||
|
||||
public void setSafetyEnabled(boolean enabled) {
|
||||
m_safetyHelper.setSafetyEnabled(enabled);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "PWM "+getChannel()+" on module "+getModuleNumber();
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
setRaw(kPwmDisabled);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
|
||||
/**
|
||||
* The base interface for objects that can be sent over the network
|
||||
* through network tables.
|
||||
*/
|
||||
public interface Sendable {
|
||||
/**
|
||||
* Initializes a table for this sendable object.
|
||||
* @param subtable The table to put the values in.
|
||||
*/
|
||||
public void initTable(ITable subtable);
|
||||
|
||||
/**
|
||||
* @return the table that is currently associated with the sendable
|
||||
*/
|
||||
public ITable getTable();
|
||||
|
||||
/**
|
||||
* @return the string representation of the named data type that will be used by the smart dashboard for this sendable
|
||||
*/
|
||||
public String getSmartDashboardType();
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.hal.HALLibrary;
|
||||
|
||||
/**
|
||||
* Base class for all sensors.
|
||||
* Stores most recent status information as well as containing utility functions for checking
|
||||
* channels and error processing.
|
||||
*
|
||||
* XXX: Wait, there's no exception thrown if we try to allocate a non-existent module? It that behavior correct?
|
||||
*/
|
||||
public abstract class SensorBase { // TODO: Refactor
|
||||
|
||||
// TODO: Move this to the HAL
|
||||
|
||||
/**
|
||||
* Ticks per microsecond
|
||||
*/
|
||||
public static final int kSystemClockTicksPerMicrosecond = 40;
|
||||
/**
|
||||
* Number of digital channels per digital sidecar
|
||||
*/
|
||||
public static final int kDigitalChannels = 14;
|
||||
/**
|
||||
* Number of digital modules
|
||||
* XXX: This number is incorrect. We need to find the correct number.
|
||||
*/
|
||||
public static final int kDigitalModules = 2;
|
||||
/**
|
||||
* Number of analog channels per module
|
||||
*/
|
||||
public static final int kAnalogChannels = 8;
|
||||
/**
|
||||
* Number of analog modules
|
||||
*/
|
||||
public static final int kAnalogModules = 2;
|
||||
/**
|
||||
* Number of solenoid channels per module
|
||||
*/
|
||||
public static final int kSolenoidChannels = 8;
|
||||
/**
|
||||
* Number of analog modules
|
||||
*/
|
||||
public static final int kSolenoidModules = 2;
|
||||
/**
|
||||
* Number of PWM channels per sidecar
|
||||
*/
|
||||
public static final int kPwmChannels = 10;
|
||||
/**
|
||||
* Number of relay channels per sidecar
|
||||
*/
|
||||
public static final int kRelayChannels = 8;
|
||||
|
||||
private static int m_defaultAnalogModule = 1;
|
||||
private static int m_defaultDigitalModule = 1;
|
||||
private static int m_defaultSolenoidModule = 1;
|
||||
|
||||
/**
|
||||
* Creates an instance of the sensor base and gets an FPGA handle
|
||||
*/
|
||||
public SensorBase() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default Digital Module.
|
||||
* This sets the default digital module to use for objects that are created without
|
||||
* specifying the digital module in the constructor. The default module is initialized
|
||||
* to the first module in the chassis.
|
||||
*
|
||||
* @param moduleNumber The number of the digital module to use.
|
||||
*/
|
||||
public static void setDefaultDigitalModule(final int moduleNumber) {
|
||||
checkDigitalModule(moduleNumber);
|
||||
SensorBase.m_defaultDigitalModule = moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default Analog module.
|
||||
* This sets the default analog module to use for objects that are created without
|
||||
* specifying the analog module in the constructor. The default module is initialized
|
||||
* to the first module in the chassis.
|
||||
*
|
||||
* @param moduleNumber The number of the analog module to use.
|
||||
*/
|
||||
public static void setDefaultAnalogModule(final int moduleNumber) {
|
||||
checkAnalogModule(moduleNumber);
|
||||
SensorBase.m_defaultAnalogModule = moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default location for the Solenoid (9472) module.
|
||||
*
|
||||
* @param moduleNumber The number of the solenoid module to use.
|
||||
*/
|
||||
public static void setDefaultSolenoidModule(final int moduleNumber) {
|
||||
checkSolenoidModule(moduleNumber);
|
||||
SensorBase.m_defaultSolenoidModule = moduleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the digital module number is valid.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
*
|
||||
* @param moduleNumber The digital module module number to check.
|
||||
*/
|
||||
protected static void checkDigitalModule(final int moduleNumber) {
|
||||
if(HALLibrary.checkDigitalModule((byte) moduleNumber) != 1)
|
||||
System.err.println("Digital module " + moduleNumber + " is not present.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the digital module number is valid.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
*
|
||||
* @param moduleNumber The digital module module number to check.
|
||||
*/
|
||||
protected static void checkRelayModule(final int moduleNumber) {
|
||||
checkDigitalModule(moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the digital module number is valid.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
*
|
||||
* @param moduleNumber The digital module module number to check.
|
||||
*/
|
||||
protected static void checkPWMModule(final int moduleNumber) {
|
||||
checkDigitalModule(moduleNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the analog module number is valid.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
*
|
||||
* @param moduleNumber The analog module module number to check.
|
||||
*/
|
||||
protected static void checkAnalogModule(final int moduleNumber) {
|
||||
if(HALLibrary.checkAnalogModule((byte) (moduleNumber - 1)) != 0) {
|
||||
System.err.println("Analog module " + moduleNumber + " is not present.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the solenoid module is correct.
|
||||
* Module numbers are 1 or 2 (they are no longer real cRIO slots).
|
||||
*
|
||||
* @param moduleNumber The solenoid module module number to check.
|
||||
*/
|
||||
protected static void checkSolenoidModule(final int moduleNumber) {
|
||||
if(HALLibrary.checkSolenoidModule((byte) (moduleNumber - 1)) != 0) {
|
||||
System.err.println("Solenoid module " + moduleNumber + " is not present.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the digital channel number is valid.
|
||||
* Verify that the channel number is one of the legal channel numbers. Channel numbers are
|
||||
* 1-based.
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkDigitalChannel(final int channel) {
|
||||
if (channel <= 0 || channel > kDigitalChannels) {
|
||||
System.err.println("Requested digital channel number is out of range.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the digital channel number is valid.
|
||||
* Verify that the channel number is one of the legal channel numbers. Channel numbers are
|
||||
* 1-based.
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkRelayChannel(final int channel) {
|
||||
if (channel <= 0 || channel > kRelayChannels) {
|
||||
System.err.println("Requested relay channel number is out of range.");
|
||||
throw new IndexOutOfBoundsException("Requested relay channel number is out of range.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the digital channel number is valid.
|
||||
* Verify that the channel number is one of the legal channel numbers. Channel numbers are
|
||||
* 1-based.
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkPWMChannel(final int channel) {
|
||||
if (channel <= 0 || channel > kPwmChannels) {
|
||||
System.err.println("Requested PWM channel number is out of range.");
|
||||
throw new IndexOutOfBoundsException("Requested PWM channel number is out of range.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the analog channel number is value.
|
||||
* Verify that the analog channel number is one of the legal channel numbers. Channel numbers
|
||||
* are 1-based.
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkAnalogChannel(final int channel) {
|
||||
if (channel <= 0 || channel > kAnalogChannels) {
|
||||
System.err.println("Requested analog channel number is out of range.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the solenoid channel number is within limits. Channel numbers
|
||||
* are 1-based.
|
||||
*
|
||||
* @param channel The channel number to check.
|
||||
*/
|
||||
protected static void checkSolenoidChannel(final int channel) {
|
||||
if (channel <= 0 || channel > kSolenoidChannels) {
|
||||
System.err.println("Requested solenoid channel number is out of range.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of the default analog module.
|
||||
*
|
||||
* @return The number of the default analog module.
|
||||
*/
|
||||
public static int getDefaultAnalogModule() {
|
||||
return SensorBase.m_defaultAnalogModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of the default analog module.
|
||||
*
|
||||
* @return The number of the default analog module.
|
||||
*/
|
||||
public static int getDefaultDigitalModule() {
|
||||
return SensorBase.m_defaultDigitalModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of the default analog module.
|
||||
*
|
||||
* @return The number of the default analog module.
|
||||
*/
|
||||
public static int getDefaultSolenoidModule() {
|
||||
return SensorBase.m_defaultSolenoidModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the resources used by this object
|
||||
*/
|
||||
public void free() {}
|
||||
}
|
||||
@@ -1,431 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.io.UnsupportedEncodingException;
|
||||
|
||||
import edu.wpi.first.wpilibj.visa.Visa;
|
||||
import edu.wpi.first.wpilibj.visa.VisaException;
|
||||
|
||||
/**
|
||||
* Driver for the RS-232 serial port on the cRIO.
|
||||
*
|
||||
* The current implementation uses the VISA formatted I/O mode. This means that
|
||||
* all traffic goes through the formatted buffers. This allows the intermingled
|
||||
* use of print(), readString(), and the raw buffer accessors read() and write().
|
||||
*
|
||||
* More information can be found in the NI-VISA User Manual here:
|
||||
* http://www.ni.com/pdf/manuals/370423a.pdf
|
||||
* and the NI-VISA Programmer's Reference Manual here:
|
||||
* http://www.ni.com/pdf/manuals/370132c.pdf
|
||||
*/
|
||||
public class SerialPort {
|
||||
|
||||
private int m_resourceManagerHandle;
|
||||
private int m_portHandle;
|
||||
|
||||
/**
|
||||
* Represents the parity to use for serial communications
|
||||
*/
|
||||
public static class Parity {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kNone_val = 0;
|
||||
static final int kOdd_val = 1;
|
||||
static final int kEven_val = 2;
|
||||
static final int kMark_val = 3;
|
||||
static final int kSpace_val = 4;
|
||||
/**
|
||||
* parity: Use no parity
|
||||
*/
|
||||
public static final Parity kNone = new Parity(kNone_val);
|
||||
/**
|
||||
* parity: Use odd parity
|
||||
*/
|
||||
public static final Parity kOdd = new Parity(kOdd_val);
|
||||
/**
|
||||
* parity: Use even parity
|
||||
*/
|
||||
public static final Parity kEven = new Parity(kEven_val);
|
||||
/**
|
||||
* parity: Use mark parity
|
||||
*/
|
||||
public static final Parity kMark = new Parity(kMark_val);
|
||||
/**
|
||||
* parity: Use space parity
|
||||
*/
|
||||
public static final Parity kSpace = new Parity((kSpace_val));
|
||||
|
||||
private Parity(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the number of stop bits to use for Serial Communication
|
||||
*/
|
||||
public static class StopBits {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kOne_val = 10;
|
||||
static final int kOnePointFive_val = 15;
|
||||
static final int kTwo_val = 20;
|
||||
/**
|
||||
* stopBits: use 1
|
||||
*/
|
||||
public static final StopBits kOne = new StopBits(kOne_val);
|
||||
/**
|
||||
* stopBits: use 1.5
|
||||
*/
|
||||
public static final StopBits kOnePointFive = new StopBits(kOnePointFive_val);
|
||||
/**
|
||||
* stopBits: use 2
|
||||
*/
|
||||
public static final StopBits kTwo = new StopBits(kTwo_val);
|
||||
|
||||
private StopBits(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents what type of flow control to use for serial communication
|
||||
*/
|
||||
public static class FlowControl {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kNone_val = 0;
|
||||
static final int kXonXoff_val = 1;
|
||||
static final int kRtsCts_val = 2;
|
||||
static final int kDtrDsr_val = 4;
|
||||
/**
|
||||
* flowControl: use none
|
||||
*/
|
||||
public static final FlowControl kNone = new FlowControl(kNone_val);
|
||||
/**
|
||||
* flowcontrol: use on/off
|
||||
*/
|
||||
public static final FlowControl kXonXoff = new FlowControl(kXonXoff_val);
|
||||
/**
|
||||
* flowcontrol: use rts cts
|
||||
*/
|
||||
public static final FlowControl kRtsCts = new FlowControl(kRtsCts_val);
|
||||
/**
|
||||
* flowcontrol: use dts dsr
|
||||
*/
|
||||
public static final FlowControl kDtrDsr = new FlowControl(kDtrDsr_val);
|
||||
|
||||
private FlowControl(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents which type of buffer mode to use when writing to a serial port
|
||||
*/
|
||||
public static class WriteBufferMode {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kFlushOnAccess_val = 1;
|
||||
static final int kFlushWhenFull_val = 2;
|
||||
/**
|
||||
* Flush on access
|
||||
*/
|
||||
public static final WriteBufferMode kFlushOnAccess = new WriteBufferMode(kFlushOnAccess_val);
|
||||
/**
|
||||
* Flush when full
|
||||
*/
|
||||
public static final WriteBufferMode kFlushWhenFull = new WriteBufferMode(kFlushWhenFull_val);
|
||||
|
||||
private WriteBufferMode(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Serial Port class.
|
||||
*
|
||||
* @param baudRate The baud rate to configure the serial port. The cRIO-9074 supports up to 230400 Baud.
|
||||
* @param dataBits The number of data bits per transfer. Valid values are between 5 and 8 bits.
|
||||
* @param parity Select the type of parity checking to use.
|
||||
* @param stopBits The number of stop bits to use as defined by the enum StopBits.
|
||||
*/
|
||||
public SerialPort(final int baudRate, final int dataBits, Parity parity, StopBits stopBits) throws VisaException {
|
||||
m_resourceManagerHandle = 0;
|
||||
m_portHandle = 0;
|
||||
|
||||
m_resourceManagerHandle = Visa.viOpenDefaultRM();
|
||||
|
||||
m_portHandle = Visa.viOpen(m_resourceManagerHandle, "ASRL1::INSTR", 0, 0);
|
||||
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_ASRL_BAUD, baudRate);
|
||||
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_ASRL_DATA_BITS, dataBits);
|
||||
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_ASRL_PARITY, parity.value);
|
||||
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_ASRL_STOP_BITS, stopBits.value);
|
||||
|
||||
// Set the default read buffer size to 1 to return bytes immediately
|
||||
setReadBufferSize(1);
|
||||
|
||||
// Set the default timeout to 5 seconds.
|
||||
setTimeout(5.0f);
|
||||
|
||||
// Don't wait until the buffer is full to transmit.
|
||||
setWriteBufferMode(WriteBufferMode.kFlushOnAccess);
|
||||
|
||||
disableTermination();
|
||||
|
||||
//viInstallHandler(m_portHandle, VI_EVENT_IO_COMPLETION, ioCompleteHandler, this);
|
||||
//viEnableEvent(m_portHandle, VI_EVENT_IO_COMPLETION, VI_HNDLR, VI_NULL);
|
||||
|
||||
// XXX: Resource Reporting Fixes
|
||||
// UsageReporting.report(UsageReporting.kResourceType_SerialPort,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Serial Port class. Defaults to one stop bit.
|
||||
*
|
||||
* @param baudRate The baud rate to configure the serial port. The cRIO-9074 supports up to 230400 Baud.
|
||||
* @param dataBits The number of data bits per transfer. Valid values are between 5 and 8 bits.
|
||||
* @param parity Select the type of parity checking to use.
|
||||
*/
|
||||
public SerialPort(final int baudRate, final int dataBits, Parity parity) throws VisaException {
|
||||
this(baudRate, dataBits, parity, StopBits.kOne);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Serial Port class. Defaults to no parity and one
|
||||
* stop bit.
|
||||
*
|
||||
* @param baudRate The baud rate to configure the serial port. The cRIO-9074 supports up to 230400 Baud.
|
||||
* @param dataBits The number of data bits per transfer. Valid values are between 5 and 8 bits.
|
||||
*/
|
||||
public SerialPort(final int baudRate, final int dataBits) throws VisaException {
|
||||
this(baudRate, dataBits, Parity.kNone, StopBits.kOne);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of a Serial Port class. Defaults to 8 databits,
|
||||
* no parity, and one stop bit.
|
||||
*
|
||||
* @param baudRate The baud rate to configure the serial port. The cRIO-9074 supports up to 230400 Baud.
|
||||
*/
|
||||
public SerialPort(final int baudRate) throws VisaException {
|
||||
this(baudRate, 8, Parity.kNone, StopBits.kOne);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public void free() {
|
||||
//viUninstallHandler(m_portHandle, VI_EVENT_IO_COMPLETION, ioCompleteHandler, this);
|
||||
Visa.viClose(m_portHandle);
|
||||
Visa.viClose(m_resourceManagerHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of flow control to enable on this port.
|
||||
*
|
||||
* By default, flow control is disabled.
|
||||
* @param flowControl
|
||||
*/
|
||||
public void setFlowControl(FlowControl flowControl) throws VisaException {
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_ASRL_FLOW_CNTRL, flowControl.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable termination and specify the termination character.
|
||||
*
|
||||
* Termination is currently only implemented for receive.
|
||||
* When the the terminator is received, the read() or readString() will return
|
||||
* fewer bytes than requested, stopping after the terminator.
|
||||
*
|
||||
* @param terminator The character to use for termination.
|
||||
*/
|
||||
public void enableTermination(char terminator) throws VisaException {
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_TERMCHAR_EN, true);
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_TERMCHAR, terminator);
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_ASRL_END_IN, Visa.VI_ASRL_END_TERMCHAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable termination and specify the termination character.
|
||||
*
|
||||
* Termination is currently only implemented for receive.
|
||||
* When the the terminator is received, the read() or readString() will return
|
||||
* fewer bytes than requested, stopping after the terminator.
|
||||
*
|
||||
* The default terminator is '\n'
|
||||
*/
|
||||
public void enableTermination() throws VisaException {
|
||||
this.enableTermination('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable termination behavior.
|
||||
*/
|
||||
public void disableTermination() throws VisaException {
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_TERMCHAR_EN, false);
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_ASRL_END_IN, Visa.VI_ASRL_END_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes currently available to read from the serial port.
|
||||
*
|
||||
* @return The number of bytes available to read.
|
||||
*/
|
||||
public int getBytesReceived() throws VisaException {
|
||||
return Visa.viGetAttribute(m_portHandle, Visa.VI_ATTR_ASRL_AVAIL_NUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output formatted text to the serial port.
|
||||
*
|
||||
* @deprecated use write(string.getBytes()) instead
|
||||
* @bug All pointer-based parameters seem to return an error.
|
||||
*
|
||||
* @param write A string to write
|
||||
*/
|
||||
public void print(String write) throws VisaException {
|
||||
Visa.viVPrintf(m_portHandle, write);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a string out of the buffer. Reads the entire contents of the buffer
|
||||
*
|
||||
* @return The read string
|
||||
*/
|
||||
public String readString() throws VisaException {
|
||||
return readString(getBytesReceived());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a string out of the buffer. Reads the entire contents of the buffer
|
||||
*
|
||||
* @param count the number of characters to read into the string
|
||||
* @return The read string
|
||||
*/
|
||||
public String readString(int count) throws VisaException {
|
||||
byte[] out = Visa.viBufRead(m_portHandle, count);
|
||||
try {
|
||||
return new String(out, 0, count, "US-ASCII");
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
ex.printStackTrace();
|
||||
return new String();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read raw bytes out of the buffer.
|
||||
*
|
||||
* @param count The maximum number of bytes to read.
|
||||
* @return An array of the read bytes
|
||||
*/
|
||||
public byte[] read(final int count) throws VisaException {
|
||||
return Visa.viBufRead(m_portHandle, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write raw bytes to the buffer.
|
||||
*
|
||||
* @param buffer the buffer to read the bytes from.
|
||||
* @param count The maximum number of bytes to write.
|
||||
* @return The number of bytes actually written into the port.
|
||||
*/
|
||||
public int write(byte[] buffer, int count) throws VisaException {
|
||||
return Visa.viBufWrite(m_portHandle, buffer, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the timeout of the serial port.
|
||||
*
|
||||
* This defines the timeout for transactions with the hardware.
|
||||
* It will affect reads if less bytes are available than the
|
||||
* read buffer size (defaults to 1) and very large writes.
|
||||
*
|
||||
* @param timeout The number of seconds to to wait for I/O.
|
||||
*/
|
||||
public void setTimeout(double timeout) throws VisaException {
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_TMO_VALUE, (int) (timeout * 1e3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the size of the input buffer.
|
||||
*
|
||||
* Specify the amount of data that can be stored before data
|
||||
* from the device is returned to Read. If you want
|
||||
* data that is received to be returned immediately, set this to 1.
|
||||
*
|
||||
* It the buffer is not filled before the read timeout expires, all
|
||||
* data that has been received so far will be returned.
|
||||
*
|
||||
* @param size The read buffer size.
|
||||
*/
|
||||
void setReadBufferSize(int size) throws VisaException {
|
||||
Visa.viSetBuf(m_portHandle, Visa.VI_READ_BUF, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the size of the output buffer.
|
||||
*
|
||||
* Specify the amount of data that can be stored before being
|
||||
* transmitted to the device.
|
||||
*
|
||||
* @param size The write buffer size.
|
||||
*/
|
||||
void setWriteBufferSize(int size) throws VisaException {
|
||||
Visa.viSetBuf(m_portHandle, Visa.VI_WRITE_BUF, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the flushing behavior of the output buffer.
|
||||
*
|
||||
* When set to kFlushOnAccess, data is synchronously written to the serial port
|
||||
* after each call to either print() or write().
|
||||
*
|
||||
* When set to kFlushWhenFull, data will only be written to the serial port when
|
||||
* the buffer is full or when flush() is called.
|
||||
*
|
||||
* @param mode The write buffer mode.
|
||||
*/
|
||||
public void setWriteBufferMode(WriteBufferMode mode) throws VisaException {
|
||||
Visa.viSetAttribute(m_portHandle, Visa.VI_ATTR_WR_BUF_OPER_MODE, mode.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the output buffer to be written to the port.
|
||||
*
|
||||
* This is used when setWriteBufferMode() is set to kFlushWhenFull to force a
|
||||
* flush before the buffer is full.
|
||||
*/
|
||||
public void flush() throws VisaException {
|
||||
Visa.viFlush(m_portHandle, Visa.VI_WRITE_BUF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the serial port driver to a known state.
|
||||
*
|
||||
* Empty the transmit and receive buffers in the device and formatted I/O.
|
||||
*/
|
||||
public void reset() throws VisaException {
|
||||
Visa.viClear(m_portHandle);
|
||||
}
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.parsing.IDevice;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
|
||||
/**
|
||||
* Standard hobby style servo.
|
||||
*
|
||||
* The range parameters default to the appropriate values for the Hitec HS-322HD servo provided
|
||||
* in the FIRST Kit of Parts in 2008.
|
||||
*/
|
||||
public class Servo extends PWM implements IDevice {
|
||||
|
||||
private static final double kMaxServoAngle = 170.0;
|
||||
private static final double kMinServoAngle = 0.0;
|
||||
|
||||
/**
|
||||
* Common initialization code called by all constructors.
|
||||
*
|
||||
* InitServo() assigns defaults for the period multiplier for the servo PWM control signal, as
|
||||
* well as the minimum and maximum PWM values supported by the servo.
|
||||
*/
|
||||
private void initServo() {
|
||||
setBounds(2.27, 0, 0, 0, .743);
|
||||
setPeriodMultiplier(PeriodMultiplier.k4X);
|
||||
|
||||
LiveWindow.addActuator("Servo", getModuleNumber(), getChannel(), this);
|
||||
UsageReporting.report(tResourceType.kResourceType_Servo, getChannel(), getModuleNumber()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that assumes the default digital module.
|
||||
*
|
||||
* @param channel The PWM channel on the digital module to which the servo is attached.
|
||||
*/
|
||||
public Servo(final int channel) {
|
||||
super(channel);
|
||||
initServo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that specifies the digital module.
|
||||
*
|
||||
* @param slot The slot in the chassis that the digital module is plugged into.
|
||||
* @param channel The PWM channel on the digital module to which the servo is attached.
|
||||
*/
|
||||
public Servo(final int slot, final int channel) {
|
||||
super(slot, channel);
|
||||
initServo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the servo position.
|
||||
*
|
||||
* Servo values range from 0.0 to 1.0 corresponding to the range of full left to full right.
|
||||
*
|
||||
* @param value Position from 0.0 to 1.0.
|
||||
*/
|
||||
public void set(double value) {
|
||||
setPosition(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the servo position.
|
||||
*
|
||||
* Servo values range from 0.0 to 1.0 corresponding to the range of full left to full right.
|
||||
*
|
||||
* @return Position from 0.0 to 1.0.
|
||||
*/
|
||||
public double get() {
|
||||
return getPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the servo angle.
|
||||
*
|
||||
* Assume that the servo angle is linear with respect to the PWM value (big assumption, need to test).
|
||||
*
|
||||
* Servo angles that are out of the supported range of the servo simply "saturate" in that direction
|
||||
* In other words, if the servo has a range of (X degrees to Y degrees) than angles of less than X
|
||||
* result in an angle of X being set and angles of more than Y degrees result in an angle of Y being set.
|
||||
*
|
||||
* @param degrees The angle in degrees to set the servo.
|
||||
*/
|
||||
public void setAngle(double degrees) {
|
||||
if (degrees < kMinServoAngle) {
|
||||
degrees = kMinServoAngle;
|
||||
} else if (degrees > kMaxServoAngle) {
|
||||
degrees = kMaxServoAngle;
|
||||
}
|
||||
|
||||
setPosition(((degrees - kMinServoAngle)) / getServoAngleRange());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the servo angle.
|
||||
*
|
||||
* Assume that the servo angle is linear with respect to the PWM value (big assumption, need to test).
|
||||
* @return The angle in degrees to which the servo is set.
|
||||
*/
|
||||
public double getAngle() {
|
||||
return getPosition() * getServoAngleRange() + kMinServoAngle;
|
||||
}
|
||||
|
||||
private double getServoAngleRange() {
|
||||
return kMaxServoAngle - kMinServoAngle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Servo";
|
||||
}
|
||||
private ITable m_table;
|
||||
private ITableListener m_table_listener;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
m_table_listener = new ITableListener() {
|
||||
public void valueChanged(ITable itable, String key, Object value, boolean bln) {
|
||||
set(((Double) value).doubleValue());
|
||||
}
|
||||
};
|
||||
m_table.addTableListener("Value", m_table_listener, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
// TODO: Broken, should only remove the listener from "Value" only.
|
||||
m_table.removeTableListener(m_table_listener);
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tInstances;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
|
||||
/**
|
||||
* A simple robot base class that knows the standard FRC competition states (disabled, autonomous, or operator controlled).
|
||||
*
|
||||
* You can build a simple robot program off of this by overriding the
|
||||
* robotinit(), disabled(), autonomous() and operatorControl() methods. The startCompetition() method will calls these methods
|
||||
* (sometimes repeatedly).
|
||||
* depending on the state of the competition.
|
||||
*
|
||||
* Alternatively you can override the robotMain() method and manage all aspects of the robot yourself.
|
||||
*/
|
||||
public class SimpleRobot extends RobotBase {
|
||||
|
||||
private boolean m_robotMainOverridden;
|
||||
|
||||
/**
|
||||
* Create a new SimpleRobot
|
||||
*/
|
||||
public SimpleRobot() {
|
||||
super();
|
||||
m_robotMainOverridden = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Robot-wide initialization code should go here.
|
||||
*
|
||||
* Users should override this method for default Robot-wide initialization which will
|
||||
* be called when the robot is first powered on.
|
||||
*
|
||||
* Called exactly 1 time when the competition starts.
|
||||
*/
|
||||
protected void robotInit() {
|
||||
System.out.println("Default robotInit() method running, consider providing your own");
|
||||
}
|
||||
|
||||
/**
|
||||
* Disabled should go here.
|
||||
* Users should overload this method to run code that should run while the field is
|
||||
* disabled.
|
||||
*
|
||||
* Called once each time the robot enters the disabled state.
|
||||
*/
|
||||
protected void disabled() {
|
||||
System.out.println("Default disabled() method running, consider providing your own");
|
||||
}
|
||||
|
||||
/**
|
||||
* Autonomous should go here.
|
||||
* Users should add autonomous code to this method that should run while the field is
|
||||
* in the autonomous period.
|
||||
*
|
||||
* Called once each time the robot enters the autonomous state.
|
||||
*/
|
||||
public void autonomous() {
|
||||
System.out.println("Default autonomous() method running, consider providing your own");
|
||||
}
|
||||
|
||||
/**
|
||||
* Operator control (tele-operated) code should go here.
|
||||
* Users should add Operator Control code to this method that should run while the field is
|
||||
* in the Operator Control (tele-operated) period.
|
||||
*
|
||||
* Called once each time the robot enters the operator-controlled state.
|
||||
*/
|
||||
public void operatorControl() {
|
||||
System.out.println("Default operatorControl() method running, consider providing your own");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test code should go here.
|
||||
* Users should add test code to this method that should run while the robot is in test mode.
|
||||
*/
|
||||
public void test() {
|
||||
System.out.println("Default test() method running, consider providing your own");
|
||||
}
|
||||
|
||||
/**
|
||||
* Robot main program for free-form programs.
|
||||
*
|
||||
* This should be overridden by user subclasses if the intent is to not use the autonomous() and
|
||||
* operatorControl() methods. In that case, the program is responsible for sensing when to run
|
||||
* the autonomous and operator control functions in their program.
|
||||
*
|
||||
* This method will be called immediately after the constructor is called. If it has not been
|
||||
* overridden by a user subclass (i.e. the default version runs), then the robotInit(), disabled(), autonomous() and
|
||||
* operatorControl() methods will be called.
|
||||
*/
|
||||
public void robotMain() {
|
||||
m_robotMainOverridden = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a competition.
|
||||
* This code tracks the order of the field starting to ensure that everything happens
|
||||
* in the right order. Repeatedly run the correct method, either Autonomous or OperatorControl
|
||||
* when the robot is enabled. After running the correct method, wait for some state to change,
|
||||
* either the other mode starts or the robot is disabled. Then go back and wait for the robot
|
||||
* to be enabled again.
|
||||
*/
|
||||
public void startCompetition() {
|
||||
UsageReporting.report(tResourceType.kResourceType_Framework, tInstances.kFramework_Simple);
|
||||
|
||||
robotMain();
|
||||
if (!m_robotMainOverridden) {
|
||||
// first and one-time initialization
|
||||
LiveWindow.setEnabled(false);
|
||||
robotInit();
|
||||
|
||||
while (true) {
|
||||
if (isDisabled()) {
|
||||
m_ds.InDisabled(true);
|
||||
disabled();
|
||||
m_ds.InDisabled(false);
|
||||
while (isDisabled()) {
|
||||
Timer.delay(0.01);
|
||||
}
|
||||
} else if (isAutonomous()) {
|
||||
m_ds.InAutonomous(true);
|
||||
autonomous();
|
||||
m_ds.InAutonomous(false);
|
||||
while (isAutonomous() && !isDisabled()) {
|
||||
Timer.delay(0.01);
|
||||
}
|
||||
} else if (isTest()) {
|
||||
LiveWindow.setEnabled(true);
|
||||
m_ds.InTest(true);
|
||||
test();
|
||||
m_ds.InTest(false);
|
||||
while (isTest() && isEnabled())
|
||||
Timer.delay(0.01);
|
||||
LiveWindow.setEnabled(false);
|
||||
} else {
|
||||
m_ds.InOperatorControl(true);
|
||||
operatorControl();
|
||||
m_ds.InOperatorControl(false);
|
||||
while (isOperatorControl() && !isDisabled()) {
|
||||
Timer.delay(0.01);
|
||||
}
|
||||
}
|
||||
} /* while loop */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
* A Skeleton object to be used with Kinect data from the
|
||||
* FRC Kinect server on the DriverStation
|
||||
* @author koconnor
|
||||
*/
|
||||
public class Skeleton {
|
||||
|
||||
/**
|
||||
* The TrackState of the skeleton
|
||||
*/
|
||||
public static class tTrackState {
|
||||
|
||||
/** The integer value representing this enumeration. */
|
||||
public final int value;
|
||||
|
||||
protected static final int kNotTracked_val = 0;
|
||||
protected static final int kPositionOnly_val = 1;
|
||||
protected static final int kTracked_val = 2;
|
||||
|
||||
/** TrackState: Not Tracked */
|
||||
public static final tTrackState kNotTracked = new tTrackState(kNotTracked_val);
|
||||
/** TrackState: Position Only */
|
||||
public static final tTrackState kPositionOnly = new tTrackState(kPositionOnly_val);
|
||||
/** TrackState: Tracked */
|
||||
public static final tTrackState kTracked = new tTrackState(kTracked_val);
|
||||
|
||||
private tTrackState(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Joint TrackingState
|
||||
*/
|
||||
public static class tJointTrackingState {
|
||||
/** The integer value representing this enumeration. */
|
||||
public final int value;
|
||||
|
||||
protected static final int kNotTracked_val = 0;
|
||||
protected static final int kInferred_val = 1;
|
||||
protected static final int kTracked_val = 2;
|
||||
|
||||
/** Joint TrackingState: Not Tracked */
|
||||
public static final tJointTrackingState kNotTracked = new tJointTrackingState(kNotTracked_val);
|
||||
/** Joint TrackingState: Inferred */
|
||||
public static final tJointTrackingState kInferred = new tJointTrackingState(kInferred_val);
|
||||
/** Joint TrackingState: Tracked */
|
||||
public static final tJointTrackingState kTracked = new tJointTrackingState(kTracked_val);
|
||||
|
||||
private tJointTrackingState(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An individual Joint from Kinect data
|
||||
*/
|
||||
public class Joint {
|
||||
protected float x, y, z;
|
||||
protected byte trackingState;
|
||||
|
||||
Joint() {
|
||||
x = y = z = 0;
|
||||
}
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
public float getY() {
|
||||
return y;
|
||||
}
|
||||
public float getZ() {
|
||||
return z;
|
||||
}
|
||||
public tJointTrackingState getTrackingState() {
|
||||
switch(trackingState) {
|
||||
case 1:
|
||||
return tJointTrackingState.kInferred;
|
||||
case 2:
|
||||
return tJointTrackingState.kTracked;
|
||||
default:
|
||||
return tJointTrackingState.kNotTracked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class used to index the joints in a (@link Skeleton)
|
||||
*/
|
||||
public static class tJointTypes {
|
||||
public final int value;
|
||||
|
||||
protected static final int kHipCenter_val = 0;
|
||||
protected static final int kSpine_val = 1;
|
||||
protected static final int kShoulderCenter_val = 2;
|
||||
protected static final int kHead_val = 3;
|
||||
protected static final int kShoulderLeft_val = 4;
|
||||
protected static final int kElbowLeft_val = 5;
|
||||
protected static final int kWristLeft_val = 6;
|
||||
protected static final int kHandLeft_val = 7;
|
||||
protected static final int kShoulderRight_val = 8;
|
||||
protected static final int kElbowRight_val = 9;
|
||||
protected static final int kWristRight_val = 10;
|
||||
protected static final int kHandRight_val = 11;
|
||||
protected static final int kHipLeft_val = 12;
|
||||
protected static final int kKneeLeft_val = 13;
|
||||
protected static final int kAnkleLeft_val = 14;
|
||||
protected static final int kFootLeft_val = 15;
|
||||
protected static final int kHipRight_val = 16;
|
||||
protected static final int kKneeRight_val = 17;
|
||||
protected static final int kAnkleRight_val = 18;
|
||||
protected static final int kFootRight_val = 19;
|
||||
protected static final int kCount_val = 20;
|
||||
|
||||
public static final tJointTypes kHipCenter = new tJointTypes(kHipCenter_val);
|
||||
public static final tJointTypes kSpine = new tJointTypes(kSpine_val);
|
||||
public static final tJointTypes kShoulderCenter = new tJointTypes(kShoulderCenter_val);
|
||||
public static final tJointTypes kHead = new tJointTypes(kHead_val);
|
||||
public static final tJointTypes kShoulderLeft = new tJointTypes(kShoulderLeft_val);
|
||||
public static final tJointTypes kElbowLeft = new tJointTypes(kElbowLeft_val);
|
||||
public static final tJointTypes kWristLeft = new tJointTypes(kWristLeft_val);
|
||||
public static final tJointTypes kHandLeft = new tJointTypes(kHandLeft_val);
|
||||
public static final tJointTypes kShoulderRight = new tJointTypes(kShoulderRight_val);
|
||||
public static final tJointTypes kElbowRight = new tJointTypes(kElbowRight_val);
|
||||
public static final tJointTypes kWristRight = new tJointTypes(kWristRight_val);
|
||||
public static final tJointTypes kHandRight = new tJointTypes(kHandRight_val);
|
||||
public static final tJointTypes kHipLeft = new tJointTypes(kHipLeft_val);
|
||||
public static final tJointTypes kKneeLeft = new tJointTypes(kKneeLeft_val);
|
||||
public static final tJointTypes kAnkleLeft = new tJointTypes(kAnkleLeft_val);
|
||||
public static final tJointTypes kFootLeft = new tJointTypes(kFootLeft_val);
|
||||
public static final tJointTypes kHipRight = new tJointTypes(kHipRight_val);
|
||||
public static final tJointTypes kKneeRight = new tJointTypes(kKneeRight_val);
|
||||
public static final tJointTypes kAnkleRight = new tJointTypes(kAnkleRight_val);
|
||||
public static final tJointTypes kFootRight = new tJointTypes(kFootRight_val);
|
||||
public static final tJointTypes kCount = new tJointTypes(kCount_val);
|
||||
|
||||
private tJointTypes(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Joint GetHandRight() {
|
||||
return skeleton[tJointTypes.kHandRight.value];
|
||||
}
|
||||
public Joint GetHandLeft() {
|
||||
return skeleton[tJointTypes.kHandLeft.value];
|
||||
}
|
||||
public Joint GetWristRight() {
|
||||
return skeleton[tJointTypes.kWristRight.value];
|
||||
}
|
||||
public Joint GetWristLeft() {
|
||||
return skeleton[tJointTypes.kWristLeft.value];
|
||||
}
|
||||
public Joint GetElbowLeft() {
|
||||
return skeleton[tJointTypes.kElbowLeft.value];
|
||||
}
|
||||
public Joint GetElbowRight() {
|
||||
return skeleton[tJointTypes.kElbowRight.value];
|
||||
}
|
||||
public Joint GetShoulderLeft() {
|
||||
return skeleton[tJointTypes.kShoulderLeft.value];
|
||||
}
|
||||
public Joint GetShoulderRight() {
|
||||
return skeleton[tJointTypes.kShoulderRight.value];
|
||||
}
|
||||
public Joint GetShoulderCenter() {
|
||||
return skeleton[tJointTypes.kShoulderCenter.value];
|
||||
}
|
||||
public Joint GetHead() {
|
||||
return skeleton[tJointTypes.kHead.value];
|
||||
}
|
||||
public Joint GetSpine() {
|
||||
return skeleton[tJointTypes.kSpine.value];
|
||||
}
|
||||
public Joint GetHipCenter() {
|
||||
return skeleton[tJointTypes.kHipCenter.value];
|
||||
}
|
||||
public Joint GetHipRight() {
|
||||
return skeleton[tJointTypes.kHipRight.value];
|
||||
}
|
||||
public Joint GetHipLeft() {
|
||||
return skeleton[tJointTypes.kHipLeft.value];
|
||||
}
|
||||
public Joint GetKneeLeft() {
|
||||
return skeleton[tJointTypes.kKneeLeft.value];
|
||||
}
|
||||
public Joint GetKneeRight() {
|
||||
return skeleton[tJointTypes.kKneeRight.value];
|
||||
}
|
||||
public Joint GetAnkleLeft() {
|
||||
return skeleton[tJointTypes.kAnkleLeft.value];
|
||||
}
|
||||
public Joint GetAnkleRight() {
|
||||
return skeleton[tJointTypes.kAnkleRight.value];
|
||||
}
|
||||
public Joint GetFootLeft() {
|
||||
return skeleton[tJointTypes.kFootLeft.value];
|
||||
}
|
||||
public Joint GetFootRight() {
|
||||
return skeleton[tJointTypes.kFootRight.value];
|
||||
}
|
||||
public Joint GetJoint(tJointTypes index) {
|
||||
return skeleton[index.value];
|
||||
}
|
||||
|
||||
public tTrackState GetTrackState() {
|
||||
return trackState;
|
||||
}
|
||||
|
||||
Skeleton() {
|
||||
for(int i=0; i<20; i++) {
|
||||
skeleton[i] = new Joint();
|
||||
}
|
||||
}
|
||||
|
||||
protected Joint[] skeleton = new Joint[20];
|
||||
protected tTrackState trackState;
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import edu.wpi.first.wpilibj.util.AllocationException;
|
||||
import edu.wpi.first.wpilibj.util.CheckedAllocationException;
|
||||
|
||||
/**
|
||||
* Solenoid class for running high voltage Digital Output (9472 module).
|
||||
*
|
||||
* The Solenoid class is typically used for pneumatics solenoids, but could be used
|
||||
* for any device within the current spec of the 9472 module.
|
||||
*/
|
||||
public class Solenoid extends SolenoidBase implements LiveWindowSendable {
|
||||
|
||||
private int m_channel; ///< The channel on the module to control.
|
||||
private Pointer m_port;
|
||||
|
||||
/**
|
||||
* Common function to implement constructor behavior.
|
||||
*/
|
||||
private synchronized void initSolenoid() {
|
||||
checkSolenoidModule(m_moduleNumber);
|
||||
checkSolenoidChannel(m_channel);
|
||||
|
||||
try {
|
||||
m_allocated.allocate((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1);
|
||||
} catch (CheckedAllocationException e) {
|
||||
throw new AllocationException(
|
||||
"Solenoid channel " + m_channel + " on module " + m_moduleNumber + " is already allocated");
|
||||
}
|
||||
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
m_port = HALLibrary.getPortWithModule((byte) m_moduleNumber, (byte) m_channel);
|
||||
HALUtil.checkStatus(status);
|
||||
HALLibrary.initializeSolenoidPort(m_port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
|
||||
LiveWindow.addActuator("Solenoid", m_moduleNumber, m_channel, this);
|
||||
UsageReporting.report(tResourceType.kResourceType_Solenoid, m_channel, m_moduleNumber - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param channel The channel on the module to control.
|
||||
*/
|
||||
public Solenoid(final int channel) {
|
||||
super(getDefaultSolenoidModule());
|
||||
m_channel = channel;
|
||||
initSolenoid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param moduleNumber The module number of the solenoid module to use.
|
||||
* @param channel The channel on the module to control.
|
||||
*/
|
||||
public Solenoid(final int moduleNumber, final int channel) {
|
||||
super(moduleNumber);
|
||||
m_channel = channel;
|
||||
initSolenoid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public synchronized void free() {
|
||||
m_allocated.free((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a solenoid.
|
||||
*
|
||||
* @param on Turn the solenoid output off or on.
|
||||
*/
|
||||
public void set(boolean on) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
HALLibrary.setSolenoid(m_port, (byte) (on ? 1 : 0), status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the current value of the solenoid.
|
||||
*
|
||||
* @return The current value of the solenoid.
|
||||
*/
|
||||
public boolean get() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
boolean value = HALLibrary.getSolenoid(m_port, status) != 0;
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Solenoid";
|
||||
}
|
||||
private ITable m_table;
|
||||
private ITableListener m_table_listener;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putBoolean("Value", get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
set(false); // Stop for safety
|
||||
m_table_listener = new ITableListener() {
|
||||
public void valueChanged(ITable itable, String key, Object value, boolean bln) {
|
||||
set(((Boolean) value).booleanValue());
|
||||
}
|
||||
};
|
||||
m_table.addTableListener("Value", m_table_listener, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
set(false); // Stop for safety
|
||||
// TODO: Broken, should only remove the listener from "Value" only.
|
||||
m_table.removeTableListener(m_table_listener);
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import com.sun.jna.Pointer;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.parsing.IDeviceController;
|
||||
|
||||
/**
|
||||
* SolenoidBase class is the common base class for the Solenoid and
|
||||
* DoubleSolenoid classes.
|
||||
*/
|
||||
public abstract class SolenoidBase extends SensorBase implements IDeviceController {
|
||||
|
||||
private Pointer[] m_ports;
|
||||
protected int m_moduleNumber; ///< The number of the solenoid module being used.
|
||||
// XXX: Move this to be both HAL calls
|
||||
protected Resource m_allocated = new Resource(HALLibrary.solenoid_kNumDO7_0Elements.get() * SensorBase.kSolenoidChannels);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param moduleNumber The number of the solenoid module to use.
|
||||
*/
|
||||
public SolenoidBase(final int moduleNumber) {
|
||||
m_moduleNumber = moduleNumber;
|
||||
m_ports = new Pointer[SensorBase.kSolenoidChannels];
|
||||
for (int i = 0; i < SensorBase.kSolenoidChannels; i++) {
|
||||
Pointer port = HALLibrary.getPortWithModule((byte) moduleNumber, (byte) (i+1));
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
m_ports[i] = HALLibrary.initializeSolenoidPort(port, status);
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a solenoid.
|
||||
*
|
||||
* @param value The value you want to set on the module.
|
||||
* @param mask The channels you want to be affected.
|
||||
*/
|
||||
protected synchronized void set(int value, int mask) {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
for (int i = 0; i < SensorBase.kSolenoidChannels; i++) {
|
||||
int local_mask = 1 << i;
|
||||
if ((mask & local_mask) != 0)
|
||||
HALLibrary.setSolenoid(m_ports[i], (byte) (value & local_mask), status);
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all 8 solenoids from the module used by this solenoid as a single byte
|
||||
*
|
||||
* @return The current value of all 8 solenoids on this module.
|
||||
*/
|
||||
public byte getAll() {
|
||||
byte value = 0;
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
for (int i = 0; i < SensorBase.kSolenoidChannels; i++) {
|
||||
value |= HALLibrary.getSolenoid(m_ports[i], status) << i;
|
||||
}
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all 8 solenoids in the default solenoid module as a single byte
|
||||
*
|
||||
* @return The current value of all 8 solenoids on the default module.
|
||||
*/
|
||||
public static byte getAllFromDefaultModule() {
|
||||
return getAllFromModule(getDefaultSolenoidModule());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all 8 solenoids in the specified solenoid module as a single byte
|
||||
*
|
||||
* @return The current value of all 8 solenoids on the specified module.
|
||||
*/
|
||||
public static byte getAllFromModule(int moduleNumber) {
|
||||
checkSolenoidModule(moduleNumber);
|
||||
throw new RuntimeException("Not supported right now.");
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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;
|
||||
|
||||
/**
|
||||
* Interface for speed controlling devices.
|
||||
*/
|
||||
public interface SpeedController extends PIDOutput {
|
||||
|
||||
/**
|
||||
* Common interface for getting the current set speed of a speed controller.
|
||||
*
|
||||
* @return The current set speed. Value is between -1.0 and 1.0.
|
||||
*/
|
||||
double get();
|
||||
|
||||
/**
|
||||
* Common interface for setting the speed of a speed controller.
|
||||
*
|
||||
* @param speed The speed to set. Value should be between -1.0 and 1.0.
|
||||
* @param syncGroup The update group to add this Set() to, pending UpdateSyncGroup(). If 0, update immediately.
|
||||
*/
|
||||
void set(double speed, byte syncGroup);
|
||||
|
||||
/**
|
||||
* Common interface for setting the speed of a speed controller.
|
||||
*
|
||||
* @param speed The speed to set. Value should be between -1.0 and 1.0.
|
||||
*/
|
||||
void set(double speed);
|
||||
|
||||
/**
|
||||
* Disable the speed controller
|
||||
*/
|
||||
void disable();
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.parsing.IDeviceController;
|
||||
|
||||
/**
|
||||
* CTRE Talon Speed Controller
|
||||
*/
|
||||
public class Talon extends SafePWM implements SpeedController, IDeviceController {
|
||||
|
||||
/**
|
||||
* Common initialization code called by all constructors.
|
||||
*
|
||||
* Note that the Talon uses the following bounds for PWM values. These values should work reasonably well for
|
||||
* most controllers, but if users experience issues such as asymmetric behavior around
|
||||
* the deadband or inability to saturate the controller in either direction, calibration is recommended.
|
||||
* The calibration procedure can be found in the Talon User Manual available from CTRE.
|
||||
*
|
||||
* - 2.037ms = full "forward"
|
||||
* - 1.539ms = the "high end" of the deadband range
|
||||
* - 1.513ms = center of the deadband range (off)
|
||||
* - 1.487ms = the "low end" of the deadband range
|
||||
* - .989ms = full "reverse"
|
||||
*/
|
||||
private void initTalon() {
|
||||
setBounds(2.037, 1.539, 1.513, 1.487, .989);
|
||||
setPeriodMultiplier(PeriodMultiplier.k2X);
|
||||
setRaw(m_centerPwm);
|
||||
|
||||
LiveWindow.addActuator("Talon", getModuleNumber(), getChannel(), this);
|
||||
UsageReporting.report(tResourceType.kResourceType_Talon, getChannel(), getModuleNumber()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that assumes the default digital module.
|
||||
*
|
||||
* @param channel The PWM channel on the digital module that the Victor is attached to.
|
||||
*/
|
||||
public Talon(final int channel) {
|
||||
super(channel);
|
||||
initTalon();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that specifies the digital module.
|
||||
*
|
||||
* @param slot The slot in the chassis that the digital module is plugged into.
|
||||
* @param channel The PWM channel on the digital module that the Victor is attached to.
|
||||
*/
|
||||
public Talon(final int slot, final int channel) {
|
||||
super(slot, channel);
|
||||
initTalon();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value.
|
||||
*
|
||||
* @deprecated For compatibility with CANJaguar
|
||||
*
|
||||
* The PWM value is set using a range of -1.0 to 1.0, appropriately
|
||||
* scaling the value for the FPGA.
|
||||
*
|
||||
* @param speed The speed to set. Value should be between -1.0 and 1.0.
|
||||
* @param syncGroup The update group to add this Set() to, pending UpdateSyncGroup(). If 0, update immediately.
|
||||
*/
|
||||
public void set(double speed, byte syncGroup) {
|
||||
setSpeed(speed);
|
||||
Feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value.
|
||||
*
|
||||
* The PWM value is set using a range of -1.0 to 1.0, appropriately
|
||||
* scaling the value for the FPGA.
|
||||
*
|
||||
* @param speed The speed value between -1.0 and 1.0 to set.
|
||||
*/
|
||||
public void set(double speed) {
|
||||
setSpeed(speed);
|
||||
Feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the recently set value of the PWM.
|
||||
*
|
||||
* @return The most recently set value for the PWM between -1.0 and 1.0.
|
||||
*/
|
||||
public double get() {
|
||||
return getSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write out the PID value as seen in the PIDOutput base object.
|
||||
*
|
||||
* @param output Write out the PWM value as was found in the PIDController
|
||||
*/
|
||||
public void pidWrite(double output) {
|
||||
set(output);
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.parsing.IUtility;
|
||||
|
||||
/**
|
||||
* Timer objects measure accumulated time in milliseconds.
|
||||
* The timer object functions like a stopwatch. It can be started, stopped, and cleared. When the
|
||||
* timer is running its value counts up in milliseconds. When stopped, the timer holds the current
|
||||
* value. The implementation simply records the time when started and subtracts the current time
|
||||
* whenever the value is requested.
|
||||
*/
|
||||
public class Timer implements IUtility {
|
||||
|
||||
private long m_startTime;
|
||||
private double m_accumulatedTime;
|
||||
private boolean m_running;
|
||||
|
||||
/**
|
||||
* Pause the thread for a specified time. Pause the execution of the
|
||||
* thread for a specified period of time given in seconds. Motors will
|
||||
* continue to run at their last assigned values, and sensors will continue
|
||||
* to update. Only the task containing the wait will pause until the wait
|
||||
* time is expired.
|
||||
*
|
||||
* @param seconds Length of time to pause
|
||||
*/
|
||||
public static void delay(final double seconds) {
|
||||
try {
|
||||
Thread.sleep((long) (seconds * 1e3));
|
||||
} catch (final InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the system clock time in microseconds. Return the time from the
|
||||
* FPGA hardware clock in microseconds since the FPGA started.
|
||||
*
|
||||
* @deprecated Use getFPGATimestamp instead.
|
||||
* @return Robot running time in microseconds.
|
||||
*/
|
||||
public static long getUsClock() {
|
||||
return Utility.getFPGATime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the system clock time in milliseconds. Return the time from the
|
||||
* FPGA hardware clock in milliseconds since the FPGA started.
|
||||
*
|
||||
* @deprecated Use getFPGATimestamp instead.
|
||||
* @return Robot running time in milliseconds.
|
||||
*/
|
||||
static long getMsClock() {
|
||||
return getUsClock() / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the system clock time in seconds. Return the time from the
|
||||
* FPGA hardware clock in seconds since the FPGA started.
|
||||
*
|
||||
* @return Robot running time in seconds.
|
||||
*/
|
||||
public static double getFPGATimestamp() {
|
||||
return Utility.getFPGATime() / 1000000.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new timer object.
|
||||
* Create a new timer object and reset the time to zero. The timer is initially not running and
|
||||
* must be started.
|
||||
*/
|
||||
public Timer() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current time from the timer. If the clock is running it is derived from
|
||||
* the current system clock the start time stored in the timer class. If the clock
|
||||
* is not running, then return the time when it was last stopped.
|
||||
*
|
||||
* @return Current time value for this timer in seconds
|
||||
*/
|
||||
public synchronized double get() {
|
||||
if (m_running) {
|
||||
return ((double) ((getMsClock() - m_startTime) + m_accumulatedTime)) / 1000.0;
|
||||
} else {
|
||||
return m_accumulatedTime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the timer by setting the time to 0.
|
||||
* Make the timer startTime the current time so new requests will be relative now
|
||||
*/
|
||||
public synchronized void reset() {
|
||||
m_accumulatedTime = 0;
|
||||
m_startTime = getMsClock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the timer running.
|
||||
* Just set the running flag to true indicating that all time requests should be
|
||||
* relative to the system clock.
|
||||
*/
|
||||
public synchronized void start() {
|
||||
m_startTime = getMsClock();
|
||||
m_running = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the timer.
|
||||
* This computes the time as of now and clears the running flag, causing all
|
||||
* subsequent time requests to be read from the accumulated time rather than
|
||||
* looking at the system clock.
|
||||
*/
|
||||
public synchronized void stop() {
|
||||
final double temp = get();
|
||||
m_accumulatedTime = temp;
|
||||
m_running = false;
|
||||
}
|
||||
}
|
||||
@@ -1,520 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
|
||||
import edu.wpi.first.wpilibj.parsing.ISensor;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
* Ultrasonic rangefinder class. The Ultrasonic rangefinder measures absolute
|
||||
* distance based on the round-trip time of a ping generated by the controller.
|
||||
* These sensors use two transducers, a speaker and a microphone both tuned to
|
||||
* the ultrasonic range. A common ultrasonic sensor, the Daventech SRF04
|
||||
* requires a short pulse to be generated on a digital channel. This causes the
|
||||
* chirp to be emmitted. A second line becomes high as the ping is transmitted
|
||||
* and goes low when the 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, ISensor,
|
||||
LiveWindowSendable {
|
||||
|
||||
/**
|
||||
* The units to return when PIDGet is called
|
||||
*/
|
||||
public static class Unit {
|
||||
|
||||
/**
|
||||
* The integer value representing this enumeration
|
||||
*/
|
||||
public final int value;
|
||||
static final int kInches_val = 0;
|
||||
static final int kMillimeters_val = 1;
|
||||
/**
|
||||
* Use inches for PIDGet
|
||||
*/
|
||||
public static final Unit kInches = new Unit(kInches_val);
|
||||
/**
|
||||
* Use millimeters for PIDGet
|
||||
*/
|
||||
public static final Unit kMillimeter = new Unit(kMillimeters_val);
|
||||
|
||||
private Unit(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static final double kPingTime = 10 * 1e-6; // /< Time (sec) for the
|
||||
// ping trigger pulse.
|
||||
private static final int kPriority = 90; // /< Priority that the ultrasonic
|
||||
// round robin task runs.
|
||||
private static final double kMaxUltrasonicTime = 0.1; // /< Max time (ms)
|
||||
// between readings.
|
||||
private static final double kSpeedOfSoundInchesPerSec = 1130.0 * 12.0;
|
||||
private static Ultrasonic m_firstSensor = null; // head of the ultrasonic
|
||||
// sensor list
|
||||
private static boolean m_automaticEnabled = false; // automatic round robin
|
||||
// mode
|
||||
private DigitalInput m_echoChannel = null;
|
||||
private DigitalOutput m_pingChannel = null;
|
||||
private boolean m_allocatedChannels;
|
||||
private boolean m_enabled = false;
|
||||
private Counter m_counter = null;
|
||||
private Ultrasonic m_nextSensor = null;
|
||||
private static Thread m_task = null; // task doing the round-robin automatic
|
||||
// sensing
|
||||
private Unit m_units;
|
||||
private static int m_instances = 0;
|
||||
|
||||
/**
|
||||
* Background task that goes through the list of ultrasonic sensors and
|
||||
* pings each one in turn. The counter is configured to read the timing of
|
||||
* the returned echo pulse.
|
||||
*
|
||||
* DANGER WILL ROBINSON, DANGER WILL ROBINSON: This code runs as a task and
|
||||
* assumes that none of the ultrasonic sensors will change while it's
|
||||
* running. If one does, then this will certainly break. Make sure to
|
||||
* disable automatic mode before changing anything with the sensors!!
|
||||
*/
|
||||
private class UltrasonicChecker extends Thread {
|
||||
|
||||
public synchronized void run() {
|
||||
Ultrasonic u = null;
|
||||
while (m_automaticEnabled) {
|
||||
if (u == null) {
|
||||
u = m_firstSensor;
|
||||
}
|
||||
if (u == null) {
|
||||
return;
|
||||
}
|
||||
if (u.isEnabled()) {
|
||||
u.m_pingChannel.pulse(m_pingChannel.m_channel,
|
||||
(float) kPingTime); // do the ping
|
||||
}
|
||||
u = u.m_nextSensor;
|
||||
Timer.delay(.1); // wait for ping to return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Ultrasonic Sensor. This is the common code that
|
||||
* initializes the ultrasonic sensor given that there are two digital I/O
|
||||
* channels allocated. If the system was running in automatic mode (round
|
||||
* robin) when the new sensor is added, it is stopped, the sensor is added,
|
||||
* then automatic mode is restored.
|
||||
*/
|
||||
private synchronized void initialize() {
|
||||
if (m_task == null) {
|
||||
m_task = new UltrasonicChecker();
|
||||
}
|
||||
boolean originalMode = m_automaticEnabled;
|
||||
setAutomaticMode(false); // kill task when adding a new sensor
|
||||
m_nextSensor = m_firstSensor;
|
||||
m_firstSensor = this;
|
||||
|
||||
m_counter = new Counter(m_echoChannel); // set up counter for this
|
||||
// sensor
|
||||
m_counter.setMaxPeriod(1.0);
|
||||
m_counter.setSemiPeriodMode(true);
|
||||
m_counter.reset();
|
||||
m_counter.start();
|
||||
m_enabled = true; // make it available for round robin scheduling
|
||||
setAutomaticMode(originalMode);
|
||||
|
||||
m_instances++;
|
||||
UsageReporting.report(tResourceType.kResourceType_Ultrasonic,
|
||||
m_instances);
|
||||
LiveWindow.addSensor("Ultrasonic", m_echoChannel.getModuleForRouting(),
|
||||
m_echoChannel.getChannel(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the Ultrasonic Sensor using the default module.
|
||||
* This is designed to supchannel the Daventech SRF04 and Vex ultrasonic
|
||||
* sensors. This constructor assumes that both digital I/O channels are in
|
||||
* the default digital module.
|
||||
*
|
||||
* @param pingChannel
|
||||
* The digital output channel that sends the pulse to initiate
|
||||
* the sensor sending the ping.
|
||||
* @param echoChannel
|
||||
* The digital input channel that receives the echo. The length
|
||||
* of time that the echo is high represents the round trip time
|
||||
* of the ping, and the distance.
|
||||
* @param units
|
||||
* The units returned in either kInches or kMilliMeters
|
||||
*/
|
||||
public Ultrasonic(final int pingChannel, final int echoChannel, Unit units) {
|
||||
m_pingChannel = new DigitalOutput(pingChannel);
|
||||
m_echoChannel = new DigitalInput(echoChannel);
|
||||
m_allocatedChannels = true;
|
||||
m_units = units;
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the Ultrasonic Sensor using the default module.
|
||||
* This is designed to supchannel the Daventech SRF04 and Vex ultrasonic
|
||||
* sensors. This constructor assumes that both digital I/O channels are in
|
||||
* the default digital module. Default unit is inches.
|
||||
*
|
||||
* @param pingChannel
|
||||
* The digital output channel that sends the pulse to initiate
|
||||
* the sensor sending the ping.
|
||||
* @param echoChannel
|
||||
* The digital input channel that receives the echo. The length
|
||||
* of time that the echo is high represents the round trip time
|
||||
* of the ping, and the distance.
|
||||
*/
|
||||
public Ultrasonic(final int pingChannel, final int echoChannel) {
|
||||
this(pingChannel, echoChannel, Unit.kInches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of an Ultrasonic Sensor from a DigitalInput for the
|
||||
* echo channel and a DigitalOutput for the ping channel.
|
||||
*
|
||||
* @param pingChannel
|
||||
* The digital output object that starts the sensor doing a ping.
|
||||
* Requires a 10uS pulse to start.
|
||||
* @param echoChannel
|
||||
* The digital input object that times the return pulse to
|
||||
* determine the range.
|
||||
* @param units
|
||||
* The units returned in either kInches or kMilliMeters
|
||||
*/
|
||||
public Ultrasonic(DigitalOutput pingChannel, DigitalInput echoChannel,
|
||||
Unit units) {
|
||||
if (pingChannel == null || echoChannel == null) {
|
||||
throw new NullPointerException("Null Channel Provided");
|
||||
}
|
||||
m_allocatedChannels = false;
|
||||
m_pingChannel = pingChannel;
|
||||
m_echoChannel = echoChannel;
|
||||
m_units = units;
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of an Ultrasonic Sensor from a DigitalInput for the
|
||||
* echo channel and a DigitalOutput for the ping channel. Default unit is
|
||||
* inches.
|
||||
*
|
||||
* @param pingChannel
|
||||
* The digital output object that starts the sensor doing a ping.
|
||||
* Requires a 10uS pulse to start.
|
||||
* @param echoChannel
|
||||
* The digital input object that times the return pulse to
|
||||
* determine the range.
|
||||
*/
|
||||
public Ultrasonic(DigitalOutput pingChannel, DigitalInput echoChannel) {
|
||||
this(pingChannel, echoChannel, Unit.kInches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the Ultrasonic sensor using specified modules. This
|
||||
* is designed to supchannel the Daventech SRF04 and Vex ultrasonic sensors.
|
||||
* This constructors takes the channel and module slot for each of the
|
||||
* required digital I/O channels.
|
||||
*
|
||||
* @param pingSlot
|
||||
* The digital module that the pingChannel is in.
|
||||
* @param pingChannel
|
||||
* The digital output channel that sends the pulse to initiate
|
||||
* the sensor sending the ping.
|
||||
* @param echoSlot
|
||||
* The digital module that the echoChannel is in.
|
||||
* @param echoChannel
|
||||
* The digital input channel that receives the echo. The length
|
||||
* of time that the echo is high represents the round trip time
|
||||
* of the ping, and the distance.
|
||||
* @param units
|
||||
* The units returned in either kInches or kMilliMeters
|
||||
*/
|
||||
public Ultrasonic(final int pingSlot, final int pingChannel,
|
||||
final int echoSlot, final int echoChannel, Unit units) {
|
||||
m_pingChannel = new DigitalOutput(pingSlot, pingChannel);
|
||||
m_echoChannel = new DigitalInput(echoSlot, echoChannel);
|
||||
m_allocatedChannels = true;
|
||||
m_units = units;
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the Ultrasonic sensor using specified modules. This
|
||||
* is designed to supchannel the Daventech SRF04 and Vex ultrasonic sensors.
|
||||
* This constructors takes the channel and module slot for each of the
|
||||
* required digital I/O channels. Defualt unit is inches.
|
||||
*
|
||||
* @param pingSlot
|
||||
* The digital module that the pingChannel is in.
|
||||
* @param pingChannel
|
||||
* The digital output channel that sends the pulse to initiate
|
||||
* the sensor sending the ping.
|
||||
* @param echoSlot
|
||||
* The digital module that the echoChannel is in.
|
||||
* @param echoChannel
|
||||
* The digital input channel that receives the echo. The length
|
||||
* of time that the echo is high represents the round trip time
|
||||
* of the ping, and the distance.
|
||||
*/
|
||||
public Ultrasonic(final int pingSlot, final int pingChannel,
|
||||
final int echoSlot, final int echoChannel) {
|
||||
this(pingSlot, pingChannel, echoSlot, echoChannel, Unit.kInches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor for the ultrasonic sensor. Delete the instance of the
|
||||
* ultrasonic sensor by freeing the allocated digital channels. If the
|
||||
* system was in automatic mode (round robin), then it is stopped, then
|
||||
* started again after this sensor is removed (provided this wasn't the last
|
||||
* sensor).
|
||||
*/
|
||||
public synchronized void free() {
|
||||
boolean wasAutomaticMode = m_automaticEnabled;
|
||||
setAutomaticMode(false);
|
||||
if (m_allocatedChannels) {
|
||||
if (m_pingChannel != null) {
|
||||
m_pingChannel.free();
|
||||
}
|
||||
if (m_echoChannel != null) {
|
||||
m_echoChannel.free();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_counter != null) {
|
||||
m_counter.free();
|
||||
m_counter = null;
|
||||
}
|
||||
|
||||
m_pingChannel = null;
|
||||
m_echoChannel = null;
|
||||
|
||||
if (this == m_firstSensor) {
|
||||
m_firstSensor = m_nextSensor;
|
||||
if (m_firstSensor == null) {
|
||||
setAutomaticMode(false);
|
||||
}
|
||||
} else {
|
||||
for (Ultrasonic s = m_firstSensor; s != null; s = s.m_nextSensor) {
|
||||
if (this == s.m_nextSensor) {
|
||||
s.m_nextSensor = s.m_nextSensor.m_nextSensor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_firstSensor != null && wasAutomaticMode) {
|
||||
setAutomaticMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn Automatic mode on/off. When in Automatic mode, all sensors will fire
|
||||
* in round robin, waiting a set time between each sensor.
|
||||
*
|
||||
* @param enabling
|
||||
* Set to true if round robin scheduling should start for all the
|
||||
* ultrasonic sensors. This scheduling method assures that the
|
||||
* sensors are non-interfering because no two sensors fire at the
|
||||
* same time. If another scheduling algorithm is preffered, it
|
||||
* can be implemented by pinging the sensors manually and waiting
|
||||
* for the results to come back.
|
||||
*/
|
||||
public void setAutomaticMode(boolean enabling) {
|
||||
if (enabling == m_automaticEnabled) {
|
||||
return; // ignore the case of no change
|
||||
}
|
||||
m_automaticEnabled = enabling;
|
||||
|
||||
if (enabling) {
|
||||
// enabling automatic mode.
|
||||
// Clear all the counters so no data is valid
|
||||
for (Ultrasonic u = m_firstSensor; u != null; u = u.m_nextSensor) {
|
||||
u.m_counter.reset();
|
||||
}
|
||||
// Start round robin task
|
||||
m_task.start();
|
||||
} else {
|
||||
// disabling automatic mode. Wait for background task to stop
|
||||
// running.
|
||||
while (m_task.isAlive()) {
|
||||
Timer.delay(.15); // just a little longer than the ping time for
|
||||
// round-robin to stop
|
||||
}
|
||||
// clear all the counters (data now invalid) since automatic mode is
|
||||
// stopped
|
||||
for (Ultrasonic u = m_firstSensor; u != null; u = u.m_nextSensor) {
|
||||
u.m_counter.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Single ping to ultrasonic sensor. Send out a single ping to the
|
||||
* ultrasonic sensor. This only works if automatic (round robin) mode is
|
||||
* disabled. A single ping is sent out, and the counter should count the
|
||||
* semi-period when it comes in. The counter is reset to make the current
|
||||
* value invalid.
|
||||
*/
|
||||
public void ping() {
|
||||
setAutomaticMode(false); // turn off automatic round robin if pinging
|
||||
// single sensor
|
||||
m_counter.reset(); // reset the counter to zero (invalid data now)
|
||||
m_pingChannel.pulse(m_pingChannel.m_channel, (float) kPingTime); // do
|
||||
// the
|
||||
// ping
|
||||
// to
|
||||
// start
|
||||
// getting
|
||||
// a
|
||||
// single
|
||||
// range
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is a valid range measurement. The ranges are accumulated
|
||||
* in a counter that will increment on each edge of the echo (return)
|
||||
* signal. If the count is not at least 2, then the range has not yet been
|
||||
* measured, and is invalid.
|
||||
*
|
||||
* @return true if the range is valid
|
||||
*/
|
||||
public boolean isRangeValid() {
|
||||
return m_counter.get() > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range in inches from the ultrasonic sensor.
|
||||
*
|
||||
* @return double Range in inches of the target returned from the ultrasonic
|
||||
* sensor. If there is no valid value yet, i.e. at least one
|
||||
* measurement hasn't completed, then return 0.
|
||||
*/
|
||||
public double getRangeInches() {
|
||||
if (isRangeValid()) {
|
||||
return m_counter.getPeriod() * kSpeedOfSoundInchesPerSec / 2.0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range in millimeters from the ultrasonic sensor.
|
||||
*
|
||||
* @return double Range in millimeters of the target returned by the
|
||||
* ultrasonic sensor. If there is no valid value yet, i.e. at least
|
||||
* one measurement hasn't complted, then return 0.
|
||||
*/
|
||||
public double getRangeMM() {
|
||||
return getRangeInches() * 25.4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range in the current DistanceUnit for the PIDSource base object.
|
||||
*
|
||||
* @return The range in DistanceUnit
|
||||
*/
|
||||
public double pidGet() {
|
||||
switch (m_units.value) {
|
||||
case Unit.kInches_val:
|
||||
return getRangeInches();
|
||||
case Unit.kMillimeters_val:
|
||||
return getRangeMM();
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current DistanceUnit that should be used for the PIDSource base
|
||||
* object.
|
||||
*
|
||||
* @param units
|
||||
* The DistanceUnit that should be used.
|
||||
*/
|
||||
public void setDistanceUnits(Unit units) {
|
||||
m_units = units;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current DistanceUnit that is used for the PIDSource base object.
|
||||
*
|
||||
* @return The type of DistanceUnit that is being used.
|
||||
*/
|
||||
public Unit getDistanceUnits() {
|
||||
return m_units;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the ultrasonic enabled
|
||||
*
|
||||
* @return true if the ultrasonic is enabled
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the ultrasonic is enabled
|
||||
*
|
||||
* @param enable
|
||||
* set to true to enable the ultrasonic
|
||||
*/
|
||||
public void setEnabled(boolean enable) {
|
||||
m_enabled = enable;
|
||||
}
|
||||
|
||||
/*
|
||||
* Live Window code, only does anything if live window is activated.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Ultrasonic";
|
||||
}
|
||||
|
||||
private ITable m_table;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void updateTable() {
|
||||
if (m_table != null) {
|
||||
m_table.putNumber("Value", getRangeInches());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void startLiveWindowMode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stopLiveWindowMode() {
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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 java.nio.IntBuffer;
|
||||
|
||||
import edu.wpi.first.wpilibj.hal.HALLibrary;
|
||||
import edu.wpi.first.wpilibj.hal.HALUtil;
|
||||
import edu.wpi.first.wpilibj.parsing.IUtility;
|
||||
|
||||
/**
|
||||
* Contains global utility functions
|
||||
*/
|
||||
public class Utility implements IUtility {
|
||||
|
||||
private Utility() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FPGA Version number. For now, expect this to be 2009.
|
||||
*
|
||||
* @return FPGA Version number.
|
||||
*/
|
||||
int getFPGAVersion() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getFPGAVersion(status);
|
||||
HALUtil.checkStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FPGA Revision number. The format of the revision is 3 numbers.
|
||||
* The 12 most significant bits are the Major Revision. the next 8 bits are
|
||||
* the Minor Revision. The 12 least significant bits are the Build Number.
|
||||
*
|
||||
* @return FPGA Revision number.
|
||||
*/
|
||||
long getFPGARevision() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getFPGARevision(status);
|
||||
HALUtil.checkStatus(status);
|
||||
return (long) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the microsecond timer from the FPGA.
|
||||
*
|
||||
* @return The current time in microseconds according to the FPGA.
|
||||
*/
|
||||
public static long getFPGATime() {
|
||||
IntBuffer status = IntBuffer.allocate(1);
|
||||
int value = HALLibrary.getFPGATime(status);
|
||||
HALUtil.checkStatus(status);
|
||||
return (long) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control whether to send System.err output to the driver station's error
|
||||
* pane.
|
||||
*
|
||||
* @param enabled
|
||||
* if true, send error stream to driver station, otherwise
|
||||
* disable sending error stream
|
||||
*/
|
||||
public static void sendErrorStreamToDriverStation(boolean enabled) {
|
||||
final String url = "dserror:edu.wpi.first.wpilibj.Utility"; // the path
|
||||
// is just a
|
||||
// comment.
|
||||
/* XXX: Code Review!
|
||||
Isolate isolate = VM.getCurrentIsolate();
|
||||
if (enabled) {
|
||||
isolate.addErr(url);
|
||||
} else {
|
||||
isolate.removeErr(url);
|
||||
} */
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj.parsing.IDeviceController;
|
||||
|
||||
/**
|
||||
* VEX Robotics Victor Speed Controller
|
||||
*/
|
||||
public class Victor extends SafePWM implements SpeedController, IDeviceController {
|
||||
|
||||
/**
|
||||
* Common initialization code called by all constructors.
|
||||
*
|
||||
* Note that the Victor uses the following bounds for PWM values. These values were determined
|
||||
* empirically and optimized for the Victor 888. These values should work reasonably well for
|
||||
* Victor 884 controllers also but if users experience issues such as asymmetric behavior around
|
||||
* the deadband or inability to saturate the controller in either direction, calibration is recommended.
|
||||
* The calibration procedure can be found in the Victor 884 User Manual available from VEX Robotics:
|
||||
* http://content.vexrobotics.com/docs/ifi-v884-users-manual-9-25-06.pdf
|
||||
*
|
||||
* - 2.027ms = full "forward"
|
||||
* - 1.525ms = the "high end" of the deadband range
|
||||
* - 1.507ms = center of the deadband range (off)
|
||||
* - 1.49ms = the "low end" of the deadband range
|
||||
* - 1.026ms = full "reverse"
|
||||
*/
|
||||
private void initVictor() {
|
||||
setBounds(2.027, 1.525, 1.507, 1.49, 1.026);
|
||||
setPeriodMultiplier(PeriodMultiplier.k2X);
|
||||
setRaw(m_centerPwm);
|
||||
|
||||
LiveWindow.addActuator("Victor", getModuleNumber(), getChannel(), this);
|
||||
UsageReporting.report(tResourceType.kResourceType_Victor, getChannel(), getModuleNumber()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that assumes the default digital module.
|
||||
*
|
||||
* @param channel The PWM channel on the digital module that the Victor is attached to.
|
||||
*/
|
||||
public Victor(final int channel) {
|
||||
super(channel);
|
||||
initVictor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that specifies the digital module.
|
||||
*
|
||||
* @param slot The slot in the chassis that the digital module is plugged into.
|
||||
* @param channel The PWM channel on the digital module that the Victor is attached to.
|
||||
*/
|
||||
public Victor(final int slot, final int channel) {
|
||||
super(slot, channel);
|
||||
initVictor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value.
|
||||
*
|
||||
* @deprecated For compatibility with CANJaguar
|
||||
*
|
||||
* The PWM value is set using a range of -1.0 to 1.0, appropriately
|
||||
* scaling the value for the FPGA.
|
||||
*
|
||||
* @param speed The speed to set. Value should be between -1.0 and 1.0.
|
||||
* @param syncGroup The update group to add this Set() to, pending UpdateSyncGroup(). If 0, update immediately.
|
||||
*/
|
||||
public void set(double speed, byte syncGroup) {
|
||||
setSpeed(speed);
|
||||
Feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value.
|
||||
*
|
||||
* The PWM value is set using a range of -1.0 to 1.0, appropriately
|
||||
* scaling the value for the FPGA.
|
||||
*
|
||||
* @param speed The speed value between -1.0 and 1.0 to set.
|
||||
*/
|
||||
public void set(double speed) {
|
||||
setSpeed(speed);
|
||||
Feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the recently set value of the PWM.
|
||||
*
|
||||
* @return The most recently set value for the PWM between -1.0 and 1.0.
|
||||
*/
|
||||
public double get() {
|
||||
return getSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write out the PID value as seen in the PIDOutput base object.
|
||||
*
|
||||
* @param output Write out the PWM value as was found in the PIDController
|
||||
*/
|
||||
public void pidWrite(double output) {
|
||||
set(output);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.buttons;
|
||||
|
||||
import edu.wpi.first.wpilibj.DriverStation;
|
||||
import edu.wpi.first.wpilibj.DriverStationEnhancedIO.EnhancedIOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Greg
|
||||
*/
|
||||
public class AnalogIOButton extends Trigger {
|
||||
|
||||
public static double THRESHOLD = 0.5;
|
||||
|
||||
int port;
|
||||
|
||||
public AnalogIOButton(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public boolean get() {
|
||||
try {
|
||||
return DriverStation.getInstance().getEnhancedIO().getAnalogIn(port) < THRESHOLD;
|
||||
} catch (EnhancedIOException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.buttons;
|
||||
|
||||
import edu.wpi.first.wpilibj.command.Command;
|
||||
|
||||
/**
|
||||
* This class provides an easy way to link commands to OI inputs.
|
||||
*
|
||||
* It is very easy to link a button to a command. For instance, you could
|
||||
* link the trigger button of a joystick to a "score" command.
|
||||
*
|
||||
* This class represents a subclass of Trigger that is specifically aimed at
|
||||
* buttons on an operator interface as a common use case of the more generalized
|
||||
* Trigger objects. This is a simple wrapper around Trigger with the method names
|
||||
* renamed to fit the Button object use.
|
||||
*
|
||||
* @author brad
|
||||
*/
|
||||
public abstract class Button extends Trigger {
|
||||
|
||||
/**
|
||||
* Starts the given command whenever the button is newly pressed.
|
||||
* @param command the command to start
|
||||
*/
|
||||
public void whenPressed(final Command command) {
|
||||
whenActive(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constantly starts the given command while the button is held.
|
||||
*
|
||||
* {@link Command#start()} will be called repeatedly while the button is held,
|
||||
* and will be canceled when the button is released.
|
||||
*
|
||||
* @param command the command to start
|
||||
*/
|
||||
public void whileHeld(final Command command) {
|
||||
whileActive(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the command when the button is released
|
||||
* @param command the command to start
|
||||
*/
|
||||
public void whenReleased(final Command command) {
|
||||
whenInactive(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the command whenever the button is pressed (on then off then on)
|
||||
* @param command
|
||||
*/
|
||||
public void toggleWhenPressed(final Command command) {
|
||||
toggleWhenActive(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the command when the button is pressed
|
||||
* @param command
|
||||
*/
|
||||
public void cancelWhenPressed(final Command command) {
|
||||
cancelWhenActive(command);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.buttons;
|
||||
|
||||
import edu.wpi.first.wpilibj.DriverStation;
|
||||
import edu.wpi.first.wpilibj.DriverStationEnhancedIO.EnhancedIOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Greg
|
||||
*/
|
||||
public class DigitalIOButton extends Button {
|
||||
public final static boolean ACTIVE_STATE = false;
|
||||
|
||||
int port;
|
||||
|
||||
public DigitalIOButton(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public boolean get() {
|
||||
try {
|
||||
return DriverStation.getInstance().getEnhancedIO().getDigital(port) == ACTIVE_STATE;
|
||||
} catch (EnhancedIOException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.buttons;
|
||||
|
||||
/**
|
||||
* This class is intended to be used within a program. The programmer can manually set its value.
|
||||
* Also includes a setting for whether or not it should invert its value.
|
||||
*
|
||||
* @author Joe
|
||||
*/
|
||||
public class InternalButton extends Button {
|
||||
|
||||
boolean pressed;
|
||||
boolean inverted;
|
||||
|
||||
/**
|
||||
* Creates an InternalButton that is not inverted.
|
||||
*/
|
||||
public InternalButton() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an InternalButton which is inverted depending on the input.
|
||||
*
|
||||
* @param inverted if false, then this button is pressed when set to true, otherwise it is pressed when set to false.
|
||||
*/
|
||||
public InternalButton(boolean inverted) {
|
||||
this.pressed = this.inverted = inverted;
|
||||
}
|
||||
|
||||
public void setInverted(boolean inverted) {
|
||||
this.inverted = inverted;
|
||||
}
|
||||
|
||||
public void setPressed(boolean pressed) {
|
||||
this.pressed = pressed;
|
||||
}
|
||||
|
||||
public boolean get() {
|
||||
return pressed ^ inverted;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.buttons;
|
||||
|
||||
import edu.wpi.first.wpilibj.GenericHID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author bradmiller
|
||||
*/
|
||||
public class JoystickButton extends Button {
|
||||
|
||||
GenericHID m_joystick;
|
||||
int m_buttonNumber;
|
||||
|
||||
/**
|
||||
* Create a joystick button for triggering commands
|
||||
* @param joystick The GenericHID object that has the button (e.g. Joystick, KinectStick, etc)
|
||||
* @param buttonNumber The button number (see {@link GenericHID#getRawButton(int) }
|
||||
*/
|
||||
public JoystickButton(GenericHID joystick, int buttonNumber) {
|
||||
m_joystick = joystick;
|
||||
m_buttonNumber = buttonNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the joystick button
|
||||
* @return The value of the joystick button
|
||||
*/
|
||||
public boolean get() {
|
||||
return m_joystick.getRawButton(m_buttonNumber);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.buttons;
|
||||
|
||||
import edu.wpi.first.wpilibj.networktables.NetworkTable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joe
|
||||
*/
|
||||
public class NetworkButton extends Button {
|
||||
|
||||
NetworkTable table;
|
||||
String field;
|
||||
|
||||
public NetworkButton(String table, String field) {
|
||||
this(NetworkTable.getTable(table), field);
|
||||
}
|
||||
|
||||
public NetworkButton(NetworkTable table, String field) {
|
||||
this.table = table;
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public boolean get() {
|
||||
return table.isConnected() && table.getBoolean(field, false);
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.buttons;
|
||||
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
import edu.wpi.first.wpilibj.command.Command;
|
||||
import edu.wpi.first.wpilibj.command.Scheduler;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
* This class provides an easy way to link commands to inputs.
|
||||
*
|
||||
* It is very easy to link a button to a command. For instance, you could
|
||||
* link the trigger button of a joystick to a "score" command.
|
||||
*
|
||||
* It is encouraged that teams write a subclass of Trigger if they want to have
|
||||
* something unusual (for instance, if they want to react to the user holding
|
||||
* a button while the robot is reading a certain sensor input). For this, they
|
||||
* only have to write the {@link Trigger#get()} method to get the full functionality
|
||||
* of the Trigger class.
|
||||
*
|
||||
* @author Joe Grinstead
|
||||
*/
|
||||
public abstract class Trigger implements Sendable {
|
||||
|
||||
/**
|
||||
* Returns whether or not the trigger is active
|
||||
*
|
||||
* This method will be called repeatedly a command is linked to the Trigger.
|
||||
*
|
||||
* @return whether or not the trigger condition is active.
|
||||
*/
|
||||
public abstract boolean get();
|
||||
|
||||
/**
|
||||
* Returns whether get() return true or the internal table for SmartDashboard use is pressed.
|
||||
* @return whether get() return true or the internal table for SmartDashboard use is pressed
|
||||
*/
|
||||
private boolean grab() {
|
||||
return get() || (table != null /*&& table.isConnected()*/ && table.getBoolean("pressed", false));//FIXME make is connected work?
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the given command whenever the trigger just becomes active.
|
||||
* @param command the command to start
|
||||
*/
|
||||
public void whenActive(final Command command) {
|
||||
new ButtonScheduler() {
|
||||
|
||||
boolean pressedLast = grab();
|
||||
|
||||
public void execute() {
|
||||
if (grab()) {
|
||||
if (!pressedLast) {
|
||||
pressedLast = true;
|
||||
command.start();
|
||||
}
|
||||
} else {
|
||||
pressedLast = false;
|
||||
}
|
||||
}
|
||||
} .start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constantly starts the given command while the button is held.
|
||||
*
|
||||
* {@link Command#start()} will be called repeatedly while the trigger is active,
|
||||
* and will be canceled when the trigger becomes inactive.
|
||||
*
|
||||
* @param command the command to start
|
||||
*/
|
||||
public void whileActive(final Command command) {
|
||||
new ButtonScheduler() {
|
||||
|
||||
boolean pressedLast = grab();
|
||||
|
||||
public void execute() {
|
||||
if (grab()) {
|
||||
pressedLast = true;
|
||||
command.start();
|
||||
} else {
|
||||
if (pressedLast) {
|
||||
pressedLast = false;
|
||||
command.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
} .start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the command when the trigger becomes inactive
|
||||
* @param command the command to start
|
||||
*/
|
||||
public void whenInactive(final Command command) {
|
||||
new ButtonScheduler() {
|
||||
|
||||
boolean pressedLast = grab();
|
||||
|
||||
public void execute() {
|
||||
if (grab()) {
|
||||
pressedLast = true;
|
||||
} else {
|
||||
if (pressedLast) {
|
||||
pressedLast = false;
|
||||
command.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
} .start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a command when the trigger becomes active
|
||||
* @param command the command to toggle
|
||||
*/
|
||||
public void toggleWhenActive(final Command command) {
|
||||
new ButtonScheduler() {
|
||||
|
||||
boolean pressedLast = grab();
|
||||
|
||||
public void execute() {
|
||||
if (grab()) {
|
||||
if (!pressedLast) {
|
||||
pressedLast = true;
|
||||
if (command.isRunning()) {
|
||||
command.cancel();
|
||||
} else {
|
||||
command.start();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pressedLast = false;
|
||||
}
|
||||
}
|
||||
} .start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a command when the trigger becomes active
|
||||
* @param command the command to cancel
|
||||
*/
|
||||
public void cancelWhenActive(final Command command) {
|
||||
new ButtonScheduler() {
|
||||
|
||||
boolean pressedLast = grab();
|
||||
|
||||
public void execute() {
|
||||
if (grab()) {
|
||||
if (!pressedLast) {
|
||||
pressedLast = true;
|
||||
command.cancel();
|
||||
}
|
||||
} else {
|
||||
pressedLast = false;
|
||||
}
|
||||
}
|
||||
} .start();
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal class of {@link Trigger}. The user should ignore this, it is
|
||||
* only public to interface between packages.
|
||||
*/
|
||||
public abstract class ButtonScheduler {
|
||||
public abstract void execute();
|
||||
|
||||
protected void start() {
|
||||
Scheduler.getInstance().addButton(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* These methods continue to return the "Button" SmartDashboard type until we decided
|
||||
* to create a Trigger widget type for the dashboard.
|
||||
*/
|
||||
public String getSmartDashboardType() {
|
||||
return "Button";
|
||||
}
|
||||
private ITable table;
|
||||
public void initTable(ITable table) {
|
||||
this.table = table;
|
||||
if(table!=null) {
|
||||
table.putBoolean("pressed", get());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return table;
|
||||
}
|
||||
}
|
||||
@@ -1,489 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.camera;
|
||||
|
||||
import com.sun.jna.BlockingFunction;
|
||||
import com.sun.jna.Function;
|
||||
import com.sun.jna.NativeLibrary;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.TaskExecutor;
|
||||
import com.sun.squawk.VM;
|
||||
import edu.wpi.first.wpilibj.DriverStation;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.image.ColorImage;
|
||||
import edu.wpi.first.wpilibj.image.HSLImage;
|
||||
import edu.wpi.first.wpilibj.image.NIVisionException;
|
||||
import edu.wpi.first.wpilibj.parsing.ISensor;
|
||||
import edu.wpi.first.wpilibj.util.BoundaryException;
|
||||
|
||||
//TODO figure out where to use finally to free resources
|
||||
//TODO go through old camera code and make sure all features are implemented
|
||||
//TODO make work with all three passwords
|
||||
//TODO get images of different types
|
||||
//TODO continue attempting to connect until succesful
|
||||
//TODO optimize and use Pointers in all locations which make sense - possibly JNA memcpy?
|
||||
/**
|
||||
* This class is a singleton used to configure and get images from the axis camera.
|
||||
* @author dtjones
|
||||
*/
|
||||
public class AxisCamera implements ISensor {
|
||||
|
||||
private static AxisCamera m_instance = null;
|
||||
|
||||
/**
|
||||
* Enumaration representing the different values which exposure may be set to.
|
||||
*/
|
||||
public static class ExposureT {
|
||||
|
||||
/**
|
||||
* The integer value of the enumeration.
|
||||
*/
|
||||
public final int value;
|
||||
static final ExposureT[] allValues = new ExposureT[4];
|
||||
/**
|
||||
* The Axis camera automatically determines what exposure level to use.
|
||||
*/
|
||||
public static final ExposureT automatic = new ExposureT(0);
|
||||
/**
|
||||
* Hold the current exposure level.
|
||||
*/
|
||||
public static final ExposureT hold = new ExposureT(1);
|
||||
/**
|
||||
* Set exposure for flicker free 50 hz.
|
||||
*/
|
||||
public static final ExposureT flickerfree50 = new ExposureT(2);
|
||||
/**
|
||||
* Set exposure for flicker free 60 hz.
|
||||
*/
|
||||
public static final ExposureT flickerfree60 = new ExposureT(3);
|
||||
|
||||
private ExposureT(int value) {
|
||||
this.value = value;
|
||||
allValues[value] = this;
|
||||
}
|
||||
|
||||
private static ExposureT get(int val) {
|
||||
return allValues[val];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration representing the different values which white balence may be
|
||||
* set to.
|
||||
*/
|
||||
public static class WhiteBalanceT {
|
||||
|
||||
/**
|
||||
* The integer value of the enumeration.
|
||||
*/
|
||||
public final int value;
|
||||
static final WhiteBalanceT[] allValues = new WhiteBalanceT[7];
|
||||
/**
|
||||
* The axis camera automatically adjusts the whit balance.
|
||||
*/
|
||||
public static final WhiteBalanceT automatic = new WhiteBalanceT(0);
|
||||
/**
|
||||
* Hold the current white balance.
|
||||
*/
|
||||
public static final WhiteBalanceT hold = new WhiteBalanceT(1);
|
||||
/**
|
||||
* White balance for outdoors.
|
||||
*/
|
||||
public static final WhiteBalanceT fixedOutdoor1 = new WhiteBalanceT(2);
|
||||
/**
|
||||
* White balance for outdoors.
|
||||
*/
|
||||
public static final WhiteBalanceT fixedOutdoor2 = new WhiteBalanceT(3);
|
||||
/**
|
||||
* White balance for indoors.
|
||||
*/
|
||||
public static final WhiteBalanceT fixedIndoor = new WhiteBalanceT(4);
|
||||
/**
|
||||
* White balance for fourescent lighting.
|
||||
*/
|
||||
public static final WhiteBalanceT fixedFlour1 = new WhiteBalanceT(5);
|
||||
/**
|
||||
* White balance for fourescent lighting.
|
||||
*/
|
||||
public static final WhiteBalanceT fixedFlour2 = new WhiteBalanceT(6);
|
||||
|
||||
private WhiteBalanceT(int value) {
|
||||
this.value = value;
|
||||
allValues[value] = this;
|
||||
}
|
||||
|
||||
private static WhiteBalanceT get(int value) {
|
||||
return allValues[value];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration representing the image resoultion provided by the camera.
|
||||
*/
|
||||
public static class ResolutionT {
|
||||
|
||||
/**
|
||||
* The integer value of the enumeration.
|
||||
*/
|
||||
public final int value;
|
||||
/**
|
||||
* Number of pixels wide.
|
||||
*/
|
||||
public final int width;
|
||||
/**
|
||||
* Number of pixels tall.
|
||||
*/
|
||||
public final int height;
|
||||
static final ResolutionT[] allValues = new ResolutionT[4];
|
||||
/**
|
||||
* Image is 640 pixels wide by 480 tall
|
||||
*/
|
||||
public static final ResolutionT k640x480 = new ResolutionT(0, 640, 480);
|
||||
/**
|
||||
* Image is 640 pixels wide by 360 tall
|
||||
*/
|
||||
public static final ResolutionT k640x360 = new ResolutionT(1, 640, 360);
|
||||
/**
|
||||
* Image is 320 pixels wide by 240 tall
|
||||
*/
|
||||
public static final ResolutionT k320x240 = new ResolutionT(2, 320, 240);
|
||||
/**
|
||||
* Image is 160 pixels wide by 120 tall
|
||||
*/
|
||||
public static final ResolutionT k160x120 = new ResolutionT(3, 160, 120);
|
||||
|
||||
private ResolutionT(int value, int horizontal, int vertical) {
|
||||
this.value = value;
|
||||
this.width = horizontal;
|
||||
this.height = vertical;
|
||||
allValues[value] = this;
|
||||
}
|
||||
|
||||
private static ResolutionT get(int value) {
|
||||
return allValues[value];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration representing the orientation of the picture.
|
||||
*/
|
||||
public static class RotationT {
|
||||
|
||||
/**
|
||||
* The integer value of the enumeration.
|
||||
*/
|
||||
public final int value;
|
||||
static final RotationT[] allValues = new RotationT[2];
|
||||
/**
|
||||
* Picture is right side up.
|
||||
*/
|
||||
public static final RotationT k0 = new RotationT(0);
|
||||
/**
|
||||
* Picture is rotated 180 degrees.
|
||||
*/
|
||||
public static final RotationT k180 = new RotationT(1);
|
||||
|
||||
private RotationT(int value) {
|
||||
this.value = value;
|
||||
allValues[value] = this;
|
||||
}
|
||||
|
||||
private static RotationT get(int value) {
|
||||
return allValues[value];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration representing the exposure priority.
|
||||
*/
|
||||
public static class ExposurePriorityT {
|
||||
|
||||
/**
|
||||
* The integer value of the enumeration.
|
||||
*/
|
||||
public final int value;
|
||||
static final ExposurePriorityT[] allValues = new ExposurePriorityT[3];
|
||||
/**
|
||||
* Prioritize image quality.
|
||||
*/
|
||||
public static final ExposurePriorityT imageQuality = new ExposurePriorityT(0);
|
||||
/**
|
||||
* No prioritization.
|
||||
*/
|
||||
public static final ExposurePriorityT none = new ExposurePriorityT(50);
|
||||
/**
|
||||
* Prioritize frame rate.
|
||||
*/
|
||||
public static final ExposurePriorityT frameRate = new ExposurePriorityT(100);
|
||||
|
||||
private ExposurePriorityT(int value) {
|
||||
this.value = value;
|
||||
allValues[value / 50] = this;
|
||||
}
|
||||
|
||||
private static ExposurePriorityT get(int value) {
|
||||
return allValues[value / 50];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the AxisCamera, or initialize the AxisCamera if it
|
||||
* has not yet been initialized. If the camera is connected to the
|
||||
* Ethernet switch on the robot, then this address should be 10.x.y.11
|
||||
* where x.y are your team number subnet address (same as the other IP
|
||||
* addresses on the robot network).
|
||||
* @param address A string containing the IP address for the camera in the
|
||||
* form "10.x.y.2" for cameras on the Ethernet switch or "192.168.0.90"
|
||||
* for cameras connected to the 2nd Ethernet port on an 8-slot cRIO.
|
||||
* @return A reference to the AxisCamera.
|
||||
*/
|
||||
public static synchronized AxisCamera getInstance(String address) {
|
||||
if (m_instance == null) {
|
||||
m_instance = new AxisCamera(address);
|
||||
// XXX: Resource Reporting Fixes
|
||||
// UsageReporting.report(UsageReporting.kResourceType_AxisCamera, 2);
|
||||
}
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the AxisCamera, or initialize the AxisCamera if it
|
||||
* has not yet been initialized. By default this will connect to a camera
|
||||
* with an IP address of 10.x.y.11 with the preference that the camera be
|
||||
* connected to the Ethernet switch on the robot rather than port 2 of the
|
||||
* 8-slot cRIO.
|
||||
* @return A reference to the AxisCamera.
|
||||
*/
|
||||
public static synchronized AxisCamera getInstance() {
|
||||
if (m_instance == null) {
|
||||
DriverStation.getInstance().waitForData();
|
||||
int teamNumber = DriverStation.getInstance().getTeamNumber();
|
||||
String address = "10."+(teamNumber/100)+"."+(teamNumber%100)+".11";
|
||||
m_instance = new AxisCamera(address);
|
||||
UsageReporting.report(UsageReporting.kResourceType_AxisCamera, 1);
|
||||
}
|
||||
|
||||
return m_instance;
|
||||
}
|
||||
private static final Function cameraStartFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraStart");
|
||||
|
||||
/**
|
||||
* Axis camera constructor that calls the C++ library to actually create the instance.
|
||||
* @param IPAddress
|
||||
*/
|
||||
AxisCamera(String IPAddress) {
|
||||
Pointer ptr = Pointer.createStringBuffer(IPAddress);
|
||||
cameraStartFn.call1(ptr);
|
||||
}
|
||||
private static final TaskExecutor cameraTaskExecutor = new TaskExecutor("camera task executor");
|
||||
private static final BlockingFunction getImageFn = NativeLibrary.getDefaultInstance().getBlockingFunction("AxisCameraGetImage");
|
||||
|
||||
static {
|
||||
getImageFn.setTaskExecutor(cameraTaskExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an image from the camera. Be sure to free the image when you are done with it.
|
||||
* @return A new image from the camera.
|
||||
*/
|
||||
public ColorImage getImage() throws AxisCameraException, NIVisionException {
|
||||
ColorImage image = new HSLImage();
|
||||
if (getImageFn.call1(image.image) == 0) {
|
||||
image.free();
|
||||
throw new AxisCameraException("No image available");
|
||||
}
|
||||
return image;
|
||||
}
|
||||
// Mid-stream gets & writes
|
||||
private static final Function writeBrightnessFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraWriteBrightness");
|
||||
|
||||
/**
|
||||
* Write the brightness for the camera to use.
|
||||
* @param brightness This must be an integer between 0 and 100, with 100 being the brightest
|
||||
*/
|
||||
public void writeBrightness(int brightness) {
|
||||
BoundaryException.assertWithinBounds(brightness, 0, 100);
|
||||
writeBrightnessFn.call1(brightness);
|
||||
}
|
||||
private static final Function getBrightnessFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraGetBrightness");
|
||||
|
||||
/**
|
||||
* Get the current brightness of the AxisCamera
|
||||
* @return An integer representing the current brightness of the axis
|
||||
* camera with 0 being the darkest and 100 being the brightest.
|
||||
*/
|
||||
public int getBrightness() {
|
||||
return getBrightnessFn.call0();
|
||||
}
|
||||
private static final Function writeWhiteBalenceFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraWriteWhiteBalance");
|
||||
|
||||
/**
|
||||
* Write the WhiteBalance for the camera to use.
|
||||
* @param whiteBalance The value to set the white balance to on the camera.
|
||||
*/
|
||||
public void writeWhiteBalance(WhiteBalanceT whiteBalance) {
|
||||
writeWhiteBalenceFn.call1(whiteBalance.value);
|
||||
}
|
||||
private static final Function getWhiteBalanceFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraGetWhiteBalance");
|
||||
|
||||
/**
|
||||
* Get the white balance set on the camera.
|
||||
* @return The white balance currently set on the camera.
|
||||
*/
|
||||
public WhiteBalanceT getWhiteBalance() {
|
||||
return WhiteBalanceT.get(getWhiteBalanceFn.call0());
|
||||
}
|
||||
private static final Function writeColorLevelFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraWriteColorLevel");
|
||||
|
||||
/**
|
||||
* Set the color level of images returned from the camera.
|
||||
* @param value This must be an integer from 0 to 100 with 0 being black and white.
|
||||
*/
|
||||
public void writeColorLevel(int value) {
|
||||
BoundaryException.assertWithinBounds(value, 0, 100);
|
||||
writeColorLevelFn.call1(value);
|
||||
}
|
||||
private static final Function getColorLevelFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraGetColorLevel");
|
||||
|
||||
/**
|
||||
* Get the color level of images being retunred from the camera.
|
||||
* @return The color level of images being returned from the camera. 0 is black and white.
|
||||
*/
|
||||
public int getColorLevel() {
|
||||
return getColorLevelFn.call0();
|
||||
}
|
||||
private static final Function writeExposureControlFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraWriteExposureControl");
|
||||
|
||||
/**
|
||||
* Write the exposure mode for the camera to use.
|
||||
* @param value The expsure mode for the camera to use.
|
||||
*/
|
||||
public void writeExposureControl(ExposureT value) {
|
||||
writeExposureControlFn.call1(value.value);
|
||||
}
|
||||
private static final Function getExposureControlFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraGetExposureControl");
|
||||
|
||||
/**
|
||||
* Get the exposure mode that the camera is using.
|
||||
* @return The exposure mode that the camera is using.
|
||||
*/
|
||||
public ExposureT getExposureControl() {
|
||||
return ExposureT.get(getExposureControlFn.call0());
|
||||
}
|
||||
private static final Function writeExposurePriorityFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraWriteExposurePriority");
|
||||
|
||||
/**
|
||||
* Write the exposure priority for the camera to use.
|
||||
* @param value The exposure priority to use.
|
||||
*/
|
||||
public void writeExposurePriority(ExposurePriorityT value) {
|
||||
writeExposurePriorityFn.call1(value.value);
|
||||
}
|
||||
private static final Function getExposurePriorityFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraGetExposurePriority");
|
||||
|
||||
/**
|
||||
* Get the exposure priority that the camera is using.
|
||||
* @return The exposure priority that the camera is using
|
||||
*/
|
||||
public ExposurePriorityT getExposurePriority() {
|
||||
return ExposurePriorityT.get(getExposurePriorityFn.call0());
|
||||
}
|
||||
// New-Stream gets & writes
|
||||
private static final Function writeResolutionFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraWriteResolution");
|
||||
|
||||
/**
|
||||
* Set the resolution of the images to return.
|
||||
* @param value The resolution imaga for the camera to return.
|
||||
*/
|
||||
public void writeResolution(ResolutionT value) {
|
||||
writeResolutionFn.call1(value.value);
|
||||
}
|
||||
private static final Function getResolutionFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraGetResolution");
|
||||
|
||||
/**
|
||||
* Get the resolution fo the images that the camera is returning.
|
||||
* @return The resolution of the images that the camera is returning.
|
||||
*/
|
||||
public ResolutionT getResolution() {
|
||||
return ResolutionT.get(getResolutionFn.call0());
|
||||
}
|
||||
private static final Function writeCompressionFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraWriteCompression");
|
||||
|
||||
/**
|
||||
* Write the level of JPEG compression to use on images returned from the camera.
|
||||
* @param value The level of JPEG compression to use from 0 to 100 with 0 being the least compression.
|
||||
*/
|
||||
public void writeCompression(int value) {
|
||||
BoundaryException.assertWithinBounds(value, 0, 100);
|
||||
writeCompressionFn.call1(value);
|
||||
}
|
||||
private static final Function getCompressionFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraGetCompression");
|
||||
|
||||
/**
|
||||
* Get the compression of the images eing returned by the camera.
|
||||
* @return The level of compression of the image being returned from the
|
||||
* camera with 0 being the least and 100 being the greatest.
|
||||
*/
|
||||
public int getCompression() {
|
||||
return getCompressionFn.call0();
|
||||
}
|
||||
private static final Function writeRotationFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraWriteRotation");
|
||||
|
||||
/**
|
||||
* Write the rotation of images for the camera to return.
|
||||
* @param value The rotation to be applied to images from the camera.
|
||||
*/
|
||||
public void writeRotation(RotationT value) {
|
||||
writeRotationFn.call1(value.value);
|
||||
}
|
||||
private static final Function getRotationFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraGetRotation");
|
||||
|
||||
/**
|
||||
* Get the rotation of the images returned from the camera.
|
||||
* @return The rotation of the images returned from the camera.
|
||||
*/
|
||||
public RotationT getRotation() {
|
||||
return RotationT.get(getRotationFn.call0());
|
||||
}
|
||||
private static final Function freshImageFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraFreshImage");
|
||||
|
||||
/**
|
||||
* Has the current image from the camera been retrieved yet.
|
||||
* @return true if the latest image from the camera has not been retrieved yet.
|
||||
*/
|
||||
public boolean freshImage() {
|
||||
return freshImageFn.call0() == 0 ? false : true;
|
||||
}
|
||||
private static final Function getMaxFPSFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraGetMaxFPS");
|
||||
|
||||
/**
|
||||
* Get the maximum frames per second that the camera will generate.
|
||||
* @return the max fps.
|
||||
*/
|
||||
public int getMaxFPS() {
|
||||
return getMaxFPSFn.call0();
|
||||
}
|
||||
private static final Function writeMaxFPSFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraWriteMaxFPS");
|
||||
|
||||
/**
|
||||
* Set the maximum frames per second that the camera will generate.
|
||||
* @param value the new max fps
|
||||
*/
|
||||
public void writeMaxFPS(int value) {
|
||||
writeMaxFPSFn.call1(value);
|
||||
}
|
||||
private static final Function deleteInstanceFn = NativeLibrary.getDefaultInstance().getFunction("AxisCameraDeleteInstance");
|
||||
|
||||
static {
|
||||
VM.addShutdownHook(new Thread() {
|
||||
|
||||
public void run() {
|
||||
deleteInstanceFn.call0();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.camera;
|
||||
|
||||
/**
|
||||
* An exception representing a problem with communicating with the camera.
|
||||
* @author dtjones
|
||||
*/
|
||||
public class AxisCameraException extends Exception {
|
||||
/**
|
||||
* Create a new AxisCameraException.
|
||||
* @param msg The message to pass with the AxisCameraException.
|
||||
*/
|
||||
public AxisCameraException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>FRC Camera Library</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=MacRoman">
|
||||
</head>
|
||||
<body>
|
||||
Provides classes for interfacing to the camera.
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,48 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.can;
|
||||
|
||||
import edu.wpi.first.wpilibj.communication.NIRioStatus;
|
||||
import edu.wpi.first.wpilibj.util.UncleanStatusException;
|
||||
|
||||
/**
|
||||
* Exception indicating that the Jaguar CAN Driver layer refused to send a
|
||||
* restricted message ID to the CAN bus.
|
||||
*/
|
||||
public class CANExceptionFactory {
|
||||
// FRC Error codes
|
||||
static final int ERR_JaguarCANDriver_InvalidBuffer = -44086;
|
||||
static final int ERR_JaguarCANDriver_TimedOut = -44087;
|
||||
static final int ERR_JaguarCANDriver_NotAllowed = -44088;
|
||||
static final int ERR_JaguarCANDriver_NotInitialized = -44089;
|
||||
|
||||
public static void checkStatus(int status, int messageID) throws
|
||||
CANInvalidBufferException, CANTimeoutException,
|
||||
CANMessageNotAllowedException, CANNotInitializedException,
|
||||
UncleanStatusException {
|
||||
switch (status) {
|
||||
case NIRioStatus.kRioStatusSuccess:
|
||||
// Everything is ok... don't throw.
|
||||
return;
|
||||
case ERR_JaguarCANDriver_InvalidBuffer:
|
||||
case NIRioStatus.kRIOStatusBufferInvalidSize:
|
||||
throw new CANInvalidBufferException();
|
||||
case ERR_JaguarCANDriver_TimedOut:
|
||||
case NIRioStatus.kRIOStatusOperationTimedOut:
|
||||
throw new CANTimeoutException();
|
||||
case ERR_JaguarCANDriver_NotAllowed:
|
||||
case NIRioStatus.kRIOStatusFeatureNotSupported:
|
||||
throw new CANMessageNotAllowedException("MessageID = " + Integer.toString(messageID));
|
||||
case ERR_JaguarCANDriver_NotInitialized:
|
||||
case NIRioStatus.kRIOStatusResourceNotInitialized:
|
||||
throw new CANNotInitializedException();
|
||||
default:
|
||||
throw new UncleanStatusException("Fatal status code detected: " + Integer.toString(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.can;
|
||||
|
||||
/**
|
||||
* Exception indicating that a CAN driver library entry-point
|
||||
* was passed an invalid buffer. Typically, this is due to a
|
||||
* buffer being too small to include the needed safety token.
|
||||
*/
|
||||
public class CANInvalidBufferException extends RuntimeException {
|
||||
public CANInvalidBufferException() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.can;
|
||||
|
||||
/**
|
||||
* Exception indicating that the CAN driver layer has not been initialized.
|
||||
* This happens when an entry-point is called before a CAN driver plugin
|
||||
* has been installed.
|
||||
*/
|
||||
public class CANJaguarVersionException extends RuntimeException {
|
||||
|
||||
public static final int kMinLegalFIRSTFirmwareVersion = 101;
|
||||
// 3330 was the first shipping RDK firmware version for the Jaguar
|
||||
public static final int kMinRDKFirmwareVersion = 3330;
|
||||
|
||||
public CANJaguarVersionException(int deviceNumber, int fwVersion) {
|
||||
super(getString(deviceNumber, fwVersion));
|
||||
System.out.println("fwVersion[" + deviceNumber + "]: " + fwVersion);
|
||||
}
|
||||
|
||||
static String getString(int deviceNumber, int fwVersion) {
|
||||
String msg;
|
||||
if (fwVersion < kMinRDKFirmwareVersion) {
|
||||
msg = "Jaguar " + deviceNumber +
|
||||
" firmware is too old. It must be updated to at least version " +
|
||||
Integer.toString(kMinLegalFIRSTFirmwareVersion) +
|
||||
" of the FIRST approved firmware!";
|
||||
} else {
|
||||
msg = "Jaguar " + deviceNumber +
|
||||
" firmware is not FIRST approved. It must be updated to at least version " +
|
||||
Integer.toString(kMinLegalFIRSTFirmwareVersion) +
|
||||
" of the FIRST approved firmware!";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
@@ -1,477 +0,0 @@
|
||||
package edu.wpi.first.wpilibj.can;
|
||||
import com.ochafik.lang.jnaerator.runtime.LibraryExtractor;
|
||||
import com.ochafik.lang.jnaerator.runtime.MangledFunctionMapper;
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.NativeLibrary;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
/**
|
||||
* JNA Wrapper for library <b>CAN</b><br>
|
||||
* This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br>
|
||||
* a tool written by <a href="http://ochafik.com/">Olivier Chafik</a> that <a href="http://code.google.com/p/jnaerator/wiki/CreditsAndLicense">uses a few opensource projects.</a>.<br>
|
||||
* For help, please visit <a href="http://nativelibs4java.googlecode.com/">NativeLibs4Java</a> , <a href="http://rococoa.dev.java.net/">Rococoa</a>, or <a href="http://jna.dev.java.net/">JNA</a>.
|
||||
*/
|
||||
public class CANLibrary implements Library {
|
||||
public static final String JNA_LIBRARY_NAME = LibraryExtractor.getLibraryPath("FRC_NetworkCommunication", true, CANLibrary.class);
|
||||
public static final NativeLibrary JNA_NATIVE_LIB = NativeLibrary.getInstance(CANLibrary.JNA_LIBRARY_NAME, MangledFunctionMapper.DEFAULT_OPTIONS);
|
||||
static {
|
||||
Native.register(CANLibrary.JNA_LIBRARY_NAME);
|
||||
}
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_LIMIT_REV = 0x02;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG_MAX_VOUT = ((0x00020000 | 0x02000000 | 0x00001c00) | (7 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_CANERR_B0 = 30;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_DIS = ((0x00020000 | 0x02000000 | 0x00000400) | (1 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_ACCEL = 0x05000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_FAULT = ((0x00020000 | 0x02000000 | 0x00001400) | (7 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_FIRMVER = 0x00000200;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_EN = ((0x00020000 | 0x02000000 | 0x00001000) | (0 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_ENUMERATE = 0x00000240;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_EN = ((0x00020000 | 0x02000000 | 0x00000400) | (0 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG_LIMIT_REV = ((0x00020000 | 0x02000000 | 0x00001c00) | (6 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_POS_B2 = 11;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_POS_B3 = 12;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP_EN = ((0x00020000 | 0x02000000 | 0x00000800) | (0 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_POS_B0 = 9;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_POS_B1 = 10;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_HWVER = ((0x00020000 | 0x1f000000) | (5 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_FAULT_ILIMIT = 0x01;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_DC = ((0x00020000 | 0x02000000 | 0x00001000) | (5 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT = (0x00020000 | 0x02000000 | 0x00000000);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_API_MC_VCOMP = 0x00000800;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_END = 0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG_LIMIT_FWD = ((0x00020000 | 0x02000000 | 0x00001c00) | (5 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_M = 0x1f000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_API_MC_ICTRL = 0x00001000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_API_MC_CFG = 0x00001c00;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_MFR_DEKA = 0x00030000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_SYSRST = 0x00000040;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_REF_QUAD_ENCODER = 0x03;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SYNC_PEND_NOW = 0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_CMODE_CURRENT = 0x01;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_TEMP = ((0x00020000 | 0x02000000 | 0x00001400) | (3 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_DC = ((0x00020000 | 0x02000000 | 0x00000400) | (5 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_API_MC_POS = 0x00000c00;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_LIMIT_SFWD = 0x04;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_DIS = ((0x00020000 | 0x02000000 | 0x00001000) | (1 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT_SET = ((0x00020000 | 0x02000000 | 0x00000000) | (2 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_HEARTBEAT = 0x00000140;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_FAULT_CURRENT = 0x01;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_GYRO = 0x04000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_FAULT_TLIMIT = 0x02;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_MFR_S = 16;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_T_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00000400) | (10 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_MFR_M = 0x00ff0000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_CMODE_POS = 0x03;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_REF_POT = 0x01;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_HWVER_UNKNOWN = 0x00;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG_BRAKE_COAST = ((0x00020000 | 0x02000000 | 0x00001c00) | (3 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_HWVER_JAG_1_0 = 0x01;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DEVNO_BCAST = 0x00000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT_T_SET = ((0x00020000 | 0x02000000 | 0x00000000) | (5 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_LIMIT_STKY_SREV = 0x80;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_IC = ((0x00020000 | 0x02000000 | 0x00001000) | (4 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_T_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00001000) | (9 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_FAULT_COMM = 0x10;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_SPD_B2 = 15;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_SPD_B1 = 14;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_STKY_FLT_CLR = 21;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_SPD_B3 = 16;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00000400) | (11 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_STATUS_MFG_S = 16;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_LIMIT = ((0x00020000 | 0x02000000 | 0x00001400) | (6 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT_EN = ((0x00020000 | 0x02000000 | 0x00000000) | (0 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT_RAMP_DIS = 0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_TEMP_B0 = 7;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_TEMP_B1 = 8;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_IC = ((0x00020000 | 0x02000000 | 0x00000c00) | (4 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_MOTOR = 0x02000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_T_EN = ((0x00020000 | 0x02000000 | 0x00000400) | (7 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DEVNO_M = 0x0000003f;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_VOLTBUS_B1 = 4;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_UPD_PING = ((0x00020000 | 0x1f000000) | (0 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_T_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00000c00) | (10 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DEVNO_S = 0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_TRUST_HEARTBEAT = ((0x00020000 | 0x1f000000) | (13 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_VOLTBUS_B0 = 3;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_SPD_B0 = 13;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG = (0x00020000 | 0x02000000 | 0x00001c00);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_FLT_COUNT_COMM = 28;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_SYSHALT = 0x00000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_UPD_DOWNLOAD = ((0x00020000 | 0x1f000000) | (1 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_CMODE = ((0x00020000 | 0x02000000 | 0x00001400) | (9 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP_IN_RAMP = ((0x00020000 | 0x02000000 | 0x00000800) | (3 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_FAULT_VLIMIT = 0x04;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_LIMIT_SREV = 0x08;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_S = 24;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_FLT_COUNT_VOLTBUS = 26;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_API_MC_STATUS = 0x00001400;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT_T_EN = ((0x00020000 | 0x02000000 | 0x00000000) | (4 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_VOLTBUS = ((0x00020000 | 0x02000000 | 0x00001400) | (1 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_UPD = (0x00020000 | 0x1f000000);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_UPD_REQUEST = ((0x00020000 | 0x1f000000) | (6 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_API_MC_VOLTAGE = 0x00000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_PER_EN_S3 = ((0x00020000 | 0x02000000 | 0x00001800) | (3 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_PER_EN_S2 = ((0x00020000 | 0x02000000 | 0x00001800) | (2 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_API_MC_PSTAT = 0x00001800;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_CANERR_B1 = 31;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_PER_EN_S1 = ((0x00020000 | 0x02000000 | 0x00001800) | (1 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_REF_ENCODER = 0x00;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_PER_EN_S0 = ((0x00020000 | 0x02000000 | 0x00001800) | (0 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_CURRENT = ((0x00020000 | 0x02000000 | 0x00001400) | (2 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_SET = ((0x00020000 | 0x02000000 | 0x00000c00) | (2 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_LIMIT_STKY_FWD = 0x10;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL = (0x00020000 | 0x02000000 | 0x00001000);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_HWVER_JAG_2_0 = 0x02;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_STATUS_MFG_M = 0x00ff0000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_LIMIT_CLR = 18;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG_POT_TURNS = ((0x00020000 | 0x02000000 | 0x00001c00) | (2 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_REF = ((0x00020000 | 0x02000000 | 0x00000c00) | (6 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_PC = ((0x00020000 | 0x02000000 | 0x00000400) | (3 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_VOUT = ((0x00020000 | 0x02000000 | 0x00001400) | (10 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_SYSRESUME = 0x00000280;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_UNTRUST_EN = ((0x00020000 | 0x1f000000) | (11 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_CANSTS = 29;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_DC = ((0x00020000 | 0x02000000 | 0x00000c00) | (5 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_POS = ((0x00020000 | 0x02000000 | 0x00001400) | (4 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_SET = ((0x00020000 | 0x02000000 | 0x00000400) | (2 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_FULL_M = 0x1fffffff;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_SPD = ((0x00020000 | 0x02000000 | 0x00001400) | (5 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_STKY_FLT_NCLR = 20;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS = (0x00020000 | 0x02000000 | 0x00001400);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_TRUST_EN = ((0x00020000 | 0x1f000000) | (12 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_T_SET = ((0x00020000 | 0x02000000 | 0x00001000) | (7 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_STATUS_CODE_M = 0x0000ffff;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_STATUS_CODE_S = 0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_T_EN = ((0x00020000 | 0x02000000 | 0x00000c00) | (7 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT = (0x00020000 | 0x02000000 | 0x00001800);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_FAULT = 19;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_FLT_COUNT_GATE = 27;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_T_EN = ((0x00020000 | 0x02000000 | 0x00001000) | (6 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_DEVQUERY = 0x000000c0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_USONIC = 0x06000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_CMODE_VCOMP = 0x04;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_T_SET = ((0x00020000 | 0x02000000 | 0x00000400) | (8 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_EN = ((0x00020000 | 0x02000000 | 0x00000c00) | (0 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT_DIS = ((0x00020000 | 0x02000000 | 0x00000000) | (1 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_LIMIT_FWD = 0x01;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP_DIS = ((0x00020000 | 0x02000000 | 0x00000800) | (1 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_REF_INV_ENCODER = 0x02;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG_NUM_BRUSHES = ((0x00020000 | 0x02000000 | 0x00001c00) | (0 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_RELAY = 0x03000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_DEVASSIGN = 0x00000080;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT_T_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00000000) | (7 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_API_MC_SPD = 0x00000400;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG_ENC_LINES = ((0x00020000 | 0x02000000 | 0x00001c00) | (1 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_REF_NONE = 0xff;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_FAULT_VBUS = 0x04;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT_SET_RAMP = ((0x00020000 | 0x02000000 | 0x00000000) | (3 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_REF = ((0x00020000 | 0x02000000 | 0x00000400) | (6 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_POWER = ((0x00020000 | 0x02000000 | 0x00001400) | (8 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_VOLTOUT_B1 = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00000800) | (9 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_VOLTOUT_B0 = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG_LIMIT_MODE = ((0x00020000 | 0x02000000 | 0x00001c00) | (4 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_VOUT_B1 = 23;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_UPD_SEND_DATA = ((0x00020000 | 0x1f000000) | (2 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_FLT_COUNT_CURRENT = 24;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_VOUT_B0 = 22;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_CFG_S0 = ((0x00020000 | 0x02000000 | 0x00001800) | (4 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_LIMIT_NCLR = 17;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_CFG_S1 = ((0x00020000 | 0x02000000 | 0x00001800) | (5 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_CFG_S2 = ((0x00020000 | 0x02000000 | 0x00001800) | (6 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_CFG_S3 = ((0x00020000 | 0x02000000 | 0x00001800) | (7 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP_SET = ((0x00020000 | 0x02000000 | 0x00000800) | (2 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_UPDATE = 0x000001c0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_CFG_FAULT_TIME = ((0x00020000 | 0x02000000 | 0x00001c00) | (8 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_VOLTOUT = ((0x00020000 | 0x02000000 | 0x00001400) | (0 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_SET = ((0x00020000 | 0x02000000 | 0x00001000) | (2 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_M = 0x0000ffc0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_CMODE_SPEED = 0x02;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_CLASS_M = 0x0000fc00;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_DATA_S3 = ((0x00020000 | 0x02000000 | 0x00001800) | (11 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_S = 6;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_FLT_COUNT = ((0x00020000 | 0x02000000 | 0x00001400) | (12 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_DATA_S2 = ((0x00020000 | 0x02000000 | 0x00001800) | (10 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_DATA_S1 = ((0x00020000 | 0x02000000 | 0x00001800) | (9 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_PSTAT_DATA_S0 = ((0x00020000 | 0x02000000 | 0x00001800) | (8 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_PC = ((0x00020000 | 0x02000000 | 0x00001000) | (3 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_PC = ((0x00020000 | 0x02000000 | 0x00000c00) | (3 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_MFR_LM = 0x00020000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_DIS = ((0x00020000 | 0x02000000 | 0x00000c00) | (1 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_BCAST = 0x00000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_CMODE_VOLT = 0x00;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_STATUS_DTYPE_S = 24;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00000c00) | (11 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_STATUS_DTYPE_M = 0x1f000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_FAULT_GATE_DRIVE = 0x08;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_LIMIT_STKY_REV = 0x20;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_ROBOT = 0x01000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP = (0x00020000 | 0x02000000 | 0x00000800);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_API_MC_ACK = 0x00002000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_UPD_ACK = ((0x00020000 | 0x1f000000) | (4 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP_COMP_RAMP = ((0x00020000 | 0x02000000 | 0x00000800) | (4 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP_T_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00000800) | (8 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS = (0x00020000 | 0x02000000 | 0x00000c00);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_SYNC = 0x00000180;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ICTRL_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00001000) | (10 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_CURRENT_B1 = 6;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD = (0x00020000 | 0x02000000 | 0x00000400);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_CURRENT_B0 = 5;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_UPDATE = 0x1f000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_SPD_IC = ((0x00020000 | 0x02000000 | 0x00000400) | (4 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_ACK = (0x00020000 | 0x02000000 | 0x00002000);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP_T_SET = ((0x00020000 | 0x02000000 | 0x00000800) | (6 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_FAULT_TEMP = 0x02;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_PSTAT_FLT_COUNT_TEMP = 25;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VOLT_SET_NO_ACK = ((0x00020000 | 0x02000000 | 0x00000000) | (8 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_DTYPE_GEART = 0x07000000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_MFR_NI = 0x00010000;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_POS_T_SET = ((0x00020000 | 0x02000000 | 0x00000c00) | (8 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_STATUS_STKY_FLT = ((0x00020000 | 0x02000000 | 0x00001400) | (11 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_UPD_RESET = ((0x00020000 | 0x1f000000) | (3 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int CAN_MSGID_API_ID_M = 0x000003c0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_API_VCOMP_T_EN = ((0x00020000 | 0x02000000 | 0x00000800) | (5 << 6));
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/can_proto.h</i> */
|
||||
public static final int LM_STATUS_LIMIT_STKY_SFWD = 0x40;
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_JaguarCANDriver_sendMessage(uint32_t, const uint8_t*, uint8_t, int32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/JaguarCANDriver.h:7</i><br>
|
||||
* @deprecated use the safer methods {@link #FRC_NetworkCommunication_JaguarCANDriver_sendMessage(int, byte[], byte, java.nio.IntBuffer)} and {@link #FRC_NetworkCommunication_JaguarCANDriver_sendMessage(int, com.sun.jna.Pointer, byte, com.sun.jna.ptr.IntByReference)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native void FRC_NetworkCommunication_JaguarCANDriver_sendMessage(int messageID, Pointer data, byte dataSize, IntByReference status);
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_JaguarCANDriver_sendMessage(uint32_t, const uint8_t*, uint8_t, int32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/JaguarCANDriver.h:7</i>
|
||||
*/
|
||||
public static native void FRC_NetworkCommunication_JaguarCANDriver_sendMessage(int messageID, byte data[], byte dataSize, IntBuffer status);
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(uint32_t*, uint8_t*, uint8_t*, uint32_t, int32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/JaguarCANDriver.h:8</i><br>
|
||||
* @deprecated use the safer methods {@link #FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(java.nio.IntBuffer, java.nio.ByteBuffer, java.nio.ByteBuffer, int, java.nio.IntBuffer)} and {@link #FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(com.sun.jna.ptr.IntByReference, com.sun.jna.Pointer, com.sun.jna.Pointer, int, com.sun.jna.ptr.IntByReference)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native void FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(IntByReference messageID, Pointer data, Pointer dataSize, int timeoutMs, IntByReference status);
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(uint32_t*, uint8_t*, uint8_t*, uint32_t, int32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/CAN/JaguarCANDriver.h:8</i>
|
||||
*/
|
||||
public static native void FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(IntBuffer messageID, ByteBuffer data, ByteBuffer dataSize, int timeoutMs, IntBuffer status);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.can;
|
||||
|
||||
/**
|
||||
* Exception indicating that the Jaguar CAN Driver layer refused to send a
|
||||
* restricted message ID to the CAN bus.
|
||||
*/
|
||||
public class CANMessageNotAllowedException extends RuntimeException {
|
||||
public CANMessageNotAllowedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.can;
|
||||
|
||||
/**
|
||||
* Exception indicating that the CAN driver layer has not been initialized.
|
||||
* This happens when an entry-point is called before a CAN driver plugin
|
||||
* has been installed.
|
||||
*/
|
||||
public class CANNotInitializedException extends RuntimeException {
|
||||
public CANNotInitializedException() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.can;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Exception indicating that the CAN device did not respond
|
||||
* within the timeout period specified.
|
||||
*/
|
||||
public class CANTimeoutException extends IOException {
|
||||
public CANTimeoutException() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -1,523 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
import edu.wpi.first.wpilibj.DriverStation;
|
||||
import edu.wpi.first.wpilibj.NamedSendable;
|
||||
import edu.wpi.first.wpilibj.Timer;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import edu.wpi.first.wpilibj.tables.ITableListener;
|
||||
import java.util.Enumeration;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* The Command class is at the very core of the entire command framework.
|
||||
* Every command can be started with a call to {@link Command#start() start()}.
|
||||
* Once a command is started it will call {@link Command#initialize() initialize()}, and then
|
||||
* will repeatedly call {@link Command#execute() execute()} until the {@link Command#isFinished() isFinished()}
|
||||
* returns true. Once it does, {@link Command#end() end()} will be called.
|
||||
*
|
||||
* <p>However, if at any point while it is running {@link Command#cancel() cancel()} is called, then
|
||||
* the command will be stopped and {@link Command#interrupted() interrupted()} will be called.</p>
|
||||
*
|
||||
* <p>If a command uses a {@link Subsystem}, then it should specify that it does so by
|
||||
* calling the {@link Command#requires(Subsystem) requires(...)} method
|
||||
* in its constructor. Note that a Command may have multiple requirements, and
|
||||
* {@link Command#requires(Subsystem) requires(...)} should be
|
||||
* called for each one.</p>
|
||||
*
|
||||
* <p>If a command is running and a new command with shared requirements is started,
|
||||
* then one of two things will happen. If the active command is interruptible,
|
||||
* then {@link Command#cancel() cancel()} will be called and the command will be removed
|
||||
* to make way for the new one. If the active command is not interruptible, the
|
||||
* other one will not even be started, and the active one will continue functioning.</p>
|
||||
*
|
||||
* @author Brad Miller
|
||||
* @author Joe Grinstead
|
||||
* @see Subsystem
|
||||
* @see CommandGroup
|
||||
* @see IllegalUseOfCommandException
|
||||
*/
|
||||
public abstract class Command implements NamedSendable {
|
||||
|
||||
/** The name of this command */
|
||||
private String m_name;
|
||||
/** The time since this command was initialized */
|
||||
private double m_startTime = -1;
|
||||
/** The time (in seconds) before this command "times out" (or -1 if no timeout) */
|
||||
private double m_timeout = -1;
|
||||
/** Whether or not this command has been initialized */
|
||||
private boolean m_initialized = false;
|
||||
/** The requirements (or null if no requirements) */
|
||||
private Set m_requirements;
|
||||
/** Whether or not it is running */
|
||||
private boolean m_running = false;
|
||||
/** Whether or not it is interruptible*/
|
||||
private boolean m_interruptible = true;
|
||||
/** Whether or not it has been canceled */
|
||||
private boolean m_canceled = false;
|
||||
/** Whether or not it has been locked */
|
||||
private boolean m_locked = false;
|
||||
/** Whether this command should run when the robot is disabled */
|
||||
private boolean m_runWhenDisabled = false;
|
||||
/** The {@link CommandGroup} this is in */
|
||||
private CommandGroup m_parent;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new command with the given name.
|
||||
* @param name the name for this command
|
||||
* @throws IllegalArgumentException if name is null
|
||||
*/
|
||||
public Command(String name) {
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Name must not be null.");
|
||||
}
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new command with the given timeout and a default name.
|
||||
* The default name is the name of the class.
|
||||
* @param timeout the time (in seconds) before this command "times out"
|
||||
* @throws IllegalArgumentException if given a negative timeout
|
||||
* @see Command#isTimedOut() isTimedOut()
|
||||
*/
|
||||
public Command(double timeout) {
|
||||
this();
|
||||
if (timeout < 0) {
|
||||
throw new IllegalArgumentException("Timeout must not be negative. Given:" + timeout);
|
||||
}
|
||||
m_timeout = timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new command with the given name and timeout.
|
||||
* @param name the name of the command
|
||||
* @param timeout the time (in seconds) before this command "times out"
|
||||
* @throws IllegalArgumentException if given a negative timeout or name was null.
|
||||
* @see Command#isTimedOut() isTimedOut()
|
||||
*/
|
||||
public Command(String name, double timeout) {
|
||||
this(name);
|
||||
if (timeout < 0) {
|
||||
throw new IllegalArgumentException("Timeout must not be negative. Given:" + timeout);
|
||||
}
|
||||
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.
|
||||
* @param seconds the timeout (in seconds)
|
||||
* @throws IllegalArgumentException if seconds is negative
|
||||
* @see Command#isTimedOut() isTimedOut()
|
||||
*/
|
||||
protected synchronized final void setTimeout(double seconds) {
|
||||
if (seconds < 0) {
|
||||
throw new IllegalArgumentException("Seconds must be positive. Given:" + seconds);
|
||||
}
|
||||
m_timeout = seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time since this command was initialized (in seconds).
|
||||
* This function will work even if there is no specified timeout.
|
||||
* @return the time since this command was initialized (in seconds).
|
||||
*/
|
||||
public synchronized final double timeSinceInitialized() {
|
||||
return m_startTime < 0 ? 0 : Timer.getFPGATimestamp() - m_startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method specifies that the given {@link Subsystem} is used by this command.
|
||||
* This method is crucial to the functioning of the Command System in general.
|
||||
*
|
||||
* <p>Note that the recommended way to call this method is in the constructor.</p>
|
||||
*
|
||||
* @param subsystem the {@link Subsystem} required
|
||||
* @throws IllegalArgumentException if subsystem is null
|
||||
* @throws IllegalUseOfCommandException if this command has started before or if it has been given to a {@link CommandGroup}
|
||||
* @see Subsystem
|
||||
*/
|
||||
protected synchronized void requires(Subsystem subsystem) {
|
||||
validate("Can not add new requirement to command");
|
||||
if (subsystem != null) {
|
||||
if (m_requirements == null) {
|
||||
m_requirements = new Set();
|
||||
}
|
||||
m_requirements.add(subsystem);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Subsystem must not be null.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the command has been removed.
|
||||
* This will call {@link Command#interrupted() interrupted()} or {@link Command#end() end()}.
|
||||
*/
|
||||
synchronized void removed() {
|
||||
if (m_initialized) {
|
||||
if (isCanceled()) {
|
||||
interrupted();
|
||||
_interrupted();
|
||||
} else {
|
||||
end();
|
||||
_end();
|
||||
}
|
||||
}
|
||||
m_initialized = false;
|
||||
m_canceled = false;
|
||||
m_running = false;
|
||||
if (table != null) {
|
||||
table.putBoolean("running", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The run method is used internally to actually run the commands.
|
||||
* @return whether or not the command should stay within the {@link Scheduler}.
|
||||
*/
|
||||
synchronized boolean run() {
|
||||
if (!m_runWhenDisabled && m_parent == null && DriverStation.getInstance().isDisabled()) {
|
||||
cancel();
|
||||
}
|
||||
if (isCanceled()) {
|
||||
return false;
|
||||
}
|
||||
if (!m_initialized) {
|
||||
m_initialized = true;
|
||||
startTiming();
|
||||
_initialize();
|
||||
initialize();
|
||||
}
|
||||
_execute();
|
||||
execute();
|
||||
return !isFinished();
|
||||
}
|
||||
|
||||
/**
|
||||
* The initialize method is called the first time this Command is run after
|
||||
* being started.
|
||||
*/
|
||||
protected abstract void initialize();
|
||||
|
||||
/** A shadow method called before {@link Command#initialize() initialize()} */
|
||||
void _initialize() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The execute method is called repeatedly until this Command either finishes
|
||||
* or is canceled.
|
||||
*/
|
||||
protected abstract void execute();
|
||||
|
||||
/** A shadow method called before {@link Command#execute() execute()} */
|
||||
void _execute() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this command is finished.
|
||||
* If it is, then the command will be removed
|
||||
* and {@link Command#end() end()} will be called.
|
||||
*
|
||||
* <p>It may be useful for a team to reference the {@link Command#isTimedOut() isTimedOut()} method
|
||||
* for time-sensitive commands.</p>
|
||||
* @return whether this command is finished.
|
||||
* @see Command#isTimedOut() isTimedOut()
|
||||
*/
|
||||
protected abstract boolean isFinished();
|
||||
|
||||
/**
|
||||
* Called when the command ended peacefully. This is where you may want
|
||||
* to wrap up loose ends, like shutting off a motor that was being used
|
||||
* in the command.
|
||||
*/
|
||||
protected abstract void end();
|
||||
|
||||
/** A shadow method called after {@link Command#end() end()}. */
|
||||
void _end() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the command ends because somebody called {@link Command#cancel() cancel()}
|
||||
* or another command shared the same requirements as this one, and booted
|
||||
* it out.
|
||||
*
|
||||
* <p>This is where you may want
|
||||
* to wrap up loose ends, like shutting off a motor that was being used
|
||||
* in the command.</p>
|
||||
*
|
||||
* <p>Generally, it is useful to simply call the {@link Command#end() end()} method
|
||||
* within this method</p>
|
||||
*/
|
||||
protected abstract void interrupted();
|
||||
|
||||
/** A shadow method called after {@link Command#interrupted() interrupted()}. */
|
||||
void _interrupted() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to indicate that the timer should start.
|
||||
* This is called right before {@link Command#initialize() initialize()} is, inside the
|
||||
* {@link Command#run() run()} method.
|
||||
*/
|
||||
private void startTiming() {
|
||||
m_startTime = Timer.getFPGATimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the {@link Command#timeSinceInitialized() timeSinceInitialized()}
|
||||
* method returns a number which is greater than or equal to the timeout for the command.
|
||||
* If there is no timeout, this will always return false.
|
||||
* @return whether the time has expired
|
||||
*/
|
||||
protected synchronized boolean isTimedOut() {
|
||||
return m_timeout != -1 && timeSinceInitialized() >= m_timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the requirements (as an {@link Enumeration Enumeration} of {@link Subsystem Subsystems}) of this command
|
||||
* @return the requirements (as an {@link Enumeration Enumeration} of {@link Subsystem Subsystems}) of this command
|
||||
*/
|
||||
synchronized Enumeration getRequirements() {
|
||||
return m_requirements == null ? emptyEnumeration : m_requirements.getElements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents further changes from being made
|
||||
*/
|
||||
synchronized void lockChanges() {
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If changes are locked, then this will throw an {@link IllegalUseOfCommandException}.
|
||||
* @param message the message to say (it is appended by a default message)
|
||||
*/
|
||||
synchronized void validate(String message) {
|
||||
if (m_locked) {
|
||||
throw new IllegalUseOfCommandException(message + " after being started or being added to a command group");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent of this command. No actual change is made to the group.
|
||||
* @param parent the parent
|
||||
* @throws IllegalUseOfCommandException if this {@link Command} already is already in a group
|
||||
*/
|
||||
synchronized void setParent(CommandGroup parent) {
|
||||
if (this.m_parent != null) {
|
||||
throw new IllegalUseOfCommandException("Can not give command to a command group after already being put in a command group");
|
||||
}
|
||||
lockChanges();
|
||||
this.m_parent = parent;
|
||||
if (table != null) {
|
||||
table.putBoolean("isParented", true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts up the command. Gets the command ready to start.
|
||||
* <p>Note that the command will eventually start, however it will not necessarily
|
||||
* do so immediately, and may in fact be canceled before initialize is even called.</p>
|
||||
* @throws IllegalUseOfCommandException if the command is a part of a CommandGroup
|
||||
*/
|
||||
public synchronized void start() {
|
||||
lockChanges();
|
||||
if (m_parent != null) {
|
||||
throw new IllegalUseOfCommandException("Can not start a command that is a part of a command group");
|
||||
}
|
||||
Scheduler.getInstance().add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used internally to mark that the command has been started.
|
||||
* The lifecycle of a command is:
|
||||
*
|
||||
* startRunning() is called.
|
||||
* run() is called (multiple times potentially)
|
||||
* removed() is called
|
||||
*
|
||||
* It is very important that startRunning and removed be called in order or some assumptions
|
||||
* of the code will be broken.
|
||||
*/
|
||||
synchronized void startRunning() {
|
||||
m_running = true;
|
||||
m_startTime = -1;
|
||||
if (table != null) {
|
||||
table.putBoolean("running", true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the command is running.
|
||||
* This may return true even if the command has just been canceled, as it may
|
||||
* not have yet called {@link Command#interrupted()}.
|
||||
* @return whether or not the command is running
|
||||
*/
|
||||
public synchronized boolean isRunning() {
|
||||
return m_running;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will cancel the current command.
|
||||
* <p>This will cancel the current command eventually. It can be called multiple times.
|
||||
* And it can be called when the command is not running. If the command is running though,
|
||||
* then the command will be marked as canceled and eventually removed.</p>
|
||||
* <p>A command can not be canceled
|
||||
* if it is a part of a command group, you must cancel the command group instead.</p>
|
||||
* @throws IllegalUseOfCommandException if this command is a part of a command group
|
||||
*/
|
||||
public synchronized void cancel() {
|
||||
if (m_parent != null) {
|
||||
throw new IllegalUseOfCommandException("Can not manually cancel a command in a command group");
|
||||
}
|
||||
_cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* This works like cancel(), except that it doesn't throw an exception if it is a part
|
||||
* of a command group. Should only be called by the parent command group.
|
||||
*/
|
||||
synchronized void _cancel() {
|
||||
if (isRunning()) {
|
||||
m_canceled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this has been canceled.
|
||||
* @return whether or not this has been canceled
|
||||
*/
|
||||
public synchronized boolean isCanceled() {
|
||||
return m_canceled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this command can be interrupted.
|
||||
* @return whether or not this command can be interrupted
|
||||
*/
|
||||
public synchronized boolean isInterruptible() {
|
||||
return m_interruptible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not this command can be interrupted.
|
||||
* @param interruptible whether or not this command can be interrupted
|
||||
*/
|
||||
protected synchronized void setInterruptible(boolean interruptible) {
|
||||
this.m_interruptible = interruptible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the command requires the given {@link Subsystem}.
|
||||
* @param system the system
|
||||
* @return whether or not the subsystem is required, or false if given null
|
||||
*/
|
||||
public synchronized boolean doesRequire(Subsystem system) {
|
||||
return m_requirements != null && m_requirements.contains(system);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link CommandGroup} that this command is a part of.
|
||||
* Will return null if this {@link Command} is not in a group.
|
||||
* @return the {@link CommandGroup} that this command is a part of (or null if not in group)
|
||||
*/
|
||||
public synchronized CommandGroup getGroup() {
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not this {@link Command} should run when the robot is disabled.
|
||||
*
|
||||
* <p>By default a command will not run when the robot is disabled, and will in fact be canceled.</p>
|
||||
* @param run whether or not this command should run when the robot is disabled
|
||||
*/
|
||||
public void setRunWhenDisabled(boolean run) {
|
||||
m_runWhenDisabled = run;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this {@link Command} will run when the robot is disabled, or if it will cancel itself.
|
||||
* @return whether or not this {@link Command} will run when the robot is disabled, or if it will cancel itself
|
||||
*/
|
||||
public boolean willRunWhenDisabled() {
|
||||
return m_runWhenDisabled;
|
||||
}
|
||||
/** An empty enumeration given whenever there are no requirements */
|
||||
private static Enumeration emptyEnumeration = new Enumeration() {
|
||||
|
||||
public boolean hasMoreElements() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object nextElement() {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The string representation for a {@link Command} is by default its name.
|
||||
* @return the string representation of this object
|
||||
*/
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
|
||||
public String getSmartDashboardType() {
|
||||
return "Command";
|
||||
}
|
||||
private ITableListener listener = new ITableListener() {
|
||||
public void valueChanged(ITable table, String key, Object value, boolean isNew) {
|
||||
if (((Boolean) value).booleanValue()) {
|
||||
start();
|
||||
} else {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
};
|
||||
private ITable table;
|
||||
public void initTable(ITable table) {
|
||||
if(this.table!=null)
|
||||
this.table.removeTableListener(listener);
|
||||
this.table = table;
|
||||
if(table!=null) {
|
||||
table.putString("name", getName());
|
||||
table.putBoolean("running", isRunning());
|
||||
table.putBoolean("isParented", m_parent != null);
|
||||
table.addTableListener("running", listener, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,398 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* A {@link CommandGroup} is a list of commands which are executed in sequence.
|
||||
*
|
||||
* <p>Commands in a {@link CommandGroup} are added using the {@link CommandGroup#addSequential(Command) addSequential(...)} method
|
||||
* and are called sequentially.
|
||||
* {@link CommandGroup CommandGroups} are themselves {@link Command commands}
|
||||
* and can be given to other {@link CommandGroup CommandGroups}.</p>
|
||||
*
|
||||
* <p>{@link CommandGroup CommandGroups} will carry all of the requirements of their {@link Command subcommands}. Additional
|
||||
* requirements can be specified by calling {@link CommandGroup#requires(Subsystem) requires(...)}
|
||||
* normally in the constructor.</P>
|
||||
*
|
||||
* <p>CommandGroups can also execute commands in parallel, simply by adding them
|
||||
* using {@link CommandGroup#addParallel(Command) addParallel(...)}.</p>
|
||||
*
|
||||
* @author Brad Miller
|
||||
* @author Joe Grinstead
|
||||
* @see Command
|
||||
* @see Subsystem
|
||||
* @see IllegalUseOfCommandException
|
||||
*/
|
||||
public class CommandGroup extends Command {
|
||||
|
||||
/** The commands in this group (stored in entries) */
|
||||
private Vector m_commands = new Vector();
|
||||
/** The active children in this group (stored in entries) */
|
||||
Vector m_children = new Vector();
|
||||
/** The current command, -1 signifies that none have been run */
|
||||
private int m_currentCommandIndex = -1;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CommandGroup CommandGroup}.
|
||||
* The name of this command will be set to its class name.
|
||||
*/
|
||||
public CommandGroup() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CommandGroup CommandGroup} with the given name.
|
||||
* @param name the name for this command group
|
||||
* @throws IllegalArgumentException if name is null
|
||||
*/
|
||||
public CommandGroup(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new {@link Command Command} to the group. The {@link Command Command} will be started after
|
||||
* all the previously added {@link Command Commands}.
|
||||
*
|
||||
* <p>Note that any requirements the given {@link Command Command} has will be added to the
|
||||
* group. For this reason, a {@link Command Command's} requirements can not be changed after
|
||||
* being added to a group.</p>
|
||||
*
|
||||
* <p>It is recommended that this method be called in the constructor.</p>
|
||||
*
|
||||
* @param command The {@link Command Command} to be added
|
||||
* @throws IllegalUseOfCommandException if the group has been started before or been given to another group
|
||||
* @throws IllegalArgumentException if command is null
|
||||
*/
|
||||
public synchronized final void addSequential(Command command) {
|
||||
validate("Can not add new command to command group");
|
||||
if (command == null) {
|
||||
throw new IllegalArgumentException("Given null command");
|
||||
}
|
||||
|
||||
command.setParent(this);
|
||||
|
||||
m_commands.addElement(new Entry(command, Entry.IN_SEQUENCE));
|
||||
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
|
||||
requires((Subsystem) e.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new {@link Command Command} to the group with a given timeout.
|
||||
* The {@link Command Command} will be started after all the previously added commands.
|
||||
*
|
||||
* <p>Once the {@link Command Command} is started, it will be run until it finishes or the time
|
||||
* expires, whichever is sooner. Note that the given {@link Command Command} will have no
|
||||
* knowledge that it is on a timer.</p>
|
||||
*
|
||||
* <p>Note that any requirements the given {@link Command Command} has will be added to the
|
||||
* group. For this reason, a {@link Command Command's} requirements can not be changed after
|
||||
* being added to a group.</p>
|
||||
*
|
||||
* <p>It is recommended that this method be called in the constructor.</p>
|
||||
*
|
||||
* @param command The {@link Command Command} to be added
|
||||
* @param timeout The timeout (in seconds)
|
||||
* @throws IllegalUseOfCommandException if the group has been started before or been given to another group or
|
||||
* if the {@link Command Command} has been started before or been given to another group
|
||||
* @throws IllegalArgumentException if command is null or timeout is negative
|
||||
*/
|
||||
public synchronized final void addSequential(Command command, double timeout) {
|
||||
validate("Can not add new command to command group");
|
||||
if (command == null) {
|
||||
throw new IllegalArgumentException("Given null command");
|
||||
}
|
||||
if (timeout < 0) {
|
||||
throw new IllegalArgumentException("Can not be given a negative timeout");
|
||||
}
|
||||
|
||||
command.setParent(this);
|
||||
|
||||
m_commands.addElement(new Entry(command, Entry.IN_SEQUENCE, timeout));
|
||||
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
|
||||
requires((Subsystem) e.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new child {@link Command} to the group. The {@link Command} will be started after
|
||||
* all the previously added {@link Command Commands}.
|
||||
*
|
||||
* <p>Instead of waiting for the child to finish, a {@link CommandGroup} will have it
|
||||
* run at the same time as the subsequent {@link Command Commands}. The child will run until either
|
||||
* it finishes, a new child with conflicting requirements is started, or
|
||||
* the main sequence runs a {@link Command} with conflicting requirements. In the latter
|
||||
* two cases, the child will be canceled even if it says it can't be
|
||||
* interrupted.</p>
|
||||
*
|
||||
* <p>Note that any requirements the given {@link Command Command} has will be added to the
|
||||
* group. For this reason, a {@link Command Command's} requirements can not be changed after
|
||||
* being added to a group.</p>
|
||||
*
|
||||
* <p>It is recommended that this method be called in the constructor.</p>
|
||||
*
|
||||
* @param command The command to be added
|
||||
* @throws IllegalUseOfCommandException if the group has been started before or been given to another command group
|
||||
* @throws IllegalArgumentException if command is null
|
||||
*/
|
||||
public synchronized final void addParallel(Command command) {
|
||||
validate("Can not add new command to command group");
|
||||
if (command == null) {
|
||||
throw new NullPointerException("Given null command");
|
||||
}
|
||||
|
||||
command.setParent(this);
|
||||
|
||||
m_commands.addElement(new Entry(command, Entry.BRANCH_CHILD));
|
||||
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
|
||||
requires((Subsystem) e.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new child {@link Command} to the group with the given timeout. The {@link Command} will be started after
|
||||
* all the previously added {@link Command Commands}.
|
||||
*
|
||||
* <p>Once the {@link Command Command} is started, it will run until it finishes, is interrupted,
|
||||
* or the time expires, whichever is sooner. Note that the given {@link Command Command} will have no
|
||||
* knowledge that it is on a timer.</p>
|
||||
*
|
||||
* <p>Instead of waiting for the child to finish, a {@link CommandGroup} will have it
|
||||
* run at the same time as the subsequent {@link Command Commands}. The child will run until either
|
||||
* it finishes, the timeout expires, a new child with conflicting requirements is started, or
|
||||
* the main sequence runs a {@link Command} with conflicting requirements. In the latter
|
||||
* two cases, the child will be canceled even if it says it can't be
|
||||
* interrupted.</p>
|
||||
*
|
||||
* <p>Note that any requirements the given {@link Command Command} has will be added to the
|
||||
* group. For this reason, a {@link Command Command's} requirements can not be changed after
|
||||
* being added to a group.</p>
|
||||
*
|
||||
* <p>It is recommended that this method be called in the constructor.</p>
|
||||
*
|
||||
* @param command The command to be added
|
||||
* @param timeout The timeout (in seconds)
|
||||
* @throws IllegalUseOfCommandException if the group has been started before or been given to another command group
|
||||
* @throws IllegalArgumentException if command is null
|
||||
*/
|
||||
public synchronized final void addParallel(Command command, double timeout) {
|
||||
validate("Can not add new command to command group");
|
||||
if (command == null) {
|
||||
throw new NullPointerException("Given null command");
|
||||
}
|
||||
if (timeout < 0) {
|
||||
throw new IllegalArgumentException("Can not be given a negative timeout");
|
||||
}
|
||||
|
||||
command.setParent(this);
|
||||
|
||||
m_commands.addElement(new Entry(command, Entry.BRANCH_CHILD, timeout));
|
||||
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
|
||||
requires((Subsystem) e.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
void _initialize() {
|
||||
m_currentCommandIndex = -1;
|
||||
}
|
||||
|
||||
void _execute() {
|
||||
Entry entry = null;
|
||||
Command cmd = null;
|
||||
boolean firstRun = false;
|
||||
if (m_currentCommandIndex == -1) {
|
||||
firstRun = true;
|
||||
m_currentCommandIndex = 0;
|
||||
}
|
||||
|
||||
while (m_currentCommandIndex < m_commands.size()) {
|
||||
|
||||
if (cmd != null) {
|
||||
if (entry.isTimedOut()) {
|
||||
cmd._cancel();
|
||||
}
|
||||
if (cmd.run()) {
|
||||
break;
|
||||
} else {
|
||||
cmd.removed();
|
||||
m_currentCommandIndex++;
|
||||
firstRun = true;
|
||||
cmd = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
entry = (Entry) m_commands.elementAt(m_currentCommandIndex);
|
||||
cmd = null;
|
||||
|
||||
switch (entry.state) {
|
||||
case Entry.IN_SEQUENCE:
|
||||
cmd = entry.command;
|
||||
if (firstRun) {
|
||||
cmd.startRunning();
|
||||
cancelConflicts(cmd);
|
||||
}
|
||||
firstRun = false;
|
||||
break;
|
||||
case Entry.BRANCH_PEER:
|
||||
m_currentCommandIndex++;
|
||||
entry.command.start();
|
||||
break;
|
||||
case Entry.BRANCH_CHILD:
|
||||
m_currentCommandIndex++;
|
||||
cancelConflicts(entry.command);
|
||||
entry.command.startRunning();
|
||||
m_children.addElement(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Run Children
|
||||
for (int i = 0; i < m_children.size(); i++) {
|
||||
entry = (Entry) m_children.elementAt(i);
|
||||
Command child = entry.command;
|
||||
if (entry.isTimedOut()) {
|
||||
child._cancel();
|
||||
}
|
||||
if (!child.run()) {
|
||||
child.removed();
|
||||
m_children.removeElementAt(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _end() {
|
||||
// Theoretically, we don't have to check this, but we do if teams override the isFinished method
|
||||
if (m_currentCommandIndex != -1 && m_currentCommandIndex < m_commands.size()) {
|
||||
Command cmd = ((Entry) m_commands.elementAt(m_currentCommandIndex)).command;
|
||||
cmd._cancel();
|
||||
cmd.removed();
|
||||
}
|
||||
|
||||
Enumeration children = m_children.elements();
|
||||
while (children.hasMoreElements()) {
|
||||
Command cmd = ((Entry) children.nextElement()).command;
|
||||
cmd._cancel();
|
||||
cmd.removed();
|
||||
}
|
||||
m_children.removeAllElements();
|
||||
}
|
||||
|
||||
void _interrupted() {
|
||||
_end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all the {@link Command Commands} in this group
|
||||
* have been started and have finished.
|
||||
*
|
||||
* <p>Teams may override this method, although they should probably
|
||||
* reference super.isFinished() if they do.</p>
|
||||
*
|
||||
* @return whether this {@link CommandGroup} is finished
|
||||
*/
|
||||
protected boolean isFinished() {
|
||||
return m_currentCommandIndex >= m_commands.size() && m_children.isEmpty();
|
||||
}
|
||||
|
||||
// Can be overwritten by teams
|
||||
protected void initialize() {
|
||||
}
|
||||
|
||||
// Can be overwritten by teams
|
||||
protected void execute() {
|
||||
}
|
||||
|
||||
// Can be overwritten by teams
|
||||
protected void end() {
|
||||
}
|
||||
|
||||
// Can be overwritten by teams
|
||||
protected void interrupted() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this group is interruptible.
|
||||
* A command group will be uninterruptible if {@link CommandGroup#setInterruptible(boolean) setInterruptable(false)}
|
||||
* was called or if it is currently running an uninterruptible command
|
||||
* or child.
|
||||
*
|
||||
* @return whether or not this {@link CommandGroup} is interruptible.
|
||||
*/
|
||||
public synchronized boolean isInterruptible() {
|
||||
if (!super.isInterruptible()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_currentCommandIndex != -1 && m_currentCommandIndex < m_commands.size()) {
|
||||
Command cmd = ((Entry) m_commands.elementAt(m_currentCommandIndex)).command;
|
||||
if (!cmd.isInterruptible()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_children.size(); i++) {
|
||||
if (!((Entry) m_children.elementAt(i)).command.isInterruptible()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void cancelConflicts(Command command) {
|
||||
for (int i = 0; i < m_children.size(); i++) {
|
||||
Command child = ((Entry) m_children.elementAt(i)).command;
|
||||
|
||||
Enumeration requirements = command.getRequirements();
|
||||
|
||||
while (requirements.hasMoreElements()) {
|
||||
Object requirement = requirements.nextElement();
|
||||
if (child.doesRequire((Subsystem) requirement)) {
|
||||
child._cancel();
|
||||
child.removed();
|
||||
m_children.removeElementAt(i--);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Entry {
|
||||
|
||||
private static final int IN_SEQUENCE = 0;
|
||||
private static final int BRANCH_PEER = 1;
|
||||
private static final int BRANCH_CHILD = 2;
|
||||
Command command;
|
||||
int state;
|
||||
double timeout;
|
||||
|
||||
Entry(Command command, int state) {
|
||||
this.command = command;
|
||||
this.state = state;
|
||||
this.timeout = -1;
|
||||
}
|
||||
|
||||
Entry(Command command, int state, double timeout) {
|
||||
this.command = command;
|
||||
this.state = state;
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
boolean isTimedOut() {
|
||||
if (timeout == -1) {
|
||||
return false;
|
||||
} else {
|
||||
double time = command.timeSinceInitialized();
|
||||
return time == 0 ? false : time >= timeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
/**
|
||||
* This exception will be thrown if a command is used illegally. There are
|
||||
* several ways for this to happen.
|
||||
*
|
||||
* <p>Basically, a command becomes "locked" after it is first started or added
|
||||
* to a command group.</p>
|
||||
*
|
||||
* <p>This exception should be thrown if (after a command has been locked) its requirements
|
||||
* change, it is put into multiple command groups,
|
||||
* it is started from outside its command group, or it adds a new child.</p>
|
||||
*
|
||||
* @author Joe Grinstead
|
||||
*/
|
||||
public class IllegalUseOfCommandException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Instantiates an {@link IllegalUseOfCommandException}.
|
||||
*/
|
||||
public IllegalUseOfCommandException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates an {@link IllegalUseOfCommandException} with the given message.
|
||||
* @param message the message
|
||||
*/
|
||||
public IllegalUseOfCommandException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Greg
|
||||
*/
|
||||
class LinkedListElement {
|
||||
private LinkedListElement next;
|
||||
private LinkedListElement previous;
|
||||
private Command data;
|
||||
|
||||
public LinkedListElement() {
|
||||
}
|
||||
|
||||
public void setData(Command newData) {
|
||||
data = newData;
|
||||
}
|
||||
|
||||
public Command getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public LinkedListElement getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public LinkedListElement getPrevious() {
|
||||
return previous;
|
||||
}
|
||||
|
||||
public void add(LinkedListElement l) {
|
||||
if(next == null) {
|
||||
next = l;
|
||||
next.previous = this;
|
||||
} else {
|
||||
next.previous = l;
|
||||
l.next = next;
|
||||
l.previous = this;
|
||||
next = l;
|
||||
}
|
||||
}
|
||||
|
||||
public LinkedListElement remove() {
|
||||
if(previous == null && next == null) {
|
||||
|
||||
} else if(next == null) {
|
||||
previous.next = null;
|
||||
} else if(previous == null) {
|
||||
next.previous = null;
|
||||
} else {
|
||||
next.previous = previous;
|
||||
previous.next = next;
|
||||
}
|
||||
LinkedListElement n = next;
|
||||
next = null;
|
||||
previous = null;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
import edu.wpi.first.wpilibj.PIDController;
|
||||
import edu.wpi.first.wpilibj.PIDOutput;
|
||||
import edu.wpi.first.wpilibj.PIDSource;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
* This class defines a {@link Command} which interacts heavily with a PID loop.
|
||||
*
|
||||
* <p>It provides some convenience methods to run an internal {@link PIDController}.
|
||||
* It will also start and stop said {@link PIDController} when the {@link PIDCommand} is
|
||||
* first initialized and ended/interrupted.</p>
|
||||
*
|
||||
* @author Joe Grinstead
|
||||
*/
|
||||
public abstract class PIDCommand extends Command implements Sendable {
|
||||
|
||||
/** The internal {@link PIDController} */
|
||||
private PIDController controller;
|
||||
/** An output which calls {@link PIDCommand#usePIDOutput(double)} */
|
||||
private PIDOutput output = new PIDOutput() {
|
||||
|
||||
public void pidWrite(double output) {
|
||||
usePIDOutput(output);
|
||||
}
|
||||
};
|
||||
/** A source which calls {@link PIDCommand#returnPIDInput()} */
|
||||
private PIDSource source = new PIDSource() {
|
||||
|
||||
public double pidGet() {
|
||||
return returnPIDInput();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDCommand} that will use the given p, i and d values.
|
||||
* @param name the name of the command
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
*/
|
||||
public PIDCommand(String name, double p, double i, double d) {
|
||||
super(name);
|
||||
controller = new PIDController(p, i, d, source, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDCommand} that will use the given p, i and d values. It will also space the time
|
||||
* between PID loop calculations to be equal to the given period.
|
||||
* @param name the name
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
* @param period the time (in seconds) between calculations
|
||||
*/
|
||||
public PIDCommand(String name, double p, double i, double d, double period) {
|
||||
super(name);
|
||||
controller = new PIDController(p, i, d, source, output, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDCommand} that will use the given p, i and d values.
|
||||
* It will use the class name as its name.
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
*/
|
||||
public PIDCommand(double p, double i, double d) {
|
||||
controller = new PIDController(p, i, d, source, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDCommand} that will use the given p, i and d values.
|
||||
* It will use the class name as its name..
|
||||
* It will also space the time
|
||||
* between PID loop calculations to be equal to the given period.
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
* @param period the time (in seconds) between calculations
|
||||
*/
|
||||
public PIDCommand(double p, double i, double d, double period) {
|
||||
controller = new PIDController(p, i, d, source, output, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link PIDController} used by this {@link PIDCommand}.
|
||||
* Use this if you would like to fine tune the pid loop.
|
||||
*
|
||||
* <p>Notice that calling {@link PIDController#setSetpoint(double) setSetpoint(...)} on the controller
|
||||
* will not result in the setpoint being trimmed to be in
|
||||
* the range defined by {@link PIDCommand#setSetpointRange(double, double) setSetpointRange(...)}.</p>
|
||||
*
|
||||
* @return the {@link PIDController} used by this {@link PIDCommand}
|
||||
*/
|
||||
protected PIDController getPIDController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
void _initialize() {
|
||||
controller.enable();
|
||||
}
|
||||
|
||||
void _end() {
|
||||
controller.disable();
|
||||
}
|
||||
|
||||
void _interrupted() {
|
||||
_end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given value to the setpoint.
|
||||
* If {@link PIDCommand#setRange(double, double) setRange(...)} was used,
|
||||
* then the bounds will still be honored by this method.
|
||||
* @param deltaSetpoint the change in the setpoint
|
||||
*/
|
||||
public void setSetpointRelative(double deltaSetpoint) {
|
||||
setSetpoint(getSetpoint() + deltaSetpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the setpoint to the given value. If {@link PIDCommand#setRange(double, double) setRange(...)}
|
||||
* was called,
|
||||
* then the given setpoint
|
||||
* will be trimmed to fit within the range.
|
||||
* @param setpoint the new setpoint
|
||||
*/
|
||||
protected void setSetpoint(double setpoint) {
|
||||
controller.setSetpoint(setpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setpoint.
|
||||
* @return the setpoint
|
||||
*/
|
||||
protected double getSetpoint() {
|
||||
return controller.getSetpoint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current position
|
||||
* @return the current position
|
||||
*/
|
||||
protected double getPosition() {
|
||||
return returnPIDInput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input for the pid loop.
|
||||
*
|
||||
* <p>It returns the input for the pid loop, so if this command was based
|
||||
* off of a gyro, then it should return the angle of the gyro</p>
|
||||
*
|
||||
* <p>All subclasses of {@link PIDCommand} must override this method.</p>
|
||||
*
|
||||
* <p>This method will be called in a different thread then the {@link Scheduler} thread.</p>
|
||||
*
|
||||
* @return the value the pid loop should use as input
|
||||
*/
|
||||
protected abstract double returnPIDInput();
|
||||
|
||||
/**
|
||||
* Uses the value that the pid loop calculated. The calculated value is the "output" parameter.
|
||||
* This method is a good time to set motor values, maybe something along the lines of <code>driveline.tankDrive(output, -output)</code>
|
||||
*
|
||||
* <p>All subclasses of {@link PIDCommand} must override this method.</p>
|
||||
*
|
||||
* <p>This method will be called in a different thread then the {@link Scheduler} thread.</p>
|
||||
*
|
||||
* @param output the value the pid loop calculated
|
||||
*/
|
||||
protected abstract void usePIDOutput(double output);
|
||||
|
||||
public String getSmartDashboardType() {
|
||||
return "PIDCommand";
|
||||
}
|
||||
public void initTable(ITable table) {
|
||||
controller.initTable(table);
|
||||
super.initTable(table);
|
||||
}
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
import edu.wpi.first.wpilibj.PIDController;
|
||||
import edu.wpi.first.wpilibj.PIDOutput;
|
||||
import edu.wpi.first.wpilibj.PIDSource;
|
||||
import edu.wpi.first.wpilibj.Sendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
* This class is designed to handle the case where there is a {@link Subsystem}
|
||||
* which uses a single {@link PIDController} almost constantly (for instance,
|
||||
* an elevator which attempts to stay at a constant height).
|
||||
*
|
||||
* <p>It provides some convenience methods to run an internal {@link PIDController}.
|
||||
* It also allows access to the internal {@link PIDController} in order to give total control
|
||||
* to the programmer.</p>
|
||||
*
|
||||
* @author Joe Grinstead
|
||||
*/
|
||||
public abstract class PIDSubsystem extends Subsystem implements Sendable {
|
||||
|
||||
/** The internal {@link PIDController} */
|
||||
private PIDController controller;
|
||||
/** An output which calls {@link PIDCommand#usePIDOutput(double)} */
|
||||
private PIDOutput output = new PIDOutput() {
|
||||
|
||||
public void pidWrite(double output) {
|
||||
usePIDOutput(output);
|
||||
}
|
||||
};
|
||||
/** A source which calls {@link PIDCommand#returnPIDInput()} */
|
||||
private PIDSource source = new PIDSource() {
|
||||
|
||||
public double pidGet() {
|
||||
return returnPIDInput();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
|
||||
* @param name the name
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
*/
|
||||
public PIDSubsystem(String name, double p, double i, double d) {
|
||||
super(name);
|
||||
controller = new PIDController(p, i, d, source, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
|
||||
* @param name the name
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
* @param f the feed forward value
|
||||
*/
|
||||
public PIDSubsystem(String name, double p, double i, double d, double f) {
|
||||
super(name);
|
||||
controller = new PIDController(p, i, d, f, source, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values. It will also space the time
|
||||
* between PID loop calculations to be equal to the given period.
|
||||
* @param name the name
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
* @param period the time (in seconds) between calculations
|
||||
*/
|
||||
public PIDSubsystem(String name, double p, double i, double d, double f, double period) {
|
||||
super(name);
|
||||
controller = new PIDController(p, i, d, f, source, output, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
|
||||
* It will use the class name as its name.
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
*/
|
||||
public PIDSubsystem(double p, double i, double d) {
|
||||
controller = new PIDController(p, i, d, source, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
|
||||
* It will use the class name as its name.
|
||||
* It will also space the time
|
||||
* between PID loop calculations to be equal to the given period.
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
* @param f the feed forward coefficient
|
||||
* @param period the time (in seconds) between calculations
|
||||
*/
|
||||
public PIDSubsystem(double p, double i, double d, double period, double f) {
|
||||
controller = new PIDController(p, i, d, f, source, output, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
|
||||
* It will use the class name as its name.
|
||||
* It will also space the time
|
||||
* between PID loop calculations to be equal to the given period.
|
||||
* @param p the proportional value
|
||||
* @param i the integral value
|
||||
* @param d the derivative value
|
||||
* @param period the time (in seconds) between calculations
|
||||
*/
|
||||
public PIDSubsystem(double p, double i, double d, double period) {
|
||||
controller = new PIDController(p, i, d, source, output, period);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link PIDController} used by this {@link PIDSubsystem}.
|
||||
* Use this if you would like to fine tune the pid loop.
|
||||
*
|
||||
* <p>Notice that calling {@link PIDController#setSetpoint(double) setSetpoint(...)} on the controller
|
||||
* will not result in the setpoint being trimmed to be in
|
||||
* the range defined by {@link PIDSubsystem#setSetpointRange(double, double) setSetpointRange(...)}.</p>
|
||||
*
|
||||
* @return the {@link PIDController} used by this {@link PIDSubsystem}
|
||||
*/
|
||||
public PIDController getPIDController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the given value to the setpoint.
|
||||
* If {@link PIDCommand#setRange(double, double) setRange(...)} was used,
|
||||
* then the bounds will still be honored by this method.
|
||||
* @param deltaSetpoint the change in the setpoint
|
||||
*/
|
||||
public void setSetpointRelative(double deltaSetpoint) {
|
||||
setSetpoint(getPosition() + deltaSetpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the setpoint to the given value. If {@link PIDCommand#setRange(double, double) setRange(...)}
|
||||
* was called,
|
||||
* then the given setpoint
|
||||
* will be trimmed to fit within the range.
|
||||
* @param setpoint the new setpoint
|
||||
*/
|
||||
public void setSetpoint(double setpoint) {
|
||||
controller.setSetpoint(setpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setpoint.
|
||||
* @return the setpoint
|
||||
*/
|
||||
public double getSetpoint() {
|
||||
return controller.getSetpoint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current position
|
||||
* @return the current position
|
||||
*/
|
||||
public double getPosition() {
|
||||
return returnPIDInput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum and minimum values expected from the input.
|
||||
*
|
||||
* @param minimumInput the minimum value expected from the input
|
||||
* @param maximumInput the maximum value expected from the output
|
||||
*/
|
||||
public void setInputRange(double minimumInput, double maximumInput) {
|
||||
controller.setInputRange(minimumInput, maximumInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the absolute error which is considered tolerable for use with
|
||||
* OnTarget. The value is in the same range as the PIDInput values.
|
||||
* @param t A PIDController.Tolerance object instance that is for example
|
||||
* AbsoluteTolerance or PercentageTolerance. E.g. setTolerance(new PIDController.AbsoluteTolerance(0.1))
|
||||
*/
|
||||
public void setAbsoluteTolerance(double t) {
|
||||
controller.setAbsoluteTolerance(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the percentage error which is considered tolerable for use with
|
||||
* OnTarget. (Value of 15.0 == 15 percent)
|
||||
* @param t A PIDController.Tolerance object instance that is for example
|
||||
* AbsoluteTolerance or PercentageTolerance. E.g. setTolerance(new PIDController.AbsoluteTolerance(0.1))
|
||||
*/
|
||||
public void setPercentTolerance(double p) {
|
||||
controller.setPercentTolerance(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the error is within the percentage of the total input range,
|
||||
* determined by setTolerance. This assumes that the maximum and minimum input
|
||||
* were set using setInput.
|
||||
* @return true if the error is less than the tolerance
|
||||
*/
|
||||
public boolean onTarget() {
|
||||
return controller.onTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input for the pid loop.
|
||||
*
|
||||
* <p>It returns the input for the pid loop, so if this Subsystem was based
|
||||
* off of a gyro, then it should return the angle of the gyro</p>
|
||||
*
|
||||
* <p>All subclasses of {@link PIDSubsystem} must override this method.</p>
|
||||
*
|
||||
* @return the value the pid loop should use as input
|
||||
*/
|
||||
protected abstract double returnPIDInput();
|
||||
|
||||
/**
|
||||
* Uses the value that the pid loop calculated. The calculated value is the "output" parameter.
|
||||
* This method is a good time to set motor values, maybe something along the lines of <code>driveline.tankDrive(output, -output)</code>
|
||||
*
|
||||
* <p>All subclasses of {@link PIDSubsystem} must override this method.</p>
|
||||
*
|
||||
* @param output the value the pid loop calculated
|
||||
*/
|
||||
protected abstract void usePIDOutput(double output);
|
||||
|
||||
/**
|
||||
* Enables the internal {@link PIDController}
|
||||
*/
|
||||
public void enable() {
|
||||
controller.enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the internal {@link PIDController}
|
||||
*/
|
||||
public void disable() {
|
||||
controller.disable();
|
||||
}
|
||||
|
||||
public String getSmartDashboardType() {
|
||||
return "PIDSubsystem";
|
||||
}
|
||||
public void initTable(ITable table) {
|
||||
controller.initTable(table);
|
||||
super.initTable(table);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
/**
|
||||
* A {@link PrintCommand} is a command which prints out a string when it is initialized, and then immediately finishes.
|
||||
* It is useful if you want a {@link CommandGroup} to print out a string when it reaches a certain point.
|
||||
*
|
||||
* @author Joe Grinstead
|
||||
*/
|
||||
public class PrintCommand extends Command {
|
||||
|
||||
/** The message to print out */
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* Instantiates a {@link PrintCommand} which will print the given message when it is run.
|
||||
* @param message the message to print
|
||||
*/
|
||||
public PrintCommand(String message) {
|
||||
super("Print(\"" + message + "\"");
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
protected void initialize() {
|
||||
System.out.println(message);
|
||||
}
|
||||
|
||||
protected void execute() {
|
||||
}
|
||||
|
||||
protected boolean isFinished() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void end() {
|
||||
}
|
||||
|
||||
protected void interrupted() {
|
||||
}
|
||||
}
|
||||
@@ -1,371 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import edu.wpi.first.wpilibj.NamedSendable;
|
||||
import edu.wpi.first.wpilibj.buttons.Trigger.ButtonScheduler;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tInstances;
|
||||
import edu.wpi.first.wpilibj.communication.FRC_NetworkCommunicationsLibrary.tResourceType;
|
||||
import edu.wpi.first.wpilibj.communication.UsageReporting;
|
||||
import edu.wpi.first.wpilibj.networktables2.type.NumberArray;
|
||||
import edu.wpi.first.wpilibj.networktables2.type.StringArray;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
|
||||
/**
|
||||
* The {@link Scheduler} is a singleton which holds the top-level running
|
||||
* commands. It is in charge of both calling the command's
|
||||
* {@link Command#run() run()} method and to make sure that there are no two
|
||||
* commands with conflicting requirements running.
|
||||
*
|
||||
* <p>It is fine if teams wish to take control of the {@link Scheduler}
|
||||
* themselves, all that needs to be done is to call
|
||||
* {@link Scheduler#getInstance() Scheduler.getInstance()}.{@link Scheduler#run() run()}
|
||||
* often to have {@link Command Commands} function correctly. However, this is
|
||||
* already done for you if you use the CommandBased Robot template.</p>
|
||||
*
|
||||
* @author Joe Grinstead
|
||||
* @see Command
|
||||
*/
|
||||
public class Scheduler implements NamedSendable {
|
||||
|
||||
/**
|
||||
* The Singleton Instance
|
||||
*/
|
||||
private static Scheduler instance;
|
||||
|
||||
/**
|
||||
* Returns the {@link Scheduler}, creating it if one does not exist.
|
||||
*
|
||||
* @return the {@link Scheduler}
|
||||
*/
|
||||
public synchronized static Scheduler getInstance() {
|
||||
return instance == null ? instance = new Scheduler() : instance;
|
||||
}
|
||||
/**
|
||||
* A hashtable of active {@link Command Commands} to their
|
||||
* {@link LinkedListElement}
|
||||
*/
|
||||
private Hashtable commandTable = new Hashtable();
|
||||
/**
|
||||
* The {@link Set} of all {@link Subsystem Subsystems}
|
||||
*/
|
||||
private Set subsystems = new Set();
|
||||
/**
|
||||
* The first {@link Command} in the list
|
||||
*/
|
||||
private LinkedListElement firstCommand;
|
||||
/**
|
||||
* The last {@link Command} in the list
|
||||
*/
|
||||
private LinkedListElement lastCommand;
|
||||
/**
|
||||
* Whether or not we are currently adding a command
|
||||
*/
|
||||
private boolean adding = false;
|
||||
/**
|
||||
* Whether or not we are currently disabled
|
||||
*/
|
||||
private boolean disabled = false;
|
||||
/**
|
||||
* A list of all {@link Command Commands} which need to be added
|
||||
*/
|
||||
private Vector additions = new Vector();
|
||||
private ITable m_table;
|
||||
/**
|
||||
* A list of all
|
||||
* {@link edu.wpi.first.wpilibj.buttons.Trigger.ButtonScheduler Buttons}. It
|
||||
* is created lazily.
|
||||
*/
|
||||
private Vector buttons;
|
||||
private boolean m_runningCommandsChanged;
|
||||
|
||||
/**
|
||||
* Instantiates a {@link Scheduler}.
|
||||
*/
|
||||
private Scheduler() {
|
||||
UsageReporting.report(tResourceType.kResourceType_Command, tInstances.kCommand_Scheduler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the command to the {@link Scheduler}. This will not add the
|
||||
* {@link Command} immediately, but will instead wait for the proper time in
|
||||
* the {@link Scheduler#run()} loop before doing so. The command returns
|
||||
* immediately and does nothing if given null.
|
||||
*
|
||||
* <p>Adding a {@link Command} to the {@link Scheduler} involves the
|
||||
* {@link Scheduler} removing any {@link Command} which has shared
|
||||
* requirements.</p>
|
||||
*
|
||||
* @param command the command to add
|
||||
*/
|
||||
public void add(Command command) {
|
||||
if (command != null) {
|
||||
additions.addElement(command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a button to the {@link Scheduler}. The {@link Scheduler} will poll
|
||||
* the button during its {@link Scheduler#run()}.
|
||||
*
|
||||
* @param button the button to add
|
||||
*/
|
||||
public void addButton(ButtonScheduler button) {
|
||||
if (buttons == null) {
|
||||
buttons = new Vector();
|
||||
}
|
||||
buttons.addElement(button);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a command immediately to the {@link Scheduler}. This should only be
|
||||
* called in the {@link Scheduler#run()} loop. Any command with conflicting
|
||||
* requirements will be removed, unless it is uninterruptable. Giving
|
||||
* <code>null</code> does nothing.
|
||||
*
|
||||
* @param command the {@link Command} to add
|
||||
*/
|
||||
private void _add(Command command) {
|
||||
if (command == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to make sure no adding during adding
|
||||
if (adding) {
|
||||
System.err.println("WARNING: Can not start command from cancel method. Ignoring:" + command);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only add if not already in
|
||||
if (!commandTable.containsKey(command)) {
|
||||
|
||||
// Check that the requirements can be had
|
||||
Enumeration requirements = command.getRequirements();
|
||||
while (requirements.hasMoreElements()) {
|
||||
Subsystem lock = (Subsystem) requirements.nextElement();
|
||||
if (lock.getCurrentCommand() != null && !lock.getCurrentCommand().isInterruptible()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Give it the requirements
|
||||
adding = true;
|
||||
requirements = command.getRequirements();
|
||||
while (requirements.hasMoreElements()) {
|
||||
Subsystem lock = (Subsystem) requirements.nextElement();
|
||||
if (lock.getCurrentCommand() != null) {
|
||||
lock.getCurrentCommand().cancel();
|
||||
remove(lock.getCurrentCommand());
|
||||
}
|
||||
lock.setCurrentCommand(command);
|
||||
}
|
||||
adding = false;
|
||||
|
||||
// Add it to the list
|
||||
LinkedListElement element = new LinkedListElement();
|
||||
element.setData(command);
|
||||
if (firstCommand == null) {
|
||||
firstCommand = lastCommand = element;
|
||||
} else {
|
||||
lastCommand.add(element);
|
||||
lastCommand = element;
|
||||
}
|
||||
commandTable.put(command, element);
|
||||
|
||||
m_runningCommandsChanged = true;
|
||||
|
||||
command.startRunning();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a single iteration of the loop. This method should be called often
|
||||
* in order to have a functioning {@link Command} system. The loop has five
|
||||
* stages:
|
||||
*
|
||||
* <ol> <li> Poll the Buttons </li> <li> Execute/Remove the Commands </li>
|
||||
* <li> Send values to SmartDashboard </li> <li> Add Commands </li> <li> Add
|
||||
* Defaults </li> </ol>
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
m_runningCommandsChanged = false;
|
||||
|
||||
if (disabled) {
|
||||
return;
|
||||
} // Don't run when disabled
|
||||
|
||||
// Get button input (going backwards preserves button priority)
|
||||
if (buttons != null) {
|
||||
for (int i = buttons.size() - 1; i >= 0; i--) {
|
||||
((ButtonScheduler) buttons.elementAt(i)).execute();
|
||||
}
|
||||
}
|
||||
// Loop through the commands
|
||||
LinkedListElement e = firstCommand;
|
||||
while (e != null) {
|
||||
Command c = e.getData();
|
||||
e = e.getNext();
|
||||
if (!c.run()) {
|
||||
remove(c);
|
||||
m_runningCommandsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the new things
|
||||
for (int i = 0; i < additions.size(); i++) {
|
||||
_add((Command) additions.elementAt(i));
|
||||
}
|
||||
additions.removeAllElements();
|
||||
|
||||
// Add in the defaults
|
||||
Enumeration locks = subsystems.getElements();
|
||||
while (locks.hasMoreElements()) {
|
||||
Subsystem lock = (Subsystem) locks.nextElement();
|
||||
if (lock.getCurrentCommand() == null) {
|
||||
_add(lock.getDefaultCommand());
|
||||
}
|
||||
lock.confirmCommand();
|
||||
}
|
||||
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link Subsystem} to this {@link Scheduler}, so that the
|
||||
* {@link Scheduler} might know if a default {@link Command} needs to be
|
||||
* run. All {@link Subsystem Subsystems} should call this.
|
||||
*
|
||||
* @param system the system
|
||||
*/
|
||||
void registerSubsystem(Subsystem system) {
|
||||
if (system != null) {
|
||||
subsystems.add(system);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the {@link Command} from the {@link Scheduler}.
|
||||
*
|
||||
* @param command the command to remove
|
||||
*/
|
||||
void remove(Command command) {
|
||||
if (command == null || !commandTable.containsKey(command)) {
|
||||
return;
|
||||
}
|
||||
LinkedListElement e = (LinkedListElement) commandTable.get(command);
|
||||
commandTable.remove(command);
|
||||
|
||||
if (e.equals(lastCommand)) {
|
||||
lastCommand = e.getPrevious();
|
||||
}
|
||||
if (e.equals(firstCommand)) {
|
||||
firstCommand = e.getNext();
|
||||
}
|
||||
e.remove();
|
||||
|
||||
Enumeration requirements = command.getRequirements();
|
||||
while (requirements.hasMoreElements()) {
|
||||
((Subsystem) requirements.nextElement()).setCurrentCommand(null);
|
||||
}
|
||||
|
||||
command.removed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all commands
|
||||
*/
|
||||
public void removeAll() {
|
||||
// TODO: Confirm that this works with "uninteruptible" commands
|
||||
while (firstCommand != null) {
|
||||
remove(firstCommand.getData());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the command scheduler.
|
||||
*/
|
||||
public void disable() {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the command scheduler.
|
||||
*/
|
||||
public void enable() {
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Scheduler";
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return "Scheduler";
|
||||
}
|
||||
private StringArray commands;
|
||||
private NumberArray ids, toCancel;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initTable(ITable subtable) {
|
||||
m_table = subtable;
|
||||
commands = new StringArray();
|
||||
ids = new NumberArray();
|
||||
toCancel = new NumberArray();
|
||||
|
||||
m_table.putValue("Names", commands);
|
||||
m_table.putValue("Ids", ids);
|
||||
m_table.putValue("Cancel", toCancel);
|
||||
}
|
||||
|
||||
private void updateTable() {
|
||||
if (m_table != null) {
|
||||
// Get the commands to cancel
|
||||
m_table.retrieveValue("Cancel", toCancel);
|
||||
if (toCancel.size() > 0) {
|
||||
for (LinkedListElement e = firstCommand; e != null; e = e.getNext()) {
|
||||
for (int i = 0; i < toCancel.size(); i++) {
|
||||
if (e.getData().hashCode() == toCancel.get(i)) {
|
||||
e.getData().cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
toCancel.setSize(0);
|
||||
m_table.putValue("Cancel", toCancel);
|
||||
}
|
||||
|
||||
if (m_runningCommandsChanged) {
|
||||
commands.setSize(0);
|
||||
ids.setSize(0);
|
||||
// Set the the running commands
|
||||
for (LinkedListElement e = firstCommand; e != null; e = e.getNext()) {
|
||||
commands.add(e.getData().getName());
|
||||
ids.add(e.getData().hashCode());
|
||||
}
|
||||
m_table.putValue("Names", commands);
|
||||
m_table.putValue("Ids", ids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return m_table;
|
||||
}
|
||||
|
||||
public String getSmartDashboardType() {
|
||||
return "Scheduler";
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Greg
|
||||
*/
|
||||
class Set {
|
||||
Vector set = new Vector();
|
||||
|
||||
public Set() {
|
||||
}
|
||||
|
||||
public void add(Object o) {
|
||||
if(set.contains(o)) return;
|
||||
set.addElement(o);
|
||||
}
|
||||
|
||||
public void add(Set s) {
|
||||
Enumeration stuff = s.getElements();
|
||||
for(Enumeration e = stuff; e.hasMoreElements();) {
|
||||
add(e.nextElement());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return set.contains(o);
|
||||
}
|
||||
|
||||
public Enumeration getElements() {
|
||||
return set.elements();
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
/**
|
||||
* A {@link StartCommand} will call the {@link Command#start() start()} method of another command when it is initialized
|
||||
* and will finish immediately.
|
||||
*
|
||||
* @author Joe Grinstead
|
||||
*/
|
||||
public class StartCommand extends Command {
|
||||
|
||||
/** The command to fork */
|
||||
private Command m_commandToFork;
|
||||
|
||||
/**
|
||||
* Instantiates a {@link StartCommand} which will start the
|
||||
* given command whenever its {@link Command#initialize() initialize()} is called.
|
||||
* @param commandToStart the {@link Command} to start
|
||||
*/
|
||||
public StartCommand(Command commandToStart) {
|
||||
super("Start(" + commandToStart + ")");
|
||||
m_commandToFork = commandToStart;
|
||||
}
|
||||
|
||||
protected void initialize() {
|
||||
m_commandToFork.start();
|
||||
}
|
||||
|
||||
protected void execute() {
|
||||
}
|
||||
|
||||
protected boolean isFinished() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void end() {
|
||||
}
|
||||
|
||||
protected void interrupted() {
|
||||
}
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
import edu.wpi.first.wpilibj.NamedSendable;
|
||||
import edu.wpi.first.wpilibj.tables.ITable;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* This class defines a major component of the robot.
|
||||
*
|
||||
* <p>A good example of a subsystem is the driveline, or a claw if the robot has one.</p>
|
||||
*
|
||||
* <p>All motors should be a part of a subsystem. For instance, all the wheel motors should be
|
||||
* a part of some kind of "Driveline" subsystem.</p>
|
||||
*
|
||||
* <p>Subsystems are used within the command system as requirements for {@link Command}.
|
||||
* Only one command which requires a subsystem can run at a time. Also, subsystems
|
||||
* can have default commands which are started if there is no command running which
|
||||
* requires this subsystem.</p>
|
||||
*
|
||||
* @author Joe Grinstead
|
||||
* @see Command
|
||||
*/
|
||||
public abstract class Subsystem implements NamedSendable {
|
||||
|
||||
/** Whether or not getDefaultCommand() was called */
|
||||
private boolean initializedDefaultCommand = false;
|
||||
/** The current command */
|
||||
private Command currentCommand;
|
||||
private boolean currentCommandChanged;
|
||||
|
||||
/** The default command */
|
||||
private Command defaultCommand;
|
||||
/** The name */
|
||||
private String name;
|
||||
/** List of all subsystems created */
|
||||
private static Vector allSubsystems = new Vector();
|
||||
|
||||
/**
|
||||
* Creates a subsystem with the given name
|
||||
* @param name the name of the subsystem
|
||||
*/
|
||||
public Subsystem(String name) {
|
||||
this.name = name;
|
||||
Scheduler.getInstance().registerSubsystem(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a subsystem. This will set the name to the name of the class.
|
||||
*/
|
||||
public Subsystem() {
|
||||
this.name = getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1);
|
||||
Scheduler.getInstance().registerSubsystem(this);
|
||||
currentCommandChanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the default command for a subsystem
|
||||
* By default subsystems have no default command, but if they do, the default command is set
|
||||
* with this method. It is called on all Subsystems by CommandBase in the users program after
|
||||
* all the Subsystems are created.
|
||||
*/
|
||||
protected abstract void initDefaultCommand();
|
||||
|
||||
/**
|
||||
* Sets the default command. If this is not called or is called with null,
|
||||
* then there will be no default command for the subsystem.
|
||||
*
|
||||
* <p><b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the subsystem is a
|
||||
* singleton.</p>
|
||||
*
|
||||
* @param command the default command (or null if there should be none)
|
||||
* @throws IllegalUseOfCommandException if the command does not require the subsystem
|
||||
*/
|
||||
protected void setDefaultCommand(Command command) {
|
||||
if (command == null) {
|
||||
defaultCommand = null;
|
||||
} else {
|
||||
boolean found = false;
|
||||
Enumeration requirements = command.getRequirements();
|
||||
while (requirements.hasMoreElements()) {
|
||||
if (requirements.nextElement().equals(this)) {
|
||||
found = true;
|
||||
// } else {
|
||||
// throw new IllegalUseOfCommandException("A default command cannot require multiple subsystems");
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
throw new IllegalUseOfCommandException("A default command must require the subsystem");
|
||||
}
|
||||
defaultCommand = command;
|
||||
}
|
||||
if (table != null) {
|
||||
if (defaultCommand != null) {
|
||||
table.putBoolean("hasDefault", true);
|
||||
table.putString("default", defaultCommand.getName());
|
||||
} else {
|
||||
table.putBoolean("hasDefault", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default command (or null if there is none).
|
||||
* @return the default command
|
||||
*/
|
||||
protected Command getDefaultCommand() {
|
||||
if (!initializedDefaultCommand) {
|
||||
initializedDefaultCommand = true;
|
||||
initDefaultCommand();
|
||||
}
|
||||
return defaultCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current command
|
||||
* @param command the new current command
|
||||
*/
|
||||
void setCurrentCommand(Command command) {
|
||||
currentCommand = command;
|
||||
currentCommandChanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this to alert Subsystem that the current command is actually the command.
|
||||
* Sometimes, the {@link Subsystem} is told that it has no command while the {@link Scheduler}
|
||||
* is going through the loop, only to be soon after given a new one. This will avoid that situation.
|
||||
*/
|
||||
void confirmCommand() {
|
||||
if (currentCommandChanged) {
|
||||
if (table != null) {
|
||||
if (currentCommand != null) {
|
||||
table.putBoolean("hasCommand", true);
|
||||
table.putString("command", currentCommand.getName());
|
||||
} else {
|
||||
table.putBoolean("hasCommand", false);
|
||||
}
|
||||
}
|
||||
currentCommandChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the command which currently claims this subsystem.
|
||||
* @return the command which currently claims this subsystem
|
||||
*/
|
||||
public Command getCurrentCommand() {
|
||||
return currentCommand;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this subsystem, which is by default the class name.
|
||||
* @return the name of this subsystem
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSmartDashboardType() {
|
||||
return "Subsystem";
|
||||
}
|
||||
private ITable table;
|
||||
public void initTable(ITable table) {
|
||||
this.table = table;
|
||||
if(table!=null) {
|
||||
if (defaultCommand != null) {
|
||||
table.putBoolean("hasDefault", true);
|
||||
table.putString("default", defaultCommand.getName());
|
||||
} else {
|
||||
table.putBoolean("hasDefault", false);
|
||||
}
|
||||
if (currentCommand != null) {
|
||||
table.putBoolean("hasCommand", true);
|
||||
table.putString("command", currentCommand.getName());
|
||||
} else {
|
||||
table.putBoolean("hasCommand", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public ITable getTable() {
|
||||
return table;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
/**
|
||||
* A {@link WaitCommand} will wait for a certain amount of time before finishing.
|
||||
* It is useful if you want a {@link CommandGroup} to pause for a moment.
|
||||
* @author Joe Grinstead
|
||||
* @see CommandGroup
|
||||
*/
|
||||
public class WaitCommand extends Command {
|
||||
|
||||
/**
|
||||
* Instantiates a {@link WaitCommand} with the given timeout.
|
||||
* @param timeout the time the command takes to run
|
||||
*/
|
||||
public WaitCommand(double timeout) {
|
||||
this("Wait(" + timeout + ")", timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a {@link WaitCommand} with the given timeout.
|
||||
* @param name the name of the command
|
||||
* @param timeout the time the command takes to run
|
||||
*/
|
||||
public WaitCommand(String name, double timeout) {
|
||||
super(name, timeout);
|
||||
}
|
||||
|
||||
protected void initialize() {
|
||||
}
|
||||
|
||||
protected void execute() {
|
||||
}
|
||||
|
||||
protected boolean isFinished() {
|
||||
return isTimedOut();
|
||||
}
|
||||
|
||||
protected void end() {
|
||||
}
|
||||
|
||||
protected void interrupted() {
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
/**
|
||||
* This command will only finish if whatever {@link CommandGroup} it is in has no active children.
|
||||
* If it is not a part of a {@link CommandGroup}, then it will finish immediately. If it is itself an
|
||||
* active child, then the {@link CommandGroup} will never end.
|
||||
*
|
||||
* <p>This class is useful for the situation where you want to allow anything running in parallel to finish, before continuing
|
||||
* in the main {@link CommandGroup} sequence.</p>
|
||||
* @author Joe Grinstead
|
||||
*/
|
||||
public class WaitForChildren extends Command {
|
||||
|
||||
protected void initialize() {
|
||||
}
|
||||
|
||||
protected void execute() {
|
||||
}
|
||||
|
||||
protected void end() {
|
||||
}
|
||||
|
||||
protected void interrupted() {
|
||||
}
|
||||
|
||||
protected boolean isFinished() {
|
||||
return getGroup() == null || getGroup().m_children.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) FIRST 2008-2012. 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.command;
|
||||
|
||||
import edu.wpi.first.wpilibj.DriverStation;
|
||||
|
||||
/**
|
||||
* WaitUntilCommand - waits until an absolute game time.
|
||||
* This will wait until the game clock reaches some value, then continue to the next command.
|
||||
* @author brad
|
||||
*
|
||||
*/
|
||||
public class WaitUntilCommand extends Command {
|
||||
|
||||
private double m_time;
|
||||
|
||||
public WaitUntilCommand(double time) {
|
||||
super("WaitUntil(" + time + ")");
|
||||
m_time = time;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we've reached the actual finish time.
|
||||
*/
|
||||
public boolean isFinished() {
|
||||
return DriverStation.getInstance().getMatchTime() >= m_time;
|
||||
}
|
||||
|
||||
public void end() {
|
||||
}
|
||||
|
||||
public void interrupted() {
|
||||
}
|
||||
}
|
||||
@@ -1,378 +0,0 @@
|
||||
package edu.wpi.first.wpilibj.communication;
|
||||
import com.ochafik.lang.jnaerator.runtime.Structure;
|
||||
import com.ochafik.lang.jnaerator.runtime.Union;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
/**
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:29</i><br>
|
||||
* This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br>
|
||||
* a tool written by <a href="http://ochafik.com/">Olivier Chafik</a> that <a href="http://code.google.com/p/jnaerator/wiki/CreditsAndLicense">uses a few opensource projects.</a>.<br>
|
||||
* For help, please visit <a href="http://nativelibs4java.googlecode.com/">NativeLibs4Java</a> , <a href="http://rococoa.dev.java.net/">Rococoa</a>, or <a href="http://jna.dev.java.net/">JNA</a>.
|
||||
*/
|
||||
public class FRCCommonControlData extends Structure<FRCCommonControlData, FRCCommonControlData.ByValue, FRCCommonControlData.ByReference > {
|
||||
public short packetIndex;
|
||||
/** C type : field1_union */
|
||||
public field1_union field1;
|
||||
public byte dsDigitalIn;
|
||||
public short teamID;
|
||||
public byte dsID_Alliance;
|
||||
public byte dsID_Position;
|
||||
/** C type : field2_union */
|
||||
public field2_union field2;
|
||||
/** Left-most 4 bits are unused */
|
||||
public short stick0Buttons;
|
||||
/** C type : field3_union */
|
||||
public field3_union field3;
|
||||
/** Left-most 4 bits are unused */
|
||||
public short stick1Buttons;
|
||||
/** C type : field4_union */
|
||||
public field4_union field4;
|
||||
/** Left-most 4 bits are unused */
|
||||
public short stick2Buttons;
|
||||
/** C type : field5_union */
|
||||
public field5_union field5;
|
||||
/** Left-most 4 bits are unused */
|
||||
public short stick3Buttons;
|
||||
/** Analog inputs are 10 bit right-justified */
|
||||
public short analog1;
|
||||
public short analog2;
|
||||
public short analog3;
|
||||
public short analog4;
|
||||
public long cRIOChecksum;
|
||||
public int FPGAChecksum0;
|
||||
public int FPGAChecksum1;
|
||||
public int FPGAChecksum2;
|
||||
public int FPGAChecksum3;
|
||||
/** C type : char[8] */
|
||||
public byte[] versionData = new byte[8];
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:31</i> */
|
||||
public static class field1_union extends Union<field1_union, field1_union.ByValue, field1_union.ByReference > {
|
||||
public byte control;
|
||||
public field1_union() {
|
||||
super();
|
||||
}
|
||||
public field1_union(byte control) {
|
||||
super();
|
||||
this.control = control;
|
||||
setType(Byte.TYPE);
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected field1_union newInstance() { return new field1_union(); }
|
||||
public static field1_union[] newArray(int arrayLength) {
|
||||
return Union.newArray(field1_union.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends field1_union implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends field1_union implements Structure.ByValue {
|
||||
|
||||
};
|
||||
};
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:63</i> */
|
||||
public static class field2_union extends Union<field2_union, field2_union.ByValue, field2_union.ByReference > {
|
||||
/** C type : int8_t[6] */
|
||||
public byte[] stick0Axes = new byte[6];
|
||||
/** C type : field1_struct */
|
||||
public field1_struct field1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:65</i> */
|
||||
public static class field1_struct extends Structure<field1_struct, field1_struct.ByValue, field1_struct.ByReference > {
|
||||
public byte stick0Axis1;
|
||||
public byte stick0Axis2;
|
||||
public byte stick0Axis3;
|
||||
public byte stick0Axis4;
|
||||
public byte stick0Axis5;
|
||||
public byte stick0Axis6;
|
||||
public field1_struct() {
|
||||
super();
|
||||
}
|
||||
protected List<? > getFieldOrder() {
|
||||
return Arrays.asList("stick0Axis1", "stick0Axis2", "stick0Axis3", "stick0Axis4", "stick0Axis5", "stick0Axis6");
|
||||
}
|
||||
public field1_struct(byte stick0Axis1, byte stick0Axis2, byte stick0Axis3, byte stick0Axis4, byte stick0Axis5, byte stick0Axis6) {
|
||||
super();
|
||||
this.stick0Axis1 = stick0Axis1;
|
||||
this.stick0Axis2 = stick0Axis2;
|
||||
this.stick0Axis3 = stick0Axis3;
|
||||
this.stick0Axis4 = stick0Axis4;
|
||||
this.stick0Axis5 = stick0Axis5;
|
||||
this.stick0Axis6 = stick0Axis6;
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected field1_struct newInstance() { return new field1_struct(); }
|
||||
public static field1_struct[] newArray(int arrayLength) {
|
||||
return Structure.newArray(field1_struct.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends field1_struct implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends field1_struct implements Structure.ByValue {
|
||||
|
||||
};
|
||||
};
|
||||
public field2_union() {
|
||||
super();
|
||||
}
|
||||
/** @param field1 C type : field1_struct */
|
||||
public field2_union(field1_struct field1) {
|
||||
super();
|
||||
this.field1 = field1;
|
||||
setType(field1_struct.class);
|
||||
}
|
||||
/** @param stick0Axes C type : int8_t[6] */
|
||||
public field2_union(byte stick0Axes[]) {
|
||||
super();
|
||||
if ((stick0Axes.length != this.stick0Axes.length))
|
||||
throw new IllegalArgumentException("Wrong array size !");
|
||||
this.stick0Axes = stick0Axes;
|
||||
setType(byte[].class);
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected field2_union newInstance() { return new field2_union(); }
|
||||
public static field2_union[] newArray(int arrayLength) {
|
||||
return Union.newArray(field2_union.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends field2_union implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends field2_union implements Structure.ByValue {
|
||||
|
||||
};
|
||||
};
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:76</i> */
|
||||
public static class field3_union extends Union<field3_union, field3_union.ByValue, field3_union.ByReference > {
|
||||
/** C type : int8_t[6] */
|
||||
public byte[] stick1Axes = new byte[6];
|
||||
/** C type : field1_struct */
|
||||
public field1_struct field1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:78</i> */
|
||||
public static class field1_struct extends Structure<field1_struct, field1_struct.ByValue, field1_struct.ByReference > {
|
||||
public byte stick1Axis1;
|
||||
public byte stick1Axis2;
|
||||
public byte stick1Axis3;
|
||||
public byte stick1Axis4;
|
||||
public byte stick1Axis5;
|
||||
public byte stick1Axis6;
|
||||
public field1_struct() {
|
||||
super();
|
||||
}
|
||||
protected List<? > getFieldOrder() {
|
||||
return Arrays.asList("stick1Axis1", "stick1Axis2", "stick1Axis3", "stick1Axis4", "stick1Axis5", "stick1Axis6");
|
||||
}
|
||||
public field1_struct(byte stick1Axis1, byte stick1Axis2, byte stick1Axis3, byte stick1Axis4, byte stick1Axis5, byte stick1Axis6) {
|
||||
super();
|
||||
this.stick1Axis1 = stick1Axis1;
|
||||
this.stick1Axis2 = stick1Axis2;
|
||||
this.stick1Axis3 = stick1Axis3;
|
||||
this.stick1Axis4 = stick1Axis4;
|
||||
this.stick1Axis5 = stick1Axis5;
|
||||
this.stick1Axis6 = stick1Axis6;
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected field1_struct newInstance() { return new field1_struct(); }
|
||||
public static field1_struct[] newArray(int arrayLength) {
|
||||
return Structure.newArray(field1_struct.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends field1_struct implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends field1_struct implements Structure.ByValue {
|
||||
|
||||
};
|
||||
};
|
||||
public field3_union() {
|
||||
super();
|
||||
}
|
||||
/** @param field1 C type : field1_struct */
|
||||
public field3_union(field1_struct field1) {
|
||||
super();
|
||||
this.field1 = field1;
|
||||
setType(field1_struct.class);
|
||||
}
|
||||
/** @param stick1Axes C type : int8_t[6] */
|
||||
public field3_union(byte stick1Axes[]) {
|
||||
super();
|
||||
if ((stick1Axes.length != this.stick1Axes.length))
|
||||
throw new IllegalArgumentException("Wrong array size !");
|
||||
this.stick1Axes = stick1Axes;
|
||||
setType(byte[].class);
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected field3_union newInstance() { return new field3_union(); }
|
||||
public static field3_union[] newArray(int arrayLength) {
|
||||
return Union.newArray(field3_union.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends field3_union implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends field3_union implements Structure.ByValue {
|
||||
|
||||
};
|
||||
};
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:89</i> */
|
||||
public static class field4_union extends Union<field4_union, field4_union.ByValue, field4_union.ByReference > {
|
||||
/** C type : int8_t[6] */
|
||||
public byte[] stick2Axes = new byte[6];
|
||||
/** C type : field1_struct */
|
||||
public field1_struct field1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:91</i> */
|
||||
public static class field1_struct extends Structure<field1_struct, field1_struct.ByValue, field1_struct.ByReference > {
|
||||
public byte stick2Axis1;
|
||||
public byte stick2Axis2;
|
||||
public byte stick2Axis3;
|
||||
public byte stick2Axis4;
|
||||
public byte stick2Axis5;
|
||||
public byte stick2Axis6;
|
||||
public field1_struct() {
|
||||
super();
|
||||
}
|
||||
protected List<? > getFieldOrder() {
|
||||
return Arrays.asList("stick2Axis1", "stick2Axis2", "stick2Axis3", "stick2Axis4", "stick2Axis5", "stick2Axis6");
|
||||
}
|
||||
public field1_struct(byte stick2Axis1, byte stick2Axis2, byte stick2Axis3, byte stick2Axis4, byte stick2Axis5, byte stick2Axis6) {
|
||||
super();
|
||||
this.stick2Axis1 = stick2Axis1;
|
||||
this.stick2Axis2 = stick2Axis2;
|
||||
this.stick2Axis3 = stick2Axis3;
|
||||
this.stick2Axis4 = stick2Axis4;
|
||||
this.stick2Axis5 = stick2Axis5;
|
||||
this.stick2Axis6 = stick2Axis6;
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected field1_struct newInstance() { return new field1_struct(); }
|
||||
public static field1_struct[] newArray(int arrayLength) {
|
||||
return Structure.newArray(field1_struct.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends field1_struct implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends field1_struct implements Structure.ByValue {
|
||||
|
||||
};
|
||||
};
|
||||
public field4_union() {
|
||||
super();
|
||||
}
|
||||
/** @param field1 C type : field1_struct */
|
||||
public field4_union(field1_struct field1) {
|
||||
super();
|
||||
this.field1 = field1;
|
||||
setType(field1_struct.class);
|
||||
}
|
||||
/** @param stick2Axes C type : int8_t[6] */
|
||||
public field4_union(byte stick2Axes[]) {
|
||||
super();
|
||||
if ((stick2Axes.length != this.stick2Axes.length))
|
||||
throw new IllegalArgumentException("Wrong array size !");
|
||||
this.stick2Axes = stick2Axes;
|
||||
setType(byte[].class);
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected field4_union newInstance() { return new field4_union(); }
|
||||
public static field4_union[] newArray(int arrayLength) {
|
||||
return Union.newArray(field4_union.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends field4_union implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends field4_union implements Structure.ByValue {
|
||||
|
||||
};
|
||||
};
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:102</i> */
|
||||
public static class field5_union extends Union<field5_union, field5_union.ByValue, field5_union.ByReference > {
|
||||
/** C type : int8_t[6] */
|
||||
public byte[] stick3Axes = new byte[6];
|
||||
/** C type : field1_struct */
|
||||
public field1_struct field1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:104</i> */
|
||||
public static class field1_struct extends Structure<field1_struct, field1_struct.ByValue, field1_struct.ByReference > {
|
||||
public byte stick3Axis1;
|
||||
public byte stick3Axis2;
|
||||
public byte stick3Axis3;
|
||||
public byte stick3Axis4;
|
||||
public byte stick3Axis5;
|
||||
public byte stick3Axis6;
|
||||
public field1_struct() {
|
||||
super();
|
||||
}
|
||||
protected List<? > getFieldOrder() {
|
||||
return Arrays.asList("stick3Axis1", "stick3Axis2", "stick3Axis3", "stick3Axis4", "stick3Axis5", "stick3Axis6");
|
||||
}
|
||||
public field1_struct(byte stick3Axis1, byte stick3Axis2, byte stick3Axis3, byte stick3Axis4, byte stick3Axis5, byte stick3Axis6) {
|
||||
super();
|
||||
this.stick3Axis1 = stick3Axis1;
|
||||
this.stick3Axis2 = stick3Axis2;
|
||||
this.stick3Axis3 = stick3Axis3;
|
||||
this.stick3Axis4 = stick3Axis4;
|
||||
this.stick3Axis5 = stick3Axis5;
|
||||
this.stick3Axis6 = stick3Axis6;
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected field1_struct newInstance() { return new field1_struct(); }
|
||||
public static field1_struct[] newArray(int arrayLength) {
|
||||
return Structure.newArray(field1_struct.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends field1_struct implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends field1_struct implements Structure.ByValue {
|
||||
|
||||
};
|
||||
};
|
||||
public field5_union() {
|
||||
super();
|
||||
}
|
||||
/** @param field1 C type : field1_struct */
|
||||
public field5_union(field1_struct field1) {
|
||||
super();
|
||||
this.field1 = field1;
|
||||
setType(field1_struct.class);
|
||||
}
|
||||
/** @param stick3Axes C type : int8_t[6] */
|
||||
public field5_union(byte stick3Axes[]) {
|
||||
super();
|
||||
if ((stick3Axes.length != this.stick3Axes.length))
|
||||
throw new IllegalArgumentException("Wrong array size !");
|
||||
this.stick3Axes = stick3Axes;
|
||||
setType(byte[].class);
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected field5_union newInstance() { return new field5_union(); }
|
||||
public static field5_union[] newArray(int arrayLength) {
|
||||
return Union.newArray(field5_union.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends field5_union implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends field5_union implements Structure.ByValue {
|
||||
|
||||
};
|
||||
};
|
||||
public FRCCommonControlData() {
|
||||
super();
|
||||
}
|
||||
protected List<? > getFieldOrder() {
|
||||
return Arrays.asList("packetIndex", "field1", "dsDigitalIn", "teamID", "dsID_Alliance", "dsID_Position", "field2", "stick0Buttons", "field3", "stick1Buttons", "field4", "stick2Buttons", "field5", "stick3Buttons", "analog1", "analog2", "analog3", "analog4", "cRIOChecksum", "FPGAChecksum0", "FPGAChecksum1", "FPGAChecksum2", "FPGAChecksum3", "versionData");
|
||||
}
|
||||
protected ByReference newByReference() { return new ByReference(); }
|
||||
protected ByValue newByValue() { return new ByValue(); }
|
||||
protected FRCCommonControlData newInstance() { return new FRCCommonControlData(); }
|
||||
public static FRCCommonControlData[] newArray(int arrayLength) {
|
||||
return Structure.newArray(FRCCommonControlData.class, arrayLength);
|
||||
}
|
||||
public static class ByReference extends FRCCommonControlData implements Structure.ByReference {
|
||||
|
||||
};
|
||||
public static class ByValue extends FRCCommonControlData implements Structure.ByValue {
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package edu.wpi.first.wpilibj.communication;
|
||||
|
||||
public class FRCCommonControlMasks {
|
||||
// XXX: Verify these are right in FRCCommonControlData.field1
|
||||
public static byte CHECK_VERSIONS = 1 << 0;
|
||||
public static byte TEST = 1 << 1;
|
||||
public static byte RESYNC = 1 << 2;
|
||||
public static byte FMS_ATTATCHED = 1 << 3;
|
||||
public static byte AUTONOMOUS = 1 << 4;
|
||||
public static byte ENABLED = 1 << 5;
|
||||
public static byte NOT_ESTOP = 1 << 6;
|
||||
public static byte RESET = (byte) (1 << 7);
|
||||
}
|
||||
@@ -1,489 +0,0 @@
|
||||
package edu.wpi.first.wpilibj.communication;
|
||||
import com.ochafik.lang.jnaerator.runtime.LibraryExtractor;
|
||||
import com.ochafik.lang.jnaerator.runtime.MangledFunctionMapper;
|
||||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
import com.sun.jna.NativeLibrary;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.PointerType;
|
||||
import com.sun.jna.ptr.IntByReference;
|
||||
import com.sun.jna.ptr.ShortByReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
/**
|
||||
* JNA Wrapper for library <b>FRC_NetworkCommunications</b><br>
|
||||
* This file was autogenerated by <a href="http://jnaerator.googlecode.com/">JNAerator</a>,<br>
|
||||
* a tool written by <a href="http://ochafik.com/">Olivier Chafik</a> that <a href="http://code.google.com/p/jnaerator/wiki/CreditsAndLicense">uses a few opensource projects.</a>.<br>
|
||||
* For help, please visit <a href="http://nativelibs4java.googlecode.com/">NativeLibs4Java</a> , <a href="http://rococoa.dev.java.net/">Rococoa</a>, or <a href="http://jna.dev.java.net/">JNA</a>.
|
||||
*/
|
||||
public class FRC_NetworkCommunicationsLibrary implements Library {
|
||||
public static final String JNA_LIBRARY_NAME = LibraryExtractor.getLibraryPath("FRC_NetworkCommunication", true, FRC_NetworkCommunicationsLibrary.class);
|
||||
public static final NativeLibrary JNA_NATIVE_LIB = NativeLibrary.getInstance(FRC_NetworkCommunicationsLibrary.JNA_LIBRARY_NAME, MangledFunctionMapper.DEFAULT_OPTIONS);
|
||||
static {
|
||||
Native.register(FRC_NetworkCommunicationsLibrary.JNA_LIBRARY_NAME);
|
||||
}
|
||||
/**
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h</i><br>
|
||||
* enum values
|
||||
*/
|
||||
public static interface tModuleType {
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:8</i> */
|
||||
public static final int kModuleType_Unknown = 0x00;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:9</i> */
|
||||
public static final int kModuleType_Analog = 0x01;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:10</i> */
|
||||
public static final int kModuleType_Digital = 0x02;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:11</i> */
|
||||
public static final int kModuleType_Solenoid = 0x03;
|
||||
};
|
||||
/**
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h</i><br>
|
||||
* enum values
|
||||
*/
|
||||
public static interface tTargetClass {
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:15</i> */
|
||||
public static final int kTargetClass_Unknown = 0x00;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:16</i> */
|
||||
public static final int kTargetClass_FRC1 = 0x10;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:17</i> */
|
||||
public static final int kTargetClass_FRC2 = 0x20;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:18</i> */
|
||||
public static final int kTargetClass_FRC2_Analog = (int)FRC_NetworkCommunicationsLibrary.tTargetClass.kTargetClass_FRC2 | (int)FRC_NetworkCommunicationsLibrary.tModuleType.kModuleType_Analog;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:19</i> */
|
||||
public static final int kTargetClass_FRC2_Digital = (int)FRC_NetworkCommunicationsLibrary.tTargetClass.kTargetClass_FRC2 | (int)FRC_NetworkCommunicationsLibrary.tModuleType.kModuleType_Digital;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:20</i> */
|
||||
public static final int kTargetClass_FRC2_Solenoid = (int)FRC_NetworkCommunicationsLibrary.tTargetClass.kTargetClass_FRC2 | (int)FRC_NetworkCommunicationsLibrary.tModuleType.kModuleType_Solenoid;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:21</i> */
|
||||
public static final int kTargetClass_FamilyMask = 0xF0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:22</i> */
|
||||
public static final int kTargetClass_ModuleMask = 0x0F;
|
||||
};
|
||||
/**
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h</i><br>
|
||||
* enum values
|
||||
*/
|
||||
public static interface tResourceType {
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:8</i> */
|
||||
public static final int kResourceType_Controller = 0;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:9</i> */
|
||||
public static final int kResourceType_Module = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:10</i> */
|
||||
public static final int kResourceType_Language = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:11</i> */
|
||||
public static final int kResourceType_CANPlugin = 3;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:12</i> */
|
||||
public static final int kResourceType_Accelerometer = 4;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:13</i> */
|
||||
public static final int kResourceType_ADXL345 = 5;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:14</i> */
|
||||
public static final int kResourceType_AnalogChannel = 6;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:15</i> */
|
||||
public static final int kResourceType_AnalogTrigger = 7;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:16</i> */
|
||||
public static final int kResourceType_AnalogTriggerOutput = 8;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:17</i> */
|
||||
public static final int kResourceType_CANJaguar = 9;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:18</i> */
|
||||
public static final int kResourceType_Compressor = 10;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:19</i> */
|
||||
public static final int kResourceType_Counter = 11;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:20</i> */
|
||||
public static final int kResourceType_Dashboard = 12;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:21</i> */
|
||||
public static final int kResourceType_DigitalInput = 13;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:22</i> */
|
||||
public static final int kResourceType_DigitalOutput = 14;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:23</i> */
|
||||
public static final int kResourceType_DriverStationCIO = 15;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:24</i> */
|
||||
public static final int kResourceType_DriverStationEIO = 16;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:25</i> */
|
||||
public static final int kResourceType_DriverStationLCD = 17;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:26</i> */
|
||||
public static final int kResourceType_Encoder = 18;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:27</i> */
|
||||
public static final int kResourceType_GearTooth = 19;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:28</i> */
|
||||
public static final int kResourceType_Gyro = 20;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:29</i> */
|
||||
public static final int kResourceType_I2C = 21;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:30</i> */
|
||||
public static final int kResourceType_Framework = 22;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:31</i> */
|
||||
public static final int kResourceType_Jaguar = 23;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:32</i> */
|
||||
public static final int kResourceType_Joystick = 24;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:33</i> */
|
||||
public static final int kResourceType_Kinect = 25;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:34</i> */
|
||||
public static final int kResourceType_KinectStick = 26;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:35</i> */
|
||||
public static final int kResourceType_PIDController = 27;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:36</i> */
|
||||
public static final int kResourceType_Preferences = 28;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:37</i> */
|
||||
public static final int kResourceType_PWM = 29;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:38</i> */
|
||||
public static final int kResourceType_Relay = 30;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:39</i> */
|
||||
public static final int kResourceType_RobotDrive = 31;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:40</i> */
|
||||
public static final int kResourceType_SerialPort = 32;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:41</i> */
|
||||
public static final int kResourceType_Servo = 33;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:42</i> */
|
||||
public static final int kResourceType_Solenoid = 34;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:43</i> */
|
||||
public static final int kResourceType_SPI = 35;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:44</i> */
|
||||
public static final int kResourceType_Task = 36;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:45</i> */
|
||||
public static final int kResourceType_Ultrasonic = 37;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:46</i> */
|
||||
public static final int kResourceType_Victor = 38;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:47</i> */
|
||||
public static final int kResourceType_Button = 39;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:48</i> */
|
||||
public static final int kResourceType_Command = 40;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:49</i> */
|
||||
public static final int kResourceType_AxisCamera = 41;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:50</i> */
|
||||
public static final int kResourceType_PCVideoServer = 42;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:51</i> */
|
||||
public static final int kResourceType_SmartDashboard = 43;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:52</i> */
|
||||
public static final int kResourceType_Talon = 44;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:53</i> */
|
||||
public static final int kResourceType_HiTechnicColorSensor = 45;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:54</i> */
|
||||
public static final int kResourceType_HiTechnicAccel = 46;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:55</i> */
|
||||
public static final int kResourceType_HiTechnicCompass = 47;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:56</i> */
|
||||
public static final int kResourceType_SRF08 = 48;
|
||||
};
|
||||
/**
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h</i><br>
|
||||
* enum values
|
||||
*/
|
||||
public static interface tInstances {
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:60</i> */
|
||||
public static final int kLanguage_LabVIEW = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:61</i> */
|
||||
public static final int kLanguage_CPlusPlus = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:62</i> */
|
||||
public static final int kLanguage_Java = 3;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:63</i> */
|
||||
public static final int kLanguage_Python = 4;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:65</i> */
|
||||
public static final int kCANPlugin_BlackJagBridge = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:66</i> */
|
||||
public static final int kCANPlugin_2CAN = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:68</i> */
|
||||
public static final int kFramework_Iterative = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:69</i> */
|
||||
public static final int kFramework_Simple = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:71</i> */
|
||||
public static final int kRobotDrive_ArcadeStandard = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:72</i> */
|
||||
public static final int kRobotDrive_ArcadeButtonSpin = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:73</i> */
|
||||
public static final int kRobotDrive_ArcadeRatioCurve = 3;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:74</i> */
|
||||
public static final int kRobotDrive_Tank = 4;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:75</i> */
|
||||
public static final int kRobotDrive_MecanumPolar = 5;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:76</i> */
|
||||
public static final int kRobotDrive_MecanumCartesian = 6;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:78</i> */
|
||||
public static final int kDriverStationCIO_Analog = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:79</i> */
|
||||
public static final int kDriverStationCIO_DigitalIn = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:80</i> */
|
||||
public static final int kDriverStationCIO_DigitalOut = 3;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:82</i> */
|
||||
public static final int kDriverStationEIO_Acceleration = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:83</i> */
|
||||
public static final int kDriverStationEIO_AnalogIn = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:84</i> */
|
||||
public static final int kDriverStationEIO_AnalogOut = 3;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:85</i> */
|
||||
public static final int kDriverStationEIO_Button = 4;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:86</i> */
|
||||
public static final int kDriverStationEIO_LED = 5;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:87</i> */
|
||||
public static final int kDriverStationEIO_DigitalIn = 6;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:88</i> */
|
||||
public static final int kDriverStationEIO_DigitalOut = 7;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:89</i> */
|
||||
public static final int kDriverStationEIO_FixedDigitalOut = 8;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:90</i> */
|
||||
public static final int kDriverStationEIO_PWM = 9;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:91</i> */
|
||||
public static final int kDriverStationEIO_Encoder = 10;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:92</i> */
|
||||
public static final int kDriverStationEIO_TouchSlider = 11;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:94</i> */
|
||||
public static final int kADXL345_SPI = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:95</i> */
|
||||
public static final int kADXL345_I2C = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:97</i> */
|
||||
public static final int kCommand_Scheduler = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:99</i> */
|
||||
public static final int kSmartDashboard_Instance = 1;
|
||||
};
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int USER_DS_LCD_DATA_SIZE = 128;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int kFRC_NetworkCommunication_DynamicType_Kinect_Custom = 25;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int kFRC_NetworkCommunication_DynamicType_Kinect_Header = 19;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int IO_CONFIG_DATA_SIZE = 32;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h</i> */
|
||||
public static final int kMaxModuleNumber = 2;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int kFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Output = 18;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int SYS_STATUS_DATA_SIZE = 44;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int kFRC_NetworkCommunication_DynamicType_Kinect_Extra2 = 22;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int kFRC_NetworkCommunication_DynamicType_Kinect_Extra1 = 20;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int kFRC_NetworkCommunication_DynamicType_DSEnhancedIO_Input = 17;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int USER_STATUS_DATA_SIZE = (984 - 32 - 44);
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int kFRC_NetworkCommunication_DynamicType_Kinect_Joystick = 24;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h</i> */
|
||||
public static final int kUsageReporting_version = 1;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int kFRC_NetworkCommunication_DynamicType_Kinect_Vertices1 = 21;
|
||||
/** <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h</i> */
|
||||
public static final int kFRC_NetworkCommunication_DynamicType_Kinect_Vertices2 = 23;
|
||||
/**
|
||||
* Original signature : <code>uint32_t FRC_NetworkCommunication_nAICalibration_getLSBWeight(const uint32_t, const uint32_t, int32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/AICalibration.h:7</i><br>
|
||||
* @deprecated use the safer methods {@link #FRC_NetworkCommunication_nAICalibration_getLSBWeight(int, int, java.nio.IntBuffer)} and {@link #FRC_NetworkCommunication_nAICalibration_getLSBWeight(int, int, com.sun.jna.ptr.IntByReference)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int FRC_NetworkCommunication_nAICalibration_getLSBWeight(int aiSystemIndex, int channel, IntByReference status);
|
||||
/**
|
||||
* Original signature : <code>uint32_t FRC_NetworkCommunication_nAICalibration_getLSBWeight(const uint32_t, const uint32_t, int32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/AICalibration.h:7</i>
|
||||
*/
|
||||
public static native int FRC_NetworkCommunication_nAICalibration_getLSBWeight(int aiSystemIndex, int channel, IntBuffer status);
|
||||
/**
|
||||
* Original signature : <code>int32_t FRC_NetworkCommunication_nAICalibration_getOffset(const uint32_t, const uint32_t, int32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/AICalibration.h:8</i><br>
|
||||
* @deprecated use the safer methods {@link #FRC_NetworkCommunication_nAICalibration_getOffset(int, int, java.nio.IntBuffer)} and {@link #FRC_NetworkCommunication_nAICalibration_getOffset(int, int, com.sun.jna.ptr.IntByReference)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int FRC_NetworkCommunication_nAICalibration_getOffset(int aiSystemIndex, int channel, IntByReference status);
|
||||
/**
|
||||
* Original signature : <code>int32_t FRC_NetworkCommunication_nAICalibration_getOffset(const uint32_t, const uint32_t, int32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/AICalibration.h:8</i>
|
||||
*/
|
||||
public static native int FRC_NetworkCommunication_nAICalibration_getOffset(int aiSystemIndex, int channel, IntBuffer status);
|
||||
/**
|
||||
* Original signature : <code>uint32_t FRC_NetworkCommunication_nLoadOut_getModulePresence(uint32_t, uint8_t)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:31</i>
|
||||
*/
|
||||
public static native int FRC_NetworkCommunication_nLoadOut_getModulePresence(int moduleType, byte moduleNumber);
|
||||
/**
|
||||
* Original signature : <code>uint32_t FRC_NetworkCommunication_nLoadOut_getTargetClass()</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/LoadOut.h:32</i>
|
||||
*/
|
||||
public static native int FRC_NetworkCommunication_nLoadOut_getTargetClass();
|
||||
/**
|
||||
* Original signature : <code>uint32_t FRC_NetworkCommunication_nUsageReporting_report(uint8_t, uint8_t, uint8_t, const char*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:117</i><br>
|
||||
* @deprecated use the safer methods {@link #FRC_NetworkCommunication_nUsageReporting_report(byte, byte, byte, java.lang.String)} and {@link #FRC_NetworkCommunication_nUsageReporting_report(byte, byte, byte, com.sun.jna.Pointer)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int FRC_NetworkCommunication_nUsageReporting_report(byte resource, byte instanceNumber, byte context, Pointer feature);
|
||||
/**
|
||||
* Original signature : <code>uint32_t FRC_NetworkCommunication_nUsageReporting_report(uint8_t, uint8_t, uint8_t, const char*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/UsageReporting.h:117</i>
|
||||
*/
|
||||
public static native int FRC_NetworkCommunication_nUsageReporting_report(byte resource, byte instanceNumber, byte context, String feature);
|
||||
/**
|
||||
* Original signature : <code>void getFPGAHardwareVersion(uint16_t*, uint32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:142</i><br>
|
||||
* @deprecated use the safer methods {@link #getFPGAHardwareVersion(java.nio.ShortBuffer, java.nio.IntBuffer)} and {@link #getFPGAHardwareVersion(com.sun.jna.ptr.ShortByReference, com.sun.jna.ptr.IntByReference)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native void getFPGAHardwareVersion(ShortByReference fpgaVersion, IntByReference fpgaRevision);
|
||||
/**
|
||||
* Original signature : <code>void getFPGAHardwareVersion(uint16_t*, uint32_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:142</i>
|
||||
*/
|
||||
public static native void getFPGAHardwareVersion(ShortBuffer fpgaVersion, IntBuffer fpgaRevision);
|
||||
/**
|
||||
* Original signature : <code>int getCommonControlData(FRCCommonControlData*, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:144</i>
|
||||
*/
|
||||
public static native int getCommonControlData(FRCCommonControlData data, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int getRecentCommonControlData(FRCCommonControlData*, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:145</i>
|
||||
*/
|
||||
public static native int getRecentCommonControlData(FRCCommonControlData commonData, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int getRecentStatusData(uint8_t*, uint8_t*, uint8_t*, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:146</i><br>
|
||||
* @deprecated use the safer methods {@link #getRecentStatusData(java.nio.ByteBuffer, java.nio.ByteBuffer, java.nio.ByteBuffer, int)} and {@link #getRecentStatusData(com.sun.jna.Pointer, com.sun.jna.Pointer, com.sun.jna.Pointer, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int getRecentStatusData(Pointer batteryInt, Pointer batteryDec, Pointer dsDigitalOut, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int getRecentStatusData(uint8_t*, uint8_t*, uint8_t*, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:146</i>
|
||||
*/
|
||||
public static native int getRecentStatusData(ByteBuffer batteryInt, ByteBuffer batteryDec, ByteBuffer dsDigitalOut, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int getDynamicControlData(uint8_t, char*, int32_t, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:147</i><br>
|
||||
* @deprecated use the safer methods {@link #getDynamicControlData(byte, java.nio.ByteBuffer, int, int)} and {@link #getDynamicControlData(byte, com.sun.jna.Pointer, int, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int getDynamicControlData(byte type, Pointer dynamicData, int maxLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int getDynamicControlData(uint8_t, char*, int32_t, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:147</i>
|
||||
*/
|
||||
public static native int getDynamicControlData(byte type, ByteBuffer dynamicData, int maxLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int setStatusData(float, uint8_t, uint8_t, const char*, int, const char*, int, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:148</i><br>
|
||||
* @deprecated use the safer methods {@link #setStatusData(float, byte, byte, java.lang.String, int, java.lang.String, int, int)} and {@link #setStatusData(float, byte, byte, com.sun.jna.Pointer, int, com.sun.jna.Pointer, int, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int setStatusData(float battery, byte dsDigitalOut, byte updateNumber, Pointer userDataHigh, int userDataHighLength, Pointer userDataLow, int userDataLowLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int setStatusData(float, uint8_t, uint8_t, const char*, int, const char*, int, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:148</i>
|
||||
*/
|
||||
public static native int setStatusData(float battery, byte dsDigitalOut, byte updateNumber, String userDataHigh, int userDataHighLength, String userDataLow, int userDataLowLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int setStatusDataFloatAsInt(int, uint8_t, uint8_t, const char*, int, const char*, int, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:151</i><br>
|
||||
* @deprecated use the safer methods {@link #setStatusDataFloatAsInt(int, byte, byte, java.lang.String, int, java.lang.String, int, int)} and {@link #setStatusDataFloatAsInt(int, byte, byte, com.sun.jna.Pointer, int, com.sun.jna.Pointer, int, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int setStatusDataFloatAsInt(int battery, byte dsDigitalOut, byte updateNumber, Pointer userDataHigh, int userDataHighLength, Pointer userDataLow, int userDataLowLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int setStatusDataFloatAsInt(int, uint8_t, uint8_t, const char*, int, const char*, int, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:151</i>
|
||||
*/
|
||||
public static native int setStatusDataFloatAsInt(int battery, byte dsDigitalOut, byte updateNumber, String userDataHigh, int userDataHighLength, String userDataLow, int userDataLowLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int setErrorData(const char*, int, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:154</i><br>
|
||||
* @deprecated use the safer methods {@link #setErrorData(java.lang.String, int, int)} and {@link #setErrorData(com.sun.jna.Pointer, int, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int setErrorData(Pointer errors, int errorsLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int setErrorData(const char*, int, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:154</i>
|
||||
*/
|
||||
public static native int setErrorData(String errors, int errorsLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int setUserDsLcdData(const char*, int, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:155</i><br>
|
||||
* @deprecated use the safer methods {@link #setUserDsLcdData(java.lang.String, int, int)} and {@link #setUserDsLcdData(com.sun.jna.Pointer, int, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int setUserDsLcdData(Pointer userDsLcdData, int userDsLcdDataLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int setUserDsLcdData(const char*, int, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:155</i>
|
||||
*/
|
||||
public static native int setUserDsLcdData(String userDsLcdData, int userDsLcdDataLength, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int overrideIOConfig(const char*, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:156</i><br>
|
||||
* @deprecated use the safer methods {@link #overrideIOConfig(java.lang.String, int)} and {@link #overrideIOConfig(com.sun.jna.Pointer, int)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native int overrideIOConfig(Pointer ioConfig, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>int overrideIOConfig(const char*, int)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:156</i>
|
||||
*/
|
||||
public static native int overrideIOConfig(String ioConfig, int wait_ms);
|
||||
/**
|
||||
* Original signature : <code>void setNewDataSem(pthread_mutex_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:165</i>
|
||||
*/
|
||||
public static native void setNewDataSem(Pointer pthread_mutex_tPtr1);
|
||||
/**
|
||||
* Original signature : <code>void setResyncSem(pthread_mutex_t*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:166</i>
|
||||
*/
|
||||
public static native void setResyncSem(Pointer pthread_mutex_tPtr1);
|
||||
/**
|
||||
* Original signature : <code>void signalResyncActionDone()</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:168</i>
|
||||
*/
|
||||
public static native void signalResyncActionDone();
|
||||
/**
|
||||
* this uint32_t is really a LVRefNum<br>
|
||||
* Original signature : <code>void setNewDataOccurRef(uint32_t)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:172</i>
|
||||
*/
|
||||
public static native void setNewDataOccurRef(int refnum);
|
||||
/**
|
||||
* Original signature : <code>void setResyncOccurRef(uint32_t)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:174</i>
|
||||
*/
|
||||
public static native void setResyncOccurRef(int refnum);
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_getVersionString(char*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:177</i><br>
|
||||
* @deprecated use the safer methods {@link #FRC_NetworkCommunication_getVersionString(java.nio.ByteBuffer)} and {@link #FRC_NetworkCommunication_getVersionString(com.sun.jna.Pointer)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static native void FRC_NetworkCommunication_getVersionString(Pointer version);
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_getVersionString(char*)</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:177</i>
|
||||
*/
|
||||
public static native void FRC_NetworkCommunication_getVersionString(ByteBuffer version);
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_observeUserProgramStarting()</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:178</i>
|
||||
*/
|
||||
public static native void FRC_NetworkCommunication_observeUserProgramStarting();
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_observeUserProgramDisabled()</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:179</i>
|
||||
*/
|
||||
public static native void FRC_NetworkCommunication_observeUserProgramDisabled();
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_observeUserProgramAutonomous()</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:180</i>
|
||||
*/
|
||||
public static native void FRC_NetworkCommunication_observeUserProgramAutonomous();
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_observeUserProgramTeleop()</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:181</i>
|
||||
*/
|
||||
public static native void FRC_NetworkCommunication_observeUserProgramTeleop();
|
||||
/**
|
||||
* Original signature : <code>void FRC_NetworkCommunication_observeUserProgramTest()</code><br>
|
||||
* <i>native declaration : /home/alex/Projects/WPILib-Development/WPILibC/WPILib/src/main/include/NetworkCommunication/FRCComm.h:182</i>
|
||||
*/
|
||||
public static native void FRC_NetworkCommunication_observeUserProgramTest();
|
||||
public static class STATUS extends PointerType {
|
||||
public STATUS(Pointer address) {
|
||||
super(address);
|
||||
}
|
||||
public STATUS() {
|
||||
super();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package edu.wpi.first.wpilibj.communication;
|
||||
|
||||
public class NIRioStatus {
|
||||
// TODO: Should this file be auto-generated?
|
||||
public static final int kRioStatusOffset = -63000;
|
||||
|
||||
public static final int kRioStatusSuccess = 0;
|
||||
public static final int kRIOStatusBufferInvalidSize = kRioStatusOffset - 80;
|
||||
public static final int kRIOStatusOperationTimedOut = -52007;
|
||||
public static final int kRIOStatusFeatureNotSupported = kRioStatusOffset - 193;
|
||||
public static final int kRIOStatusResourceNotInitialized = -52010;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package edu.wpi.first.wpilibj.communication;
|
||||
|
||||
public class UsageReporting {
|
||||
|
||||
public static void report(int resource, int instanceNumber, int i) {
|
||||
report(resource, instanceNumber, i, "");
|
||||
}
|
||||
|
||||
public static void report(int resource, int instanceNumber) {
|
||||
report(resource, instanceNumber, 0, "");
|
||||
}
|
||||
|
||||
public static void report(int resource, int instanceNumber, int i,
|
||||
String string) {
|
||||
FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_nUsageReporting_report((byte)resource, (byte) instanceNumber, (byte) i, string);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user