Initial checkin of unified hierarchy of WPILib 2015

This commit is contained in:
Brad Miller
2013-12-15 18:30:16 -05:00
commit 3178911eef
1560 changed files with 410007 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
/*----------------------------------------------------------------------------*/
/* 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
}

View File

@@ -0,0 +1,177 @@
/*----------------------------------------------------------------------------*/
/* 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() {}
}

View File

@@ -0,0 +1,24 @@
/*----------------------------------------------------------------------------*/
/* 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;
}

View File

@@ -0,0 +1,497 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,289 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,243 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,140 @@
/*----------------------------------------------------------------------------*/
/* 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

View File

@@ -0,0 +1,229 @@
/*----------------------------------------------------------------------------*/
/* 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() {}
}

View File

@@ -0,0 +1,25 @@
/*
* 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();
}

View File

@@ -0,0 +1,731 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,91 @@
/*----------------------------------------------------------------------------*/
/* 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();
}

View File

@@ -0,0 +1,372 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,208 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,521 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,269 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,101 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,209 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,648 @@
/*----------------------------------------------------------------------------*/
/* 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

View File

@@ -0,0 +1,198 @@
/*----------------------------------------------------------------------------*/
/* 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();
}
}

View File

@@ -0,0 +1,887 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,124 @@
/*----------------------------------------------------------------------------*/
/* 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";
}
}

View File

@@ -0,0 +1,155 @@
/*----------------------------------------------------------------------------*/
/* 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);
}

View File

@@ -0,0 +1,290 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,385 @@
/*----------------------------------------------------------------------------*/
/* 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() {}
}

View File

@@ -0,0 +1,142 @@
/*----------------------------------------------------------------------------*/
/* 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() {}
}

View File

@@ -0,0 +1,229 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,34 @@
/*----------------------------------------------------------------------------*/
/* 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();
}

View File

@@ -0,0 +1,135 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,279 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}
}

View File

@@ -0,0 +1,108 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,354 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,456 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,260 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,93 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,23 @@
/*----------------------------------------------------------------------------*/
/* 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();
}

View File

@@ -0,0 +1,124 @@
/*----------------------------------------------------------------------------*/
/* 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();
}
}
}

View File

@@ -0,0 +1,14 @@
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();
}

View File

@@ -0,0 +1,591 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,21 @@
/*----------------------------------------------------------------------------*/
/* 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);
}

View File

@@ -0,0 +1,39 @@
/*----------------------------------------------------------------------------*/
/* 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();
}

View File

@@ -0,0 +1,481 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,828 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}
}

View File

@@ -0,0 +1,440 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,111 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,197 @@
/*----------------------------------------------------------------------------*/
/* 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.");
}
}
}
}

View File

@@ -0,0 +1,760 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,109 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,26 @@
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();
}

View File

@@ -0,0 +1,259 @@
/*----------------------------------------------------------------------------*/
/* 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() {}
}

View File

@@ -0,0 +1,431 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,165 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,156 @@
/*----------------------------------------------------------------------------*/
/* 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 */
}
}
}

View File

@@ -0,0 +1,227 @@
/*----------------------------------------------------------------------------*/
/* 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;
}

View File

@@ -0,0 +1,168 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,94 @@
/*----------------------------------------------------------------------------*/
/* 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.");
}
}

View File

@@ -0,0 +1,41 @@
/*----------------------------------------------------------------------------*/
/* 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();
}

View File

@@ -0,0 +1,110 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,127 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,520 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,83 @@
/*----------------------------------------------------------------------------*/
/* 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);
} */
}
}

View File

@@ -0,0 +1,112 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,35 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}
}

View File

@@ -0,0 +1,70 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,33 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}
}

View File

@@ -0,0 +1,48 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,38 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,33 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,200 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,489 @@
/*----------------------------------------------------------------------------*/
/* 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();
}
});
}
}

View File

@@ -0,0 +1,22 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,11 @@
<!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>

View File

@@ -0,0 +1,48 @@
/*----------------------------------------------------------------------------*/
/* 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));
}
}
}

View File

@@ -0,0 +1,19 @@
/*----------------------------------------------------------------------------*/
/* 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();
}
}

View File

@@ -0,0 +1,41 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,477 @@
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);
}

View File

@@ -0,0 +1,18 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,19 @@
/*----------------------------------------------------------------------------*/
/* 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();
}
}

View File

@@ -0,0 +1,20 @@
/*----------------------------------------------------------------------------*/
/* 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();
}
}

View File

@@ -0,0 +1,523 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,398 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}
}
}

View File

@@ -0,0 +1,38 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,66 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,191 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,260 @@
/*----------------------------------------------------------------------------*/
/* 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);
}
}

View File

@@ -0,0 +1,46 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,371 @@
/*----------------------------------------------------------------------------*/
/* 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";
}
}

View File

@@ -0,0 +1,42 @@
/*----------------------------------------------------------------------------*/
/* 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();
}
}

View File

@@ -0,0 +1,47 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,197 @@
/*----------------------------------------------------------------------------*/
/* 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;
}
}

View File

@@ -0,0 +1,50 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,36 @@
/*----------------------------------------------------------------------------*/
/* 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();
}
}

View File

@@ -0,0 +1,45 @@
/*----------------------------------------------------------------------------*/
/* 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() {
}
}

View File

@@ -0,0 +1,378 @@
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 {
};
}

View File

@@ -0,0 +1,13 @@
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);
}

View File

@@ -0,0 +1,489 @@
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();
}
};
}

View File

@@ -0,0 +1,12 @@
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;
}

View File

@@ -0,0 +1,18 @@
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