FRCSim artf2604: Synchronized the codebases of WPILibJ-Simulation

and the main WPILibJ.

Change-Id: I9b933b6f21be21cd5e9808b6f8d127a995a742e7
This commit is contained in:
Colby Skeggs
2014-06-21 12:45:07 -07:00
parent 698f38d404
commit f5862582e6
32 changed files with 910 additions and 918 deletions

View File

@@ -13,37 +13,36 @@ import edu.wpi.first.wpilibj.tables.ITable;
/**
* 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,
public class AnalogInput extends SensorBase implements PIDSource,
LiveWindowSendable {
private SimFloatInput m_impl;
private int m_moduleNumber, m_channel;
private int m_channel;
/**
* Construct an analog channel on the default module.
* Construct an analog channel.
*
* @param channel
* The channel number to represent.
*/
public AnalogChannel(final int channel) {
this(1, 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) {
public AnalogInput(final int channel) {
m_channel = channel;
m_moduleNumber = moduleNumber;
m_impl = new SimFloatInput("simulator/analog/"+moduleNumber+"/"+channel);
m_impl = new SimFloatInput("simulator/analog/1/"+channel); // TODO: If module numbers cannot be specified, remove them from the communication system.
LiveWindow.addSensor("Analog", moduleNumber, channel, this);
LiveWindow.addSensor("AnalogInput", channel, this);
}
/**
@@ -51,7 +50,6 @@ public class AnalogChannel extends SensorBase implements PIDSource,
*/
public void free() {
m_channel = 0;
m_moduleNumber = 0;
}
/**
@@ -90,15 +88,6 @@ public class AnalogChannel extends SensorBase implements PIDSource,
}
/**
* 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;
}
/**
* Get the average value for use with PIDController
*
* @return the average value
@@ -107,7 +96,7 @@ public class AnalogChannel extends SensorBase implements PIDSource,
return getAverageVoltage();
}
/**
/**
* Live Window code, only does anything if live window is activated.
*/
public String getSmartDashboardType() {

View File

@@ -1,61 +1,157 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. 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.interfaces.Potentiometer;
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
import edu.wpi.first.wpilibj.simulation.SimFloatInput;
import edu.wpi.first.wpilibj.tables.ITable;
/**
* A class for reading analog potentiometers.
*
* Class for reading analog potentiometers. Analog potentiometers read
* in an analog voltage that corresponds to a position. Usually the
* position is either degrees or meters. However, if no conversion is
* given it remains volts.
*
* @author Alex Henning
*/
public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
private int module, channel;
private SimFloatInput impl;
private double m_scale, m_offset;
private AnalogInput m_analog_input;
private boolean m_init_analog_input;
/**
* Common initialization code called by all constructors.
* @param input The {@link AnalogInput} this potentiometer is plugged into.
* @param scale The scaling to multiply the voltage by to get a meaningful unit.
* @param offset The offset to add to the scaled value for controlling the zero value
*/
private void initPot(final int slot, final int channel, double scale, double offset) {
this.module = slot;
this.channel = channel;
impl = new SimFloatInput("simulator/analog/"+slot+"/"+channel);
}
public AnalogPotentiometer(final int slot, final int channel, double scale, double offset) {
initPot(slot, channel, scale, offset);
private void initPot(final AnalogInput input, double scale, double offset) {
this.m_scale = scale;
this.m_offset = offset;
m_analog_input = input;
}
/**
* AnalogPotentiometer constructor.
*
* Use the scaling and offset values so that the output produces
* meaningful values. I.E: you have a 270 degree potentiometer and
* you want the output to be degrees with the halfway point as 0
* degrees. The scale value is 270.0(degrees)/5.0(volts) and the
* offset is -135.0 since the halfway point after scaling is 135
* degrees.
*
* @param channel The analog channel this potentiometer is plugged into.
* @param scale The scaling to multiply the voltage by to get a meaningful unit.
* @param offset The offset to add to the scaled value for controlling the zero value
*/
public AnalogPotentiometer(final int channel, double scale, double offset) {
initPot(1, channel, scale, offset);
AnalogInput input = new AnalogInput(channel);
m_init_analog_input = true;
initPot(input, scale, offset);
}
/**
* AnalogPotentiometer constructor.
*
* Use the scaling and offset values so that the output produces
* meaningful values. I.E: you have a 270 degree potentiometer and
* you want the output to be degrees with the halfway point as 0
* degrees. The scale value is 270.0(degrees)/5.0(volts) and the
* offset is -135.0 since the halfway point after scaling is 135
* degrees.
*
* @param input The {@link AnalogInput} this potentiometer is plugged into.
* @param scale The scaling to multiply the voltage by to get a meaningful unit.
* @param offset The offset to add to the scaled value for controlling the zero value
*/
public AnalogPotentiometer(final AnalogInput input, double scale, double offset) {
m_init_analog_input = false;
initPot(input, scale, offset);
}
/**
* AnalogPotentiometer constructor.
*
* Use the scaling and offset values so that the output produces
* meaningful values. I.E: you have a 270 degree potentiometer and
* you want the output to be degrees with the halfway point as 0
* degrees. The scale value is 270.0(degrees)/5.0(volts) and the
* offset is -135.0 since the halfway point after scaling is 135
* degrees.
*
* @param channel The analog channel this potentiometer is plugged into.
* @param scale The scaling to multiply the voltage by to get a meaningful unit.
*/
public AnalogPotentiometer(final int channel, double scale) {
initPot(1, channel, scale, 0);
this(channel, scale, 0);
}
/**
* AnalogPotentiometer constructor.
*
* Use the scaling and offset values so that the output produces
* meaningful values. I.E: you have a 270 degree potentiometer and
* you want the output to be degrees with the halfway point as 0
* degrees. The scale value is 270.0(degrees)/5.0(volts) and the
* offset is -135.0 since the halfway point after scaling is 135
* degrees.
*
* @param input The {@link AnalogInput} this potentiometer is plugged into.
* @param scale The scaling to multiply the voltage by to get a meaningful unit.
*/
public AnalogPotentiometer(final AnalogInput input, double scale) {
this(input, scale, 0);
}
/**
* AnalogPotentiometer constructor.
*
* @param channel The analog channel this potentiometer is plugged into.
*/
public AnalogPotentiometer(final int channel) {
initPot(1, channel, 1, 0);
this(channel, 1, 0);
}
/**
* AnalogPotentiometer constructor.
*
* @param input The {@link AnalogInput} this potentiometer is plugged into.
*/
public AnalogPotentiometer(final AnalogInput input) {
this(input, 1, 0);
}
@Override
public double get() {
return impl.get();
}
@Override
public double pidGet() {
return get();
}
/*
/**
* Get the current reading of the potentiomere.
*
* @return The current position of the potentiometer.
*/
public double get() {
return m_analog_input.getVoltage() * m_scale + m_offset;
}
/**
* Implement the PIDSource interface.
*
* @return The current reading.
*/
public double pidGet() {
return get();
}
/**
* Live Window code, only does anything if live window is activated.
*/
public String getSmartDashboardType(){
return "Analog Input";
}
private ITable m_table;
/**
* {@inheritDoc}
*/
@@ -63,7 +159,7 @@ public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
m_table = subtable;
updateTable();
}
/**
* {@inheritDoc}
*/
@@ -72,7 +168,7 @@ public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
m_table.putNumber("Value", get());
}
}
/**
* {@inheritDoc}
*/
@@ -80,12 +176,20 @@ public class AnalogPotentiometer implements Potentiometer, LiveWindowSendable {
return m_table;
}
public void free(){
if(m_init_analog_input){
m_analog_input.free();
m_analog_input = null;
m_init_analog_input = false;
}
}
/**
* 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}

View File

@@ -1,43 +1,44 @@
/*----------------------------------------------------------------------------*/
/* 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.livewindow.LiveWindowSendable;
import edu.wpi.first.wpilibj.simulation.SimDigitalInput;
import edu.wpi.first.wpilibj.parsing.IInputOutput;
import edu.wpi.first.wpilibj.tables.ITable;
public class DigitalInput implements LiveWindowSendable {
/**
* 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 implements IInputOutput,
LiveWindowSendable {
private SimDigitalInput impl;
private int m_moduleNumber, m_channel;
private int m_channel;
/**
* Create an instance of a Digital Input class. Creates a digital input
* given a channel and uses the default module.
*
* given a channel.
*
* @param channel
* the port for the digital input
*/
public DigitalInput(int channel) {
this(1, 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) {
impl = new SimDigitalInput("simulator/dio/"+moduleNumber+"/"+channel);
m_moduleNumber = moduleNumber;
impl = new SimDigitalInput("simulator/dio/1/"+channel);
m_channel = channel;
}
/**
* 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() {
@@ -46,7 +47,7 @@ public class DigitalInput implements LiveWindowSendable {
/**
* Get the channel of the digital input
*
*
* @return The GPIO channel number that this object represents.
*/
public int getChannel() {

View File

@@ -12,11 +12,12 @@ import gazebo.msgs.GzDriverStation.DriverStation.State;
import gazebo.msgs.GzJoystick.Joystick;
import org.gazebosim.transport.SubscriberCallback;
import edu.wpi.first.wpilibj.parsing.IInputOutput;
/**
* Provide access to the network communication data to / from the Driver Station.
*/
public class DriverStation {
public class DriverStation implements IInputOutput {
/**
* Slot for the analog module to read the battery
*/
@@ -24,7 +25,7 @@ public class DriverStation {
/**
* Analog channel to read the battery
*/
public static final int kBatteryChannel = 8;
public static final int kBatteryChannel = 7;
/**
* Number of Joystick Ports
*/
@@ -33,6 +34,10 @@ public class DriverStation {
* 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
@@ -79,7 +84,7 @@ public class DriverStation {
return DriverStation.instance;
}
/**
/**
* DriverStation constructor.
*
* The single DriverStation instance is created statically with the
@@ -155,8 +160,11 @@ public class DriverStation {
* @return The value of the axis on the joystick.
*/
public double getStickAxis(int stick, int axis) {
if (axis < 1 || axis > kJoystickAxes || joysticks[stick] == null) {
return 0.0;
if (axis < 1 || axis > kJoystickAxes) {
return 0.0;
}
if (stick < 0 || stick >= joysticks.length || joysticks[stick] == null) {
return 0.0;
}
return joysticks[stick].getAxes(axis - 1);
}
@@ -169,58 +177,12 @@ public class DriverStation {
* @return The state of the buttons on the joystick.
*/
public boolean getStickButton(int stick, int button) {
if (joysticks[stick] == null) {
return false;
if (stick < 0 || stick >= joysticks.length || joysticks[stick] == null) {
return false;
}
return joysticks[stick].getButtons(button - 1);
}
/**
* 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) {
throw new RuntimeException("The simulated DriverStation doesn't have analog inputs");
}
/**
* 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) {
throw new RuntimeException("The simulated DriverStation doesn't have digital inputs");
}
/**
* 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) {
throw new RuntimeException("The simulated DriverStation doesn't have digital outputs");
}
/**
* 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) {
throw new RuntimeException("The simulated DriverStation doesn't have digital outputs");
}
/**
* Gets a value indicating whether the Driver Station requires the
* robot to be enabled.
@@ -311,7 +273,7 @@ public class DriverStation {
public int getTeamNumber() {
return 348; // TODO
}
/**
* Is the driver station attached to a Field Management System?
* Note: This does not work with the Blue DS.
@@ -321,20 +283,6 @@ public class DriverStation {
return false;
}
/**
* 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() {
throw new RuntimeException("The simulated DriverStation doesn't support match times"); // TODO:
}
/** 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 */

View File

@@ -9,533 +9,319 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
import edu.wpi.first.wpilibj.simulation.SimEncoder;
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.
* 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, LiveWindowSendable {
private int m_index;
private double m_distancePerPulse; // distance of travel for each encoder tick
private EncodingType m_encodingType = EncodingType.k4X;
private boolean m_allocatedA;
private boolean m_allocatedB;
private boolean m_allocatedI;
private PIDSourceParameter m_pidSource;
private SimEncoder impl;
public class Encoder extends SensorBase implements CounterBase, PIDSource,
ISensor, LiveWindowSendable {
private int m_index;
private double m_distancePerPulse; // distance of travel for each encoder tick
private EncodingType m_encodingType = EncodingType.k4X;
private boolean m_allocatedA;
private boolean m_allocatedB;
private boolean m_allocatedI;
private PIDSourceParameter m_pidSource;
private SimEncoder impl;
/**
* 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(int aSlot, int aChannel,
int bSlot, int bChannel, boolean reverseDirection) {
/**
* 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(int aChannel, int bChannel, boolean reverseDirection) {
m_distancePerPulse = 1.0;
m_pidSource = PIDSourceParameter.kDistance;
LiveWindow.addSensor("Encoder", aSlot, aChannel, this);
if ((bSlot < aSlot) || ((bSlot == aSlot) && (bChannel < aChannel))) { // Swap ports
int slot = bSlot;
int channel = bChannel;
bSlot = aSlot;
bChannel = aChannel;
aSlot = slot;
aChannel = channel;
}
impl = new SimEncoder("simulator/dio/"+aSlot+"/"+aChannel+"/"+bSlot+"/"+bChannel);
setDistancePerPulse(1);
}
LiveWindow.addSensor("Encoder", aChannel, this);
if (bChannel < aChannel) { // Swap ports
int channel = bChannel;
bChannel = aChannel;
aChannel = channel;
}
impl = new SimEncoder("simulator/dio/1/"+aChannel+"/1/"+bChannel);
setDistancePerPulse(1);
/**
* 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;
initEncoder(aSlot, aChannel, bSlot, bChannel, 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 channels.
*
* @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;
initEncoder(aChannel, bChannel, 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.
* @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;
if (encodingType == null)
throw new NullPointerException("Given encoding type was null");
m_encodingType = encodingType;
initEncoder(aSlot, aChannel, bSlot, bChannel, reverseDirection);
}
/**
* Encoder constructor. Construct a Encoder given a and b channels.
*
* @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 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) {
throw new UnsupportedOperationException("Simulation doesn't currently support indexed encoders.");
}
/**
* Encoder constructor. Construct a Encoder given a and b channels.
*
* @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;
initEncoder(aChannel, bChannel, 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) {
throw new UnsupportedOperationException("Simulation doesn't currently support indexed encoders.");
}
public void free() {}
/**
* 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;
initEncoder(1, aChannel, 1, bChannel, reverseDirection);
}
/**
* Start the Encoder.
* Starts counting pulses on the Encoder device.
*/
public void start() {
impl.start();
}
/**
* 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);
}
/**
* Stops counting pulses on the Encoder device. The value is not changed.
*/
public void stop() {
impl.stop();
}
/**
* 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;
initEncoder(1, aChannel, 1, bChannel, reverseDirection);
}
/**
* Reset the Encoder distance to zero.
* Resets the current count to zero on the encoder.
*/
public void reset() {
impl.reset();
}
/**
* 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) {
throw new UnsupportedOperationException("Simulation doesn't currently support indexed encoders.");
}
// Left this in despite removing other such stubs because this one is needed to compile.
public boolean getDirection() {
// XXX: not implemented in simulation yet
throw new UnsupportedOperationException("Simulation doesn't currently support this method.");
}
/**
* 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);
}
/**
* 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 m_distancePerPulse * impl.getPosition();
}
/**
* 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.
*/
// Not Supported: public Encoder(DigitalSource aSource, DigitalSource bSource, boolean reverseDirection) {
/**
* 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 sc
*/
public int get() {
throw new UnsupportedOperationException("Simulation doesn't currently support this method.");
}
/**
* 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.
*/
// Not Supported: public Encoder(DigitalSource aSource, DigitalSource bSource) {
/**
* 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 unscale
*
* @return Period in seconds of the most recent pulse.
*/
public double getPeriod() {
throw new UnsupportedOperationException("Simulation doesn't currently support this method.");
}
/**
* 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.
*/
// Not Supported: public Encoder(DigitalSource aSource, DigitalSource bSource, boolean reverseDirection, final EncodingType encodingType) {
/**
* Sets the maximum period for stopped detection.
* Sets the value that represents the maximum period of the Encoder before
* that the attached device is stopped. This timeout allows users to determ
* other shaft has stopped rotating.
* This method compensates for the decoding type.
*
*
* @param maxPeriod The maximum time between rising and falling edges befor
* report the device stopped. This is expressed in seconds.
*/
public void setMaxPeriod(double maxPeriod) {
// XXX: not implemented in simulation yet
throw new UnsupportedOperationException("Simulation doesn't currently support this method.");
}
/**
* 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.
*/
// Not Supported: public Encoder(DigitalSource aSource, DigitalSource bSource, DigitalSource indexSource, boolean reverseDirection) {
/**
* Determine if the encoder is stopped.
* Using the MaxPeriod value, a boolean is returned that is true if the enc
* stopped and false if it is still moving. A stopped encoder is one where
* width exceeds the MaxPeriod.
* @return True if the encoder is considered stopped.
*/
public boolean getStopped() {
// XXX: not implemented in simulation yet
throw new UnsupportedOperationException("Simulation doesn't currently support this method.");
}
/**
* 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.
*/
// Not Supported: public Encoder(DigitalSource aSource, DigitalSource bSource, DigitalSource indexSource) {
/**
* 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 * impl.getVelocity();
}
public void free() {}
/**
* 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) {
System.err.println("NOTE|WPILibJSim: Encoder.setDistancePerPulse() assumes 360 pulses per revolution in simulation.");
m_distancePerPulse = distancePerPulse;
}
/**
* Start the Encoder.
* Starts counting pulses on the Encoder device.
*/
public void start() {
impl.start();
}
/**
* 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;
}
/**
* Stops counting pulses on the Encoder device. The value is not changed.
*/
public void stop() {
impl.stop();
}
/**
* 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;
}
}
/**
* 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() {
throw new UnsupportedOperationException("Simulation doesn't currently support raw values.");
}
/*
* 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;
/**
* 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() {
throw new UnsupportedOperationException("Simulation doesn't support ticks.");
}
/**
* {@inheritDoc}
*/
public void initTable(ITable subtable) {
m_table = subtable;
updateTable();
}
/**
* Reset the Encoder distance to zero.
* Resets the current count to zero on the encoder.
*/
public void reset() {
impl.reset();
}
/**
* {@inheritDoc}
*/
public ITable getTable() {
return m_table;
}
/**
* 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() {
throw new UnsupportedOperationException("Simulation doesn't currently support deprecated methods.");
}
/**
* {@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);
}
}
/**
* 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) {
// XXX: not implemented in simulation yet
throw new UnsupportedOperationException("Simulation doesn't currently support this method.");
}
/**
* {@inheritDoc}
*/
public void startLiveWindowMode() {
}
/**
* 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() {
// XXX: not implemented in simulation yet
throw new UnsupportedOperationException("Simulation doesn't currently support this method.");
}
/**
* The last direction the encoder value changed.
* @return The last direction the encoder value changed.
*/
public boolean getDirection() {
// XXX: not implemented in simulation yet
throw new UnsupportedOperationException("Simulation doesn't currently support this method.");
}
/**
* 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 m_distancePerPulse * impl.getPosition();
}
/**
* 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 * impl.getVelocity();
}
/**
* 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) {
// XXX: not implemented in simulation yet
throw new UnsupportedOperationException("Simulation doesn't currently support this method.");
}
/**
* 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) {
System.err.println("NOTE|WPILibJSim: Encoder.setDistancePerPulse() assumes 360 pulses per revolution in simulation.");
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) {
// XXX: Currently uni-directional
throw new UnsupportedOperationException("Simulation doesn't support reversing direction.");
}
/**
* 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) {
throw new UnsupportedOperationException("Simulation doesn't support averaging samples.");
}
/**
* 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() {
throw new UnsupportedOperationException("Simulation doesn't support averaging samples.");
}
/**
* 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() {}
/**
* {@inheritDoc}
*/
public void stopLiveWindowMode() {
}
}

View File

@@ -9,6 +9,7 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
import edu.wpi.first.wpilibj.simulation.SimGyro;
import edu.wpi.first.wpilibj.parsing.ISensor;
import edu.wpi.first.wpilibj.tables.ITable;
import edu.wpi.first.wpilibj.util.BoundaryException;
@@ -21,11 +22,9 @@ import edu.wpi.first.wpilibj.util.BoundaryException;
* determine the default offset. This is subtracted from each sample to
* determine the heading.
*/
public class Gyro extends SensorBase implements PIDSource, LiveWindowSendable {
public class Gyro extends SensorBase implements PIDSource, ISensor,
LiveWindowSendable {
double m_offset;
int m_center;
boolean m_channelAllocated;
private PIDSourceParameter m_pidSource;
private SimGyro impl;
@@ -37,41 +36,23 @@ public class Gyro extends SensorBase implements PIDSource, LiveWindowSendable {
* 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(int slot, int channel) {
impl = new SimGyro("simulator/analog/"+slot+"/"+channel);
private void initGyro(int channel) {
impl = new SimGyro("simulator/analog/1/"+channel);
reset();
setPIDSourceParameter(PIDSourceParameter.kAngle);
//UsageReporting.report(tResourceType.kResourceType_Gyro,
// m_analog.getChannel(), m_analog.getModuleNumber() - 1);
LiveWindow.addSensor("Gyro", slot, channel, 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_channelAllocated = true;
initGyro(slot, channel);
LiveWindow.addSensor("Gyro", channel, this);
}
/**
* 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_channelAllocated = true;
initGyro(1, channel);
initGyro(channel);
}
/**
@@ -102,13 +83,13 @@ public class Gyro extends SensorBase implements PIDSource, LiveWindowSendable {
/**
* 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.
*/
@@ -118,32 +99,19 @@ public class Gyro extends SensorBase implements PIDSource, LiveWindowSendable {
/**
* 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() {
return impl.getVelocity();
}
/**
* 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) {
throw new UnsupportedOperationException("Simulation doesn't currently support setting the sensitivity.");
}
/**
* 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.
*/
@@ -154,7 +122,7 @@ public class Gyro extends SensorBase implements PIDSource, LiveWindowSendable {
/**
* Get the angle of the gyro for use with PIDControllers
*
*
* @return the current angle according to the gyro
*/
public double pidGet() {

View File

@@ -60,8 +60,6 @@ public class IterativeRobot extends RobotBase {
*
*/
public void startCompetition() {
// UsageReporting.report(tResourceType.kResourceType_Framework, tInstances.kFramework_Iterative);
robotInit();
// tracing support:
@@ -125,7 +123,6 @@ public class IterativeRobot extends RobotBase {
m_disabledInitialized = false;
}
if (nextPeriodReady()) {
// TODO: getWatchdog().feed();
// TODO: FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramAutonomous();
autonomousPeriodic();
didAutonomousPeriodic = true;
@@ -142,7 +139,6 @@ public class IterativeRobot extends RobotBase {
m_disabledInitialized = false;
}
if (nextPeriodReady()) {
// TODO: getWatchdog().feed();
// TODO: FRC_NetworkCommunicationsLibrary.FRC_NetworkCommunication_observeUserProgramTeleop();
teleopPeriodic();
didTeleopPeriodic = true;
@@ -158,7 +154,7 @@ public class IterativeRobot extends RobotBase {
private boolean nextPeriodReady() {
// TODO: return m_ds.isNewControlData();
try {
Thread.sleep(20);
Thread.sleep(20); // TODO: Find a better solution. This one is way too hacky!
} catch (InterruptedException ex) {}
return true;
}

View File

@@ -11,47 +11,36 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
import edu.wpi.first.wpilibj.simulation.SimSpeedController;
import edu.wpi.first.wpilibj.tables.ITable;
import edu.wpi.first.wpilibj.tables.ITableListener;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
/**
* CTRE Talon Speed Controller
* VEX Robotics Jaguar Speed Control
*/
public class Jaguar implements SpeedController, PIDOutput, MotorSafety, LiveWindowSendable {
private int module, channel;
private int channel;
private SimSpeedController impl;
/**
* Common initialization code called by all constructors.
*/
private void initTalon(final int slot, final int channel) {
this.module = slot;
private void initJaguar(final int channel) {
this.channel = channel;
impl = new SimSpeedController("simulator/pwm/"+slot+"/"+channel);
impl = new SimSpeedController("simulator/pwm/1/"+channel);
m_safetyHelper = new MotorSafetyHelper(this);
m_safetyHelper.setExpiration(0.0);
m_safetyHelper.setSafetyEnabled(false);
// LiveWindow.addActuator("Talon", getModuleNumber(), getChannel(), this);
// UsageReporting.report(tResourceType.kResourceType_Talon, getChannel(), getModuleNumber()-1);
LiveWindow.addActuator("Jaguar", channel, this);
}
/**
* Constructor that assumes the default digital module.
* Constructor.
*
* @param channel The PWM channel on the digital module that the Victor is attached to.
* @param channel The PWM channel that the Jaguar is attached to.
*/
public Jaguar(final int channel) {
initTalon(1, channel);
}
/**
* 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 Jaguar(final int slot, final int channel) {
initTalon(slot, channel);
initJaguar(channel);
}
/**
@@ -89,7 +78,7 @@ public class Jaguar implements SpeedController, PIDOutput, MotorSafety, LiveWind
public double get() {
return impl.get();
}
/**
* Disable the speed controller
*/
@@ -141,7 +130,7 @@ public class Jaguar implements SpeedController, PIDOutput, MotorSafety, LiveWind
@Override
public String getDescription() {
return "PWM "+channel+" on module "+module;
return "PWM "+channel+" on module 1";
}
//// LiveWindow Methods

View File

@@ -6,7 +6,7 @@
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
import edu.wpi.first.wpilibj.GenericHID;
import edu.wpi.first.wpilibj.parsing.IInputOutput;
/**
* Handle input from standard Joysticks connected to the Driver Station.
@@ -14,7 +14,7 @@ import edu.wpi.first.wpilibj.GenericHID;
* 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 {
public class Joystick extends GenericHID implements IInputOutput {
static final byte kDefaultXAxis = 1;
static final byte kDefaultYAxis = 2;
@@ -98,6 +98,7 @@ public class Joystick extends GenericHID {
this.value = value;
}
}
private DriverStation m_ds;
private final int m_port;
private final byte[] m_axes;
private final byte[] m_buttons;
@@ -120,7 +121,6 @@ public class Joystick extends GenericHID {
m_buttons[ButtonType.kTrigger.value] = kDefaultTriggerButton;
m_buttons[ButtonType.kTop.value] = kDefaultTopButton;
//UsageReporting.report(tResourceType.kResourceType_Joystick, port);
}
/**
@@ -134,6 +134,7 @@ public class Joystick extends GenericHID {
* @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;
@@ -199,7 +200,7 @@ public class Joystick extends GenericHID {
* @return The value of the axis.
*/
public double getRawAxis(final int axis) {
return DriverStation.getInstance().getStickAxis(m_port, axis);
return m_ds.getStickAxis(m_port, axis);
}
/**
@@ -273,7 +274,7 @@ public class Joystick extends GenericHID {
* @return The state of the button.
*/
public boolean getRawButton(final int button) {
return DriverStation.getInstance().getStickButton(m_port, button);
return m_ds.getStickButton(m_port, button);
}
/**

View File

@@ -82,9 +82,9 @@ public class MotorSafetyHelper {
* updated again.
*/
public void check() {
// TODO: DriverStation ds = DriverStation.getInstance();
// TODO: if (!m_enabled || ds.isDisabled() || ds.isTest())
// TODO: return;
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.");

View File

@@ -9,6 +9,7 @@ package edu.wpi.first.wpilibj;
import java.util.TimerTask;
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;
@@ -20,7 +21,7 @@ import edu.wpi.first.wpilibj.util.BoundaryException;
* care of the integral calculations, as well as writing the given
* PIDOutput
*/
public class PIDController implements LiveWindowSendable, Controller {
public class PIDController implements IUtility, LiveWindowSendable, Controller {
public static final double kDefaultPeriod = .05;
private static int instances = 0;
@@ -44,6 +45,7 @@ public class PIDController implements LiveWindowSendable, Controller {
PIDSource m_pidInput;
PIDOutput m_pidOutput;
java.util.Timer m_controlLoop;
private boolean m_freed = false;
private boolean m_usingPercentTolerance;
/**
@@ -99,7 +101,11 @@ public class PIDController implements LiveWindowSendable, Controller {
}
public void run() {
m_controller.calculate();
if(!m_freed){
m_controller.calculate();
} else {
cancel();
}
}
}
@@ -140,7 +146,6 @@ public class PIDController implements LiveWindowSendable, Controller {
m_controlLoop.schedule(new PIDTask(this), 0L, (long) (m_period * 1000));
instances++;
// UsageReporting.report(tResourceType.kResourceType_PIDController, instances);
m_tolerance = new NullTolerance();
}
@@ -189,7 +194,11 @@ public class PIDController implements LiveWindowSendable, Controller {
* Free the PID object
*/
public void free() {
m_freed = true;
if(this.table!=null) table.removeTableListener(listener);
m_controlLoop.cancel();
m_pidInput = null;
m_pidOutput = null;
m_controlLoop = null;
}
@@ -214,10 +223,12 @@ public class PIDController implements LiveWindowSendable, Controller {
}
if (enabled) {
double input = pidInput.pidGet();
double input;
double result;
PIDOutput pidOutput = null;
synchronized (this){
input = pidInput.pidGet();
}
synchronized (this) {
m_error = m_setpoint - input;
if (m_continuous) {
@@ -256,7 +267,7 @@ public class PIDController implements LiveWindowSendable, Controller {
pidOutput = m_pidOutput;
result = m_result;
}
pidOutput.pidWrite(result);
}
}
@@ -435,27 +446,16 @@ public class PIDController implements LiveWindowSendable, Controller {
* 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))
* @deprecated Use {@link #setPercentTolerance(double) or {@link #setAbsoluteTolerance(double)} instead.
*/
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
* @param absvalue absolute error which is tolerable in the units of the input object
*/
public synchronized void setAbsoluteTolerance(double absvalue) {
m_tolerance = new AbsoluteTolerance(absvalue);
@@ -464,7 +464,7 @@ public class PIDController implements LiveWindowSendable, Controller {
/**
* Set the percentage error which is considered tolerable for use with
* OnTarget. (Input of 15.0 = 15 percent)
* @param percent error which is tolerable
* @param percentage percent error which is tolerable
*/
public synchronized void setPercentTolerance(double percentage) {
m_tolerance = new PercentageTolerance(percentage);

View File

@@ -13,7 +13,6 @@ import java.util.Enumeration;
import java.util.jar.Manifest;
import edu.wpi.first.wpilibj.simulation.MainNode;
import edu.wpi.first.wpilibj.networktables.NetworkTable;
/**
@@ -25,8 +24,6 @@ import edu.wpi.first.wpilibj.networktables.NetworkTable;
* might be spawned as a task, then killed at the end of the Autonomous period.
*/
public abstract class RobotBase {
private static DriverStation ds;
/**
* The VxWorks priority that robot code should work at (so Java code should run at)
*/
@@ -37,8 +34,7 @@ public abstract class RobotBase {
*/
public final static String ERRORS_TO_DRIVERSTATION_PROP = "first.driverstation.senderrors";
// TODO: protected final DriverStation m_ds;
// TODO: private final Watchdog m_watchdog = Watchdog.getInstance();
protected final DriverStation m_ds;
/**
* Constructor for a generic robot program.
@@ -57,7 +53,7 @@ public abstract class RobotBase {
// Utility.sendErrorStreamToDriverStation(true);
// }
NetworkTable.setServerMode();//must be before b
// TODO: m_watchdog.setEnabled(false);
m_ds = DriverStation.getInstance();
NetworkTable.getTable(""); // forces network tables to initialize
NetworkTable.getTable("LiveWindow").getSubTable("~STATUS~").putBoolean("LW Enabled", false);
}
@@ -68,29 +64,6 @@ public abstract class RobotBase {
public void free() {
}
/**
* Check on the overall status of the system.
*
* @return Is the system active (i.e. PWM motor outputs, etc. enabled)?
*/
public boolean isSystemActive() {
// TODO: return m_watchdog.isSystemActive();
return true;
}
/**
* Return the instance of the Watchdog timer.
* Get the watchdog timer so the user program can either disable it or feed it when
* necessary.
*
* @return The Watchdog timer.
*/
// TODO: No watchdog supportr
// public Watchdog getWatchdog() {
// return m_watchdog;
//}
/**
* @return If the robot is running in simulation.
*/
@@ -110,7 +83,7 @@ public abstract class RobotBase {
* @return True if the Robot is currently disabled by the field controls.
*/
public boolean isDisabled() {
return ds.isDisabled();
return m_ds.isDisabled();
}
/**
@@ -118,7 +91,7 @@ public abstract class RobotBase {
* @return True if the Robot is currently enabled by the field controls.
*/
public boolean isEnabled() {
return ds.isEnabled();
return m_ds.isEnabled();
}
/**
@@ -126,7 +99,7 @@ public abstract class RobotBase {
* @return True if the robot is currently operating Autonomously as determined by the field controls.
*/
public boolean isAutonomous() {
return ds.isAutonomous();
return m_ds.isAutonomous();
}
/**
@@ -134,7 +107,7 @@ public abstract class RobotBase {
* @return True if the robot is currently operating in Test mode as determined by the driver station.
*/
public boolean isTest() {
return ds.isTest();
return m_ds.isTest();
}
/**
@@ -142,7 +115,7 @@ public abstract class RobotBase {
* @return True if the robot is currently operating in Tele-Op mode as determined by the field controls.
*/
public boolean isOperatorControl() {
return ds.isOperatorControl();
return m_ds.isOperatorControl();
}
/**
@@ -150,7 +123,7 @@ public abstract class RobotBase {
* @return Has new data arrived over the network since the last time this function was called?
*/
public boolean isNewDataAvailable() {
return ds.isNewControlData();
return m_ds.isNewControlData();
}
/**
@@ -189,8 +162,6 @@ public abstract class RobotBase {
return;
}
ds = DriverStation.getInstance();
String robotName = "";
Enumeration<URL> resources = null;
try {

View File

@@ -6,6 +6,8 @@
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
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
@@ -14,7 +16,7 @@ package edu.wpi.first.wpilibj;
* 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 {
public class RobotDrive implements MotorSafety, IUtility {
protected MotorSafetyHelper m_safetyHelper;
@@ -64,7 +66,7 @@ public class RobotDrive implements MotorSafety {
protected SpeedController m_rearLeftMotor;
protected SpeedController m_rearRightMotor;
protected boolean m_allocatedSpeedControllers;
protected boolean m_isCANInitialized = true;
protected boolean m_isCANInitialized = false;//TODO: fix can
protected static boolean kArcadeRatioCurve_Reported = false;
protected static boolean kTank_Reported = false;
protected static boolean kArcadeStandard_Reported = false;
@@ -75,16 +77,16 @@ public class RobotDrive implements MotorSafety {
* 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.
* @param leftMotorChannel The PWM channel number that drives the left motor.
* @param rightMotorChannel The PWM channel number 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 Talon(leftMotorChannel);
m_rearLeftMotor = new Jaguar(leftMotorChannel);
m_frontRightMotor = null;
m_rearRightMotor = new Talon(rightMotorChannel);
m_rearRightMotor = new Jaguar(rightMotorChannel);
for (int i = 0; i < kMaxNumberOfMotors; i++) {
m_invertedMotors[i] = 1;
}
@@ -98,19 +100,19 @@ public class RobotDrive implements MotorSafety {
* 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
* @param frontLeftMotor Front left motor channel number
* @param rearLeftMotor Rear Left motor channel number
* @param frontRightMotor Front right motor channel number
* @param rearRightMotor Rear Right motor channel number
*/
public RobotDrive(final int frontLeftMotor, final int rearLeftMotor,
final int frontRightMotor, final int rearRightMotor) {
m_sensitivity = kDefaultSensitivity;
m_maxOutput = kDefaultMaxOutput;
m_rearLeftMotor = new Talon(rearLeftMotor);
m_rearRightMotor = new Talon(rearRightMotor);
m_frontLeftMotor = new Talon(frontLeftMotor);
m_frontRightMotor = new Talon(frontRightMotor);
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;
}
@@ -190,7 +192,6 @@ public class RobotDrive implements MotorSafety {
double leftOutput, rightOutput;
if(!kArcadeRatioCurve_Reported) {
// UsageReporting.report(tResourceType.kResourceType_RobotDrive, getNumMotors(), tInstances.kRobotDrive_ArcadeRatioCurve);
kArcadeRatioCurve_Reported = true;
}
if (curve < 0) {
@@ -290,7 +291,6 @@ public class RobotDrive implements MotorSafety {
public void tankDrive(double leftValue, double rightValue, boolean squaredInputs) {
if(!kTank_Reported) {
// UsageReporting.report(tResourceType.kResourceType_RobotDrive, getNumMotors(), tInstances.kRobotDrive_Tank);
kTank_Reported = true;
}
@@ -391,7 +391,6 @@ public class RobotDrive implements MotorSafety {
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;
}
@@ -464,7 +463,6 @@ public class RobotDrive implements MotorSafety {
*/
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;
@@ -509,7 +507,6 @@ public class RobotDrive implements MotorSafety {
*/
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;
@@ -657,7 +654,6 @@ public class RobotDrive implements MotorSafety {
* Free the speed controllers if they were allocated locally
*/
public void free() {
}
public void setExpiration(double timeout) {

View File

@@ -12,13 +12,12 @@ package edu.wpi.first.wpilibj;
* 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
*/
@@ -26,28 +25,47 @@ public abstract class SensorBase { // TODO: Refactor
/**
* Number of digital channels per digital sidecar
*/
public static final int kDigitalChannels = 14;
public static final int kDigitalChannels = 20;
/**
* Number of analog channels per module
* Number of digital modules
* XXX: This number is incorrect. We need to find the correct number.
*/
public static final int kAnalogChannels = 8;
public static final int kDigitalModules = 1;
/**
* Number of analog input channels per module
*/
public static final int kAnalogInputChannels = 8;
/**
* Number of analog output channels per module
*/
public static final int kAnalogOutputChannels = 2;
/**
* Number of analog modules
*/
public static final int kAnalogModules = 1;
/**
* Number of solenoid channels per module
*/
public static final int kSolenoidChannels = 8;
/**
* Number of solenoid modules
* Number of analog modules
*/
public static final int kSolenoidModules = 2;
/**
* Number of PWM channels per sidecar
*/
public static final int kPwmChannels = 10;
public static final int kPwmChannels = 20;
/**
* Number of relay channels per sidecar
*/
public static final int kRelayChannels = 8;
public static final int kRelayChannels = 4;
/**
* Number of power distribution channels
*/
public static final int kPDPChannels = 16;
private static int m_defaultAnalogModule = 1;
private static int m_defaultDigitalModule = 1;
private static int m_defaultSolenoidModule = 1;
/**
@@ -56,6 +74,32 @@ public abstract class SensorBase { // TODO: Refactor
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.
*
@@ -66,6 +110,49 @@ public abstract class SensorBase { // TODO: Refactor
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 (moduleNumber != 1 && moduleNumber != 2)
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 (moduleNumber != 1 && moduleNumber != 2) {
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).
@@ -73,10 +160,9 @@ public abstract class SensorBase { // TODO: Refactor
* @param moduleNumber The solenoid module module number to check.
*/
protected static void checkSolenoidModule(final int moduleNumber) {
// TODO: fix
if(moduleNumber == 1 || moduleNumber == 2) {
System.err.println("Solenoid module " + moduleNumber + " is not present.");
}
// if(HALLibrary.checkSolenoidModule((byte) (moduleNumber - 1)) != 0) {
// System.err.println("Solenoid module " + moduleNumber + " is not present.");
// }
}
/**
@@ -87,7 +173,7 @@ public abstract class SensorBase { // TODO: Refactor
* @param channel The channel number to check.
*/
protected static void checkDigitalChannel(final int channel) {
if (channel <= 0 || channel > kDigitalChannels) {
if (channel < 0 || channel >= kDigitalChannels) {
System.err.println("Requested digital channel number is out of range.");
}
}
@@ -100,7 +186,7 @@ public abstract class SensorBase { // TODO: Refactor
* @param channel The channel number to check.
*/
protected static void checkRelayChannel(final int channel) {
if (channel <= 0 || channel > kRelayChannels) {
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.");
}
@@ -114,21 +200,34 @@ public abstract class SensorBase { // TODO: Refactor
* @param channel The channel number to check.
*/
protected static void checkPWMChannel(final int channel) {
if (channel <= 0 || channel > kPwmChannels) {
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.
* Check that the analog input number is value.
* Verify that the analog input number is one of the legal channel numbers. Channel numbers
* are 0-based.
*
* @param channel The channel number to check.
*/
protected static void checkAnalogChannel(final int channel) {
if (channel <= 0 || channel > kAnalogChannels) {
protected static void checkAnalogInputChannel(final int channel) {
if (channel <= 0 || channel > kAnalogInputChannels) {
System.err.println("Requested analog channel number is out of range.");
}
}
/**
* Check that the analog input number is value.
* Verify that the analog input number is one of the legal channel numbers. Channel numbers
* are 0-based.
*
* @param channel The channel number to check.
*/
protected static void checkAnalogOutputChannel(final int channel) {
if (channel <= 0 || channel > kAnalogOutputChannels) {
System.err.println("Requested analog channel number is out of range.");
}
}
@@ -145,6 +244,36 @@ public abstract class SensorBase { // TODO: Refactor
}
}
/**
* Verify that the power distribution channel number is within limits.
* Channel numbers are 1-based.
*
* @param channel The channel number to check.
*/
protected static void checkPDPChannel(final int channel) {
if (channel <= 0 || channel > kPDPChannels) {
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.
*

View File

@@ -108,8 +108,6 @@ public class SimpleRobot extends RobotBase {
* to be enabled again.
*/
public void startCompetition() {
// UsageReporting.report(tResourceType.kResourceType_Framework, tInstances.kFramework_Simple);
robotMain();
if (!m_robotMainOverridden) {
// first and one-time initialization
@@ -118,42 +116,33 @@ public class SimpleRobot extends RobotBase {
while (true) {
if (isDisabled()) {
// TODO: m_ds.InDisabled(true);
m_ds.InDisabled(true);
disabled();
// TODO: m_ds.InDisabled(false);
m_ds.InDisabled(false);
while (isDisabled()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
Timer.delay(0.01);
}
} else if (isAutonomous()) {
// TODO: m_ds.InAutonomous(true);
m_ds.InAutonomous(true);
autonomous();
// TODO: m_ds.InAutonomous(false);
m_ds.InAutonomous(false);
while (isAutonomous() && !isDisabled()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
Timer.delay(0.01);
}
} else if (isTest()) {
LiveWindow.setEnabled(true);
// TODO: m_ds.InTest(true);
m_ds.InTest(true);
test();
// TODO: m_ds.InTest(false);
while (isTest() && isEnabled()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
}
m_ds.InTest(false);
while (isTest() && isEnabled())
Timer.delay(0.01);
LiveWindow.setEnabled(false);
} else {
// TODO: m_ds.InOperatorControl(true);
m_ds.InOperatorControl(true);
operatorControl();
// TODO: m_ds.InOperatorControl(false);
m_ds.InOperatorControl(false);
while (isOperatorControl() && !isDisabled()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
Timer.delay(0.01);
}
}
} /* while loop */

View File

@@ -11,47 +11,47 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
import edu.wpi.first.wpilibj.simulation.SimSpeedController;
import edu.wpi.first.wpilibj.tables.ITable;
import edu.wpi.first.wpilibj.tables.ITableListener;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
/**
* CTRE Talon Speed Controller
*/
public class Talon implements SpeedController, PIDOutput, MotorSafety, LiveWindowSendable {
private int module, channel;
private int channel;
private SimSpeedController impl;
/**
* 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(final int slot, final int channel) {
this.module = slot;
private void initTalon(final int channel) {
this.channel = channel;
impl = new SimSpeedController("simulator/pwm/"+slot+"/"+channel);
impl = new SimSpeedController("simulator/pwm/1/"+channel);
m_safetyHelper = new MotorSafetyHelper(this);
m_safetyHelper.setExpiration(0.0);
m_safetyHelper.setSafetyEnabled(false);
// LiveWindow.addActuator("Talon", getModuleNumber(), getChannel(), this);
// UsageReporting.report(tResourceType.kResourceType_Talon, getChannel(), getModuleNumber()-1);
LiveWindow.addActuator("Talon", channel, this);
}
/**
* Constructor that assumes the default digital module.
* Constructor.
*
* @param channel The PWM channel on the digital module that the Victor is attached to.
* @param channel The PWM channel that the Talon is attached to.
*/
public Talon(final int channel) {
initTalon(1, channel);
}
/**
* 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) {
initTalon(slot, channel);
initTalon(channel);
}
/**
@@ -66,7 +66,7 @@ public class Talon implements SpeedController, PIDOutput, MotorSafety, LiveWindo
* @param syncGroup The update group to add this Set() to, pending UpdateSyncGroup(). If 0, update immediately.
*/
public void set(double speed, byte syncGroup) {
impl.set(speed, syncGroup);
impl.set(speed, syncGroup);
}
/**
@@ -78,7 +78,7 @@ public class Talon implements SpeedController, PIDOutput, MotorSafety, LiveWindo
* @param speed The speed value between -1.0 and 1.0 to set.
*/
public void set(double speed) {
impl.set(speed);
impl.set(speed);
}
/**
@@ -89,7 +89,7 @@ public class Talon implements SpeedController, PIDOutput, MotorSafety, LiveWindo
public double get() {
return impl.get();
}
/**
* Disable the speed controller
*/
@@ -141,7 +141,7 @@ public class Talon implements SpeedController, PIDOutput, MotorSafety, LiveWindo
@Override
public String getDescription() {
return "PWM "+channel+" on module "+module;
return "PWM "+channel+" on module 1";
}
//// LiveWindow Methods

View File

@@ -7,6 +7,8 @@
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
@@ -14,7 +16,7 @@ package edu.wpi.first.wpilibj;
* value. The implementation simply records the time when started and subtracts the current time
* whenever the value is requested.
*/
public class Timer {
public class Timer implements IUtility {
private long m_startTime;
private double m_accumulatedTime;
@@ -44,7 +46,6 @@ public class Timer {
* @return Robot running time in microseconds.
*/
public static long getUsClock() {
return System.nanoTime() / 1000;
}

View File

@@ -11,47 +11,50 @@ import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
import edu.wpi.first.wpilibj.simulation.SimSpeedController;
import edu.wpi.first.wpilibj.tables.ITable;
import edu.wpi.first.wpilibj.tables.ITableListener;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
/**
* CTRE Talon Speed Controller
* VEX Robotics Victor Speed Controller
*/
public class Victor implements SpeedController, PIDOutput, MotorSafety, LiveWindowSendable {
private int module, channel;
private int channel;
private SimSpeedController impl;
/**
* 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 initTalon(final int slot, final int channel) {
this.module = slot;
private void initVictor(final int channel) {
this.channel = channel;
impl = new SimSpeedController("simulator/pwm/"+slot+"/"+channel);
impl = new SimSpeedController("simulator/pwm/1/"+channel);
m_safetyHelper = new MotorSafetyHelper(this);
m_safetyHelper.setExpiration(0.0);
m_safetyHelper.setSafetyEnabled(false);
// LiveWindow.addActuator("Talon", getModuleNumber(), getChannel(), this);
LiveWindow.addActuator("Victor", channel, this);
// UsageReporting.report(tResourceType.kResourceType_Talon, getChannel(), getModuleNumber()-1);
}
/**
* Constructor that assumes the default digital module.
* Constructor.
*
* @param channel The PWM channel on the digital module that the Victor is attached to.
* @param channel The PWM channel that the Victor is attached to.
*/
public Victor(final int channel) {
initTalon(1, channel);
}
/**
* 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) {
initTalon(slot, channel);
initVictor(channel);
}
/**
@@ -66,7 +69,7 @@ public class Victor implements SpeedController, PIDOutput, MotorSafety, LiveWind
* @param syncGroup The update group to add this Set() to, pending UpdateSyncGroup(). If 0, update immediately.
*/
public void set(double speed, byte syncGroup) {
impl.set(speed, syncGroup);
impl.set(speed, syncGroup);
}
/**
@@ -78,7 +81,7 @@ public class Victor implements SpeedController, PIDOutput, MotorSafety, LiveWind
* @param speed The speed value between -1.0 and 1.0 to set.
*/
public void set(double speed) {
impl.set(speed);
impl.set(speed);
}
/**
@@ -141,7 +144,7 @@ public class Victor implements SpeedController, PIDOutput, MotorSafety, LiveWind
@Override
public String getDescription() {
return "PWM "+channel+" on module "+module;
return "PWM "+channel+" on module 1";
}
//// LiveWindow Methods

View File

@@ -7,6 +7,7 @@
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;
@@ -200,9 +201,9 @@ public abstract class Command implements NamedSendable {
* @return whether or not the command should stay within the {@link Scheduler}.
*/
synchronized boolean run() {
// XXX: if (!m_runWhenDisabled && m_parent == null && DriverStation.getInstance().isDisabled()) {
// XXX: cancel();
// XXX: }
if (!m_runWhenDisabled && m_parent == null && DriverStation.getInstance().isDisabled()) {
cancel();
}
if (isCanceled()) {
return false;
}

View File

@@ -88,7 +88,6 @@ public class Scheduler implements NamedSendable {
* Instantiates a {@link Scheduler}.
*/
private Scheduler() {
// UsageReporting.report(tResourceType.kResourceType_Command, tInstances.kCommand_Scheduler);
}
/**

View File

@@ -1,7 +1,17 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. 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.interfaces;
import edu.wpi.first.wpilibj.PIDSource;
/**
*
* @author alex
*/
public interface Potentiometer extends PIDSource {
double get();
}

View File

@@ -169,24 +169,38 @@ public class LiveWindow {
}
/**
* Add Sensor to LiveWindow. The components are shown with the module type,
* slot and channel like this: Gyro[1, 2] for a gyro object connected to the
* first analog module in channel 2
* Add Sensor to LiveWindow. The components are shown with the type and
* channel like this: Gyro[1] for a gyro object connected to the first
* analog channel.
*
* @param moduleType A string indicating the type of the module used in the
* naming (above)
* @param moduleNumber The number of the particular module type
* @param channel The channel number the device is connected to
* @param component A reference to the object being added
*/
public static void addSensor(String moduleType, int moduleNumber, int channel, LiveWindowSendable component) {
addSensor("Ungrouped", moduleType + "[" + moduleNumber + "," + channel + "]", component);
public static void addSensor(String moduleType, int channel, LiveWindowSendable component) {
addSensor("Ungrouped", moduleType + "[" + channel + "]", component);
if (sensors.contains(component)) {
sensors.removeElement(component);
}
sensors.addElement(component);
}
/**
* Add Actuator to LiveWindow. The components are shown with the module
* type, slot and channel like this: Servo[1,2] for a servo object connected
* to the first digital module and PWM port 2.
*
* @param moduleType A string that defines the module name in the label for
* the value
* @param channel The channel number the device is plugged into (usually
* PWM)
* @param component The reference to the object being added
*/
public static void addActuator(String moduleType, int channel, LiveWindowSendable component) {
addActuator("Ungrouped", moduleType + "[" + channel + "]", component);
}
/**
* Add Actuator to LiveWindow. The components are shown with the module
* type, slot and channel like this: Servo[1,2] for a servo object connected

View File

@@ -0,0 +1,15 @@
/*----------------------------------------------------------------------------*/
/* 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.parsing;
/**
* An IDevice is any WPILibJ object which can be used in the creation of the
* robot program
* @author Ryan O'Meara
*/
public interface IDevice {}

View File

@@ -0,0 +1,15 @@
/*----------------------------------------------------------------------------*/
/* 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.parsing;
/**
* IDeviceController is implemented by control elements in the robot. An
* example of this would be a victor
* @author Ryan O'Meara
*/
public interface IDeviceController extends IDevice {}

View File

@@ -0,0 +1,16 @@
/*----------------------------------------------------------------------------*/
/* 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.parsing;
/**
* IInputOutput is implemented by devices which provide the robot with data and
* allow it to react to its environment. An example of an input/output would be
* a joystick
* @author Ryan O'Meara
*/
public interface IInputOutput extends IDevice {}

View File

@@ -0,0 +1,17 @@
/*----------------------------------------------------------------------------*/
/* 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.parsing;
/**
* The IMechanism interface is implemented by any class to be classified as a
* mechanism. These are user-defined, and contain other devices (which implement
* IDevice). They are generally over-arching systems, such as the drive train or
* arm
* @author Ryan O'Meara
*/
public interface IMechanism {}

View File

@@ -0,0 +1,17 @@
/*----------------------------------------------------------------------------*/
/* 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.parsing;
/**
* ISensor is extended by any WPILibJ class to be categorized as a sensor in the
* java program builder. A sensor is a robot part that provides the robot with
* information about its environment. An example of this is the Ultrasonic
* sensor class
* @author Ryan O'Meara
*/
public interface ISensor extends IDevice {}

View File

@@ -0,0 +1,17 @@
/*----------------------------------------------------------------------------*/
/* 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.parsing;
/**
* IUtility is an interface implemented by any WPILibJ class which should appear
* in the utility tree of the java program builder. A utility is generally a
* class which is not a specific device, but more of a software tool. An
* example of this would be the Timer class
* @author Ryan O'Meara
*/
public interface IUtility extends IDevice {}