Major formatting changes (breaks diffs). No code changes.

The changes made in this commit do not affect any actual code,
    they are purely aesthetic. I ran clang-format with google style
    over all .h/.cpp files in wpilibc that weren't in wpilibC++Sim
    or gtest, and the eclipse formatter over all of the Java files
    using the Google eclipse formatting configuration.

Change-Id: I9627bca0bc103c398ecc1c5ba17467193291ae63
This commit is contained in:
James Kuszmaul
2015-06-25 15:07:55 -04:00
parent bd64d9a7ef
commit 7eb8550bdb
470 changed files with 89798 additions and 77287 deletions

View File

@@ -1,6 +1,6 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
package edu.wpi.first.wpilibj;
@@ -12,14 +12,14 @@ package edu.wpi.first.wpilibj;
* @author alex
*/
interface Controller {
/**
* Allows the control loop to run.
*/
public void enable();
/**
* Allows the control loop to run.
*/
public void enable();
/**
* Stops the control loop from running until explicitly re-enabled by calling
* {@link enable()}.
*/
public void disable();
/**
* Stops the control loop from running until explicitly re-enabled by calling
* {@link enable()}.
*/
public void disable();
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
@@ -12,150 +12,166 @@ package edu.wpi.first.wpilibj;
*/
public abstract class GenericHID {
/**
* Which hand the Human Interface Device is associated with.
*/
public static class Hand {
/**
* Which hand the Human Interface Device is associated with.
* The integer value representing this enumeration
*/
public static class Hand {
public final int value;
static final int kLeft_val = 0;
static final int kRight_val = 1;
/**
* hand: left
*/
public static final Hand kLeft = new Hand(kLeft_val);
/**
* hand: right
*/
public static final Hand kRight = new Hand(kRight_val);
/**
* The integer value representing this enumeration
*/
public final int value;
static final int kLeft_val = 0;
static final int kRight_val = 1;
/**
* hand: left
*/
public static final Hand kLeft = new Hand(kLeft_val);
/**
* hand: right
*/
public static final Hand kRight = new Hand(kRight_val);
private Hand(int value) {
this.value = value;
}
private Hand(int value) {
this.value = value;
}
}
/**
* Get the x position of the HID
* @return the x position of the HID
*/
public final double getX() {
return getX(Hand.kRight);
}
/**
* Get the x position of the HID
*$
* @return the x position of the HID
*/
public final double getX() {
return getX(Hand.kRight);
}
/**
* Get the x position of HID
* @param hand which hand, left or right
* @return the x position
*/
public abstract double getX(Hand hand);
/**
* Get the x position of HID
*$
* @param hand which hand, left or right
* @return the x position
*/
public abstract double getX(Hand hand);
/**
* Get the y position of the HID
* @return the y position
*/
public final double getY() {
return getY(Hand.kRight);
}
/**
* Get the y position of the HID
*$
* @return the y position
*/
public final double getY() {
return getY(Hand.kRight);
}
/**
* Get the y position of the HID
* @param hand which hand, left or right
* @return the y position
*/
public abstract double getY(Hand hand);
/**
* Get the y position of the HID
*$
* @param hand which hand, left or right
* @return the y position
*/
public abstract double getY(Hand hand);
/**
* Get the z position of the HID
* @return the z position
*/
public final double getZ() {
return getZ(Hand.kRight);
}
/**
* Get the z position of the HID
*$
* @return the z position
*/
public final double getZ() {
return getZ(Hand.kRight);
}
/**
* Get the z position of the HID
* @param hand which hand, left or right
* @return the z position
*/
public abstract double getZ(Hand hand);
/**
* Get the z position of the HID
*$
* @param hand which hand, left or right
* @return the z position
*/
public abstract double getZ(Hand hand);
/**
* Get the twist value
* @return the twist value
*/
public abstract double getTwist();
/**
* Get the twist value
*$
* @return the twist value
*/
public abstract double getTwist();
/**
* Get the throttle
* @return the throttle value
*/
public abstract double getThrottle();
/**
* Get the throttle
*$
* @return the throttle value
*/
public abstract double getThrottle();
/**
* Get the raw axis
* @param which index of the axis
* @return the raw value of the selected axis
*/
public abstract double getRawAxis(int which);
/**
* Get the raw axis
*$
* @param which index of the axis
* @return the raw value of the selected axis
*/
public abstract double getRawAxis(int which);
/**
* Is the trigger pressed
* @return true if pressed
*/
public final boolean getTrigger() {
return getTrigger(Hand.kRight);
}
/**
* Is the trigger pressed
*$
* @return true if pressed
*/
public final boolean getTrigger() {
return getTrigger(Hand.kRight);
}
/**
* Is the trigger pressed
* @param hand which hand
* @return true if the trigger for the given hand is pressed
*/
public abstract boolean getTrigger(Hand hand);
/**
* Is the trigger pressed
*$
* @param hand which hand
* @return true if the trigger for the given hand is pressed
*/
public abstract boolean getTrigger(Hand hand);
/**
* Is the top button pressed
* @return true if the top button is pressed
*/
public final boolean getTop() {
return getTop(Hand.kRight);
}
/**
* Is the top button pressed
*$
* @return true if the top button is pressed
*/
public final boolean getTop() {
return getTop(Hand.kRight);
}
/**
* Is the top button pressed
* @param hand which hand
* @return true if hte top button for the given hand is pressed
*/
public abstract boolean getTop(Hand hand);
/**
* Is the top button pressed
*$
* @param hand which hand
* @return true if hte top button for the given hand is pressed
*/
public abstract boolean getTop(Hand hand);
/**
* Is the bumper pressed
* @return true if the bumper is pressed
*/
public final boolean getBumper() {
return getBumper(Hand.kRight);
}
/**
* Is the bumper pressed
*$
* @return true if the bumper is pressed
*/
public final boolean getBumper() {
return getBumper(Hand.kRight);
}
/**
* Is the bumper pressed
* @param hand which hand
* @return true if hte bumper is pressed
*/
public abstract boolean getBumper(Hand hand);
/**
* Is the bumper pressed
*$
* @param hand which hand
* @return true if hte bumper is pressed
*/
public abstract boolean getBumper(Hand hand);
/**
* Is the given button pressed
* @param button which button number
* @return true if the button is pressed
*/
public abstract boolean getRawButton(int button);
/**
* Is the given button pressed
*$
* @param button which button number
* @return true if the button is pressed
*/
public abstract boolean getRawButton(int button);
public abstract int getPOV(int pov);
public abstract int getPOV(int pov);
public int getPOV() {
return getPOV(0);
}
public int getPOV() {
return getPOV(0);
}
}

View File

@@ -8,45 +8,49 @@ import edu.wpi.first.wpilibj.util.BaseSystemNotInitializedException;
* @author alex
*/
public class HLUsageReporting {
private static Interface impl;
private static Interface impl;
public static void SetImplementation(Interface i) {
impl = i;
}
public static void SetImplementation(Interface i) {
impl = i;
}
public static void reportScheduler() {
if (impl != null) {
impl.reportScheduler();
} else {
throw new BaseSystemNotInitializedException(Interface.class, HLUsageReporting.class);
}
}
public static void reportScheduler() {
if (impl != null) {
impl.reportScheduler();
} else {
throw new BaseSystemNotInitializedException(Interface.class, HLUsageReporting.class);
}
}
public static void reportPIDController(int num) {
if (impl != null) {
impl.reportPIDController(num);
} else {
throw new BaseSystemNotInitializedException(Interface.class, HLUsageReporting.class);
}
}
public static void reportPIDController(int num) {
if (impl != null) {
impl.reportPIDController(num);
} else {
throw new BaseSystemNotInitializedException(Interface.class, HLUsageReporting.class);
}
}
public static void reportSmartDashboard() {
if(impl != null) {
impl.reportSmartDashboard();
} else {
throw new BaseSystemNotInitializedException(Interface.class, HLUsageReporting.class);
}
}
public static void reportSmartDashboard() {
if (impl != null) {
impl.reportSmartDashboard();
} else {
throw new BaseSystemNotInitializedException(Interface.class, HLUsageReporting.class);
}
}
public interface Interface {
void reportScheduler();
void reportPIDController(int num);
void reportSmartDashboard();
}
public interface Interface {
void reportScheduler();
public static class Null implements Interface {
public void reportScheduler() {}
public void reportPIDController(int num) {}
public void reportSmartDashboard() {}
}
void reportPIDController(int num);
void reportSmartDashboard();
}
public static class Null implements Interface {
public void reportScheduler() {}
public void reportPIDController(int num) {}
public void reportSmartDashboard() {}
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
@@ -12,12 +12,19 @@ package edu.wpi.first.wpilibj;
* @author brad
*/
public interface MotorSafety {
public static final double DEFAULT_SAFETY_EXPIRATION = 0.1;
void setExpiration(double timeout);
double getExpiration();
boolean isAlive();
void stopMotor();
void setSafetyEnabled(boolean enabled);
boolean isSafetyEnabled();
String getDescription();
public static final double DEFAULT_SAFETY_EXPIRATION = 0.1;
void setExpiration(double timeout);
double getExpiration();
boolean isAlive();
void stopMotor();
void setSafetyEnabled(boolean enabled);
boolean isSafetyEnabled();
String getDescription();
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
@@ -10,116 +10,123 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.wpilibj.Timer;
/**
* The MotorSafetyHelper object is constructed for every object that wants to implement the Motor
* Safety protocol. The helper object has the code to actually do the timing and call the
* motors Stop() method when the timeout expires. The motor object is expected to call the
* Feed() method whenever the motors value is updated.
* The MotorSafetyHelper object is constructed for every object that wants to
* implement the Motor Safety protocol. The helper object has the code to
* actually do the timing and call the motors Stop() method when the timeout
* expires. The motor object is expected to call the Feed() method whenever the
* motors value is updated.
*
* @author brad
*/
public class MotorSafetyHelper {
double m_expiration;
boolean m_enabled;
double m_stopTime;
MotorSafety m_safeObject;
MotorSafetyHelper m_nextHelper;
static MotorSafetyHelper m_headHelper = null;
double m_expiration;
boolean m_enabled;
double m_stopTime;
MotorSafety m_safeObject;
MotorSafetyHelper m_nextHelper;
static MotorSafetyHelper m_headHelper = null;
/**
* The constructor for a MotorSafetyHelper object.
* The helper object is constructed for every object that wants to implement the Motor
* Safety protocol. The helper object has the code to actually do the timing and call the
* motors Stop() method when the timeout expires. The motor object is expected to call the
* Feed() method whenever the motors value is updated.
*
* @param safeObject a pointer to the motor object implementing MotorSafety. This is used
* to call the Stop() method on the motor.
*/
public MotorSafetyHelper(MotorSafety safeObject) {
m_safeObject = safeObject;
m_enabled = false;
m_expiration = MotorSafety.DEFAULT_SAFETY_EXPIRATION;
m_stopTime = Timer.getFPGATimestamp();
m_nextHelper = m_headHelper;
m_headHelper = this;
/**
* The constructor for a MotorSafetyHelper object. The helper object is
* constructed for every object that wants to implement the Motor Safety
* protocol. The helper object has the code to actually do the timing and call
* the motors Stop() method when the timeout expires. The motor object is
* expected to call the Feed() method whenever the motors value is updated.
*
* @param safeObject a pointer to the motor object implementing MotorSafety.
* This is used to call the Stop() method on the motor.
*/
public MotorSafetyHelper(MotorSafety safeObject) {
m_safeObject = safeObject;
m_enabled = false;
m_expiration = MotorSafety.DEFAULT_SAFETY_EXPIRATION;
m_stopTime = Timer.getFPGATimestamp();
m_nextHelper = m_headHelper;
m_headHelper = this;
}
/**
* Feed the motor safety object. Resets the timer on this object that is used
* to do the timeouts.
*/
public void feed() {
m_stopTime = Timer.getFPGATimestamp() + m_expiration;
}
/**
* Set the expiration time for the corresponding motor safety object.
*$
* @param expirationTime The timeout value in seconds.
*/
public void setExpiration(double expirationTime) {
m_expiration = expirationTime;
}
/**
* Retrieve the timeout value for the corresponding motor safety object.
*$
* @return the timeout value in seconds.
*/
public double getExpiration() {
return m_expiration;
}
/**
* Determine of the motor is still operating or has timed out.
*$
* @return a true value if the motor is still operating normally and hasn't
* timed out.
*/
public boolean isAlive() {
return !m_enabled || m_stopTime > Timer.getFPGATimestamp();
}
/**
* Check if this motor has exceeded its timeout. This method is called
* periodically to determine if this motor has exceeded its timeout value. If
* it has, the stop method is called, and the motor is shut down until its
* value is updated again.
*/
public void check() {
if (!m_enabled || RobotState.isDisabled() || RobotState.isTest())
return;
if (m_stopTime < Timer.getFPGATimestamp()) {
System.err.println(m_safeObject.getDescription() + "... Output not updated often enough.");
m_safeObject.stopMotor();
}
}
/**
* Feed the motor safety object.
* Resets the timer on this object that is used to do the timeouts.
*/
public void feed() {
m_stopTime = Timer.getFPGATimestamp() + m_expiration;
}
/**
* Set the expiration time for the corresponding motor safety object.
* @param expirationTime The timeout value in seconds.
*/
public void setExpiration(double expirationTime) {
m_expiration = expirationTime;
}
/**
* Retrieve the timeout value for the corresponding motor safety object.
* @return the timeout value in seconds.
*/
public double getExpiration() {
return m_expiration;
}
/**
* Determine of the motor is still operating or has timed out.
* @return a true value if the motor is still operating normally and hasn't timed out.
*/
public boolean isAlive() {
return !m_enabled || m_stopTime > Timer.getFPGATimestamp();
}
/**
* Check if this motor has exceeded its timeout.
* This method is called periodically to determine if this motor has exceeded its timeout
* value. If it has, the stop method is called, and the motor is shut down until its value is
* updated again.
*/
public void check() {
if (!m_enabled || RobotState.isDisabled() || RobotState.isTest())
return;
if (m_stopTime < Timer.getFPGATimestamp()) {
System.err.println(m_safeObject.getDescription() + "... Output not updated often enough.");
m_safeObject.stopMotor();
}
}
/**
* Enable/disable motor safety for this device
* Turn on and off the motor safety option for this PWM object.
* @param enabled True if motor safety is enforced for this object
*/
public void setSafetyEnabled(boolean enabled) {
m_enabled = enabled;
}
/**
* Return the state of the motor safety enabled flag
* Return if the motor safety is currently enabled for this devicce.
* @return True if motor safety is enforced for this device
*/
public boolean isSafetyEnabled() {
return m_enabled;
}
/**
* Check the motors to see if any have timed out.
* This static method is called periodically to poll all the motors and stop any that have
* timed out.
*/
//TODO: these should be synchronized with the setting methods in case it's called from a different thread
public static void checkMotors() {
for (MotorSafetyHelper msh = m_headHelper; msh != null; msh = msh.m_nextHelper) {
msh.check();
}
/**
* Enable/disable motor safety for this device Turn on and off the motor
* safety option for this PWM object.
*$
* @param enabled True if motor safety is enforced for this object
*/
public void setSafetyEnabled(boolean enabled) {
m_enabled = enabled;
}
/**
* Return the state of the motor safety enabled flag Return if the motor
* safety is currently enabled for this devicce.
*$
* @return True if motor safety is enforced for this device
*/
public boolean isSafetyEnabled() {
return m_enabled;
}
/**
* Check the motors to see if any have timed out. This static method is called
* periodically to poll all the motors and stop any that have timed out.
*/
// TODO: these should be synchronized with the setting methods in case it's
// called from a different thread
public static void checkMotors() {
for (MotorSafetyHelper msh = m_headHelper; msh != null; msh = msh.m_nextHelper) {
msh.check();
}
}
}

View File

@@ -2,13 +2,15 @@ package edu.wpi.first.wpilibj;
/**
* The interface for sendable objects that gives the sendable a default name in the Smart Dashboard
* The interface for sendable objects that gives the sendable a default name in
* the Smart Dashboard
*
*/
public interface NamedSendable extends Sendable {
/**
* @return the name of the subtable of SmartDashboard that the Sendable object will use
*/
public String getName();
/**
* @return the name of the subtable of SmartDashboard that the Sendable object
* will use
*/
public String getName();
}

View File

@@ -2,15 +2,25 @@ package edu.wpi.first.wpilibj;
public interface PIDInterface extends Controller {
public void setPID(double p, double i, double d);
public double getP();
public double getI();
public double getD();
public void setSetpoint(double setpoint);
public double getSetpoint();
public double getError();
public void enable();
public void disable();
public boolean isEnabled();
public void reset();
public void setPID(double p, double i, double d);
public double getP();
public double getI();
public double getD();
public void setSetpoint(double setpoint);
public double getSetpoint();
public double getError();
public void enable();
public void disable();
public boolean isEnabled();
public void reset();
}

View File

@@ -1,21 +1,23 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
/**
* This interface allows PIDController to write it's results to its output.
*$
* @author dtjones
*/
public interface PIDOutput {
/**
* Set the output to the value calculated by PIDController
* @param output the value calculated by PIDController
*/
public void pidWrite(double output);
/**
* Set the output to the value calculated by PIDController
*$
* @param output the value calculated by PIDController
*/
public void pidWrite(double output);
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
@@ -10,30 +10,32 @@ package edu.wpi.first.wpilibj;
/**
* This interface allows for PIDController to automatically read from this
* object
*$
* @author dtjones
*/
public interface PIDSource {
/**
* A description for the type of output value to provide to a PIDController
*/
public static class PIDSourceParameter {
public final int value;
static final int kDistance_val = 0;
static final int kRate_val = 1;
static final int kAngle_val = 2;
public static final PIDSourceParameter kDistance = new PIDSourceParameter(kDistance_val);
public static final PIDSourceParameter kRate = new PIDSourceParameter(kRate_val);
public static final PIDSourceParameter kAngle = new PIDSourceParameter(kAngle_val);
/**
* A description for the type of output value to provide to a PIDController
*/
public static class PIDSourceParameter {
public final int value;
static final int kDistance_val = 0;
static final int kRate_val = 1;
static final int kAngle_val = 2;
public static final PIDSourceParameter kDistance = new PIDSourceParameter(kDistance_val);
public static final PIDSourceParameter kRate = new PIDSourceParameter(kRate_val);
public static final PIDSourceParameter kAngle = new PIDSourceParameter(kAngle_val);
private PIDSourceParameter(int value) {
this.value = value;
}
private PIDSourceParameter(int value) {
this.value = value;
}
}
/**
* Get the result to use in PIDController
* @return the result to use in PIDController
*/
public double pidGet();
/**
* Get the result to use in PIDController
*$
* @return the result to use in PIDController
*/
public double pidGet();
}

View File

@@ -3,57 +3,61 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.wpilibj.util.BaseSystemNotInitializedException;
public class RobotState {
private static Interface impl;
private static Interface impl;
public static void SetImplementation(Interface i) {
impl = i;
}
public static void SetImplementation(Interface i) {
impl = i;
}
public static boolean isDisabled() {
if (impl != null) {
return impl.isDisabled();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
public static boolean isDisabled() {
if (impl != null) {
return impl.isDisabled();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
public static boolean isEnabled() {
if (impl != null) {
return impl.isEnabled();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
public static boolean isEnabled() {
if (impl != null) {
return impl.isEnabled();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
public static boolean isOperatorControl() {
if (impl != null) {
return impl.isOperatorControl();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
public static boolean isOperatorControl() {
if (impl != null) {
return impl.isOperatorControl();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
public static boolean isAutonomous() {
if (impl != null) {
return impl.isAutonomous();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
public static boolean isAutonomous() {
if (impl != null) {
return impl.isAutonomous();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
public static boolean isTest() {
if (impl != null) {
return impl.isTest();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
public static boolean isTest() {
if (impl != null) {
return impl.isTest();
} else {
throw new BaseSystemNotInitializedException(Interface.class, RobotState.class);
}
}
interface Interface {
boolean isDisabled();
boolean isEnabled();
boolean isOperatorControl();
boolean isAutonomous();
boolean isTest();
}
interface Interface {
boolean isDisabled();
boolean isEnabled();
boolean isOperatorControl();
boolean isAutonomous();
boolean isTest();
}
}

View File

@@ -4,23 +4,25 @@ import edu.wpi.first.wpilibj.tables.ITable;
/**
* The base interface for objects that can be sent over the network
* through network tables.
* The base interface for objects that can be sent over the network through
* network tables.
*/
public interface Sendable {
/**
* Initializes a table for this sendable object.
* @param subtable The table to put the values in.
*/
public void initTable(ITable subtable);
/**
* Initializes a table for this sendable object.
*$
* @param subtable The table to put the values in.
*/
public void initTable(ITable subtable);
/**
* @return the table that is currently associated with the sendable
*/
public ITable getTable();
/**
* @return the table that is currently associated with the sendable
*/
public ITable getTable();
/**
* @return the string representation of the named data type that will be used by the smart dashboard for this sendable
*/
public String getSmartDashboardType();
/**
* @return the string representation of the named data type that will be used
* by the smart dashboard for this sendable
*/
public String getSmartDashboardType();
}

View File

@@ -3,169 +3,170 @@ package edu.wpi.first.wpilibj;
import edu.wpi.first.wpilibj.util.BaseSystemNotInitializedException;
public class Timer {
private static StaticInterface impl;
private static StaticInterface impl;
public static void SetImplementation(StaticInterface ti) {
impl = ti;
}
public static void SetImplementation(StaticInterface ti) {
impl = ti;
}
/**
* Return the system clock time in seconds. Return the time from the
* FPGA hardware clock in seconds since the FPGA started.
*
* @return Robot running time in seconds.
*/
public static double getFPGATimestamp() {
if (impl != null) {
return impl.getFPGATimestamp();
} else {
throw new BaseSystemNotInitializedException(StaticInterface.class, Timer.class);
}
}
/**
* Return the system clock time in seconds. Return the time from the FPGA
* hardware clock in seconds since the FPGA started.
*
* @return Robot running time in seconds.
*/
public static double getFPGATimestamp() {
if (impl != null) {
return impl.getFPGATimestamp();
} else {
throw new BaseSystemNotInitializedException(StaticInterface.class, Timer.class);
}
}
/**
* 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 static double getMatchTime() {
if (impl != null) {
return impl.getMatchTime();
} else {
throw new BaseSystemNotInitializedException(StaticInterface.class, Timer.class);
}
}
/**
* 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 static double getMatchTime() {
if (impl != null) {
return impl.getMatchTime();
} else {
throw new BaseSystemNotInitializedException(StaticInterface.class, Timer.class);
}
}
/**
* Pause the thread for a specified time. Pause the execution of the
* thread for a specified period of time given in seconds. Motors will
* continue to run at their last assigned values, and sensors will continue
* to update. Only the task containing the wait will pause until the wait
* time is expired.
*
* @param seconds Length of time to pause
*/
public static void delay(final double seconds) {
if (impl != null) {
impl.delay(seconds);
} else {
throw new BaseSystemNotInitializedException(StaticInterface.class, Timer.class);
}
}
/**
* Pause the thread for a specified time. Pause the execution of the thread
* for a specified period of time given in seconds. Motors will continue to
* run at their last assigned values, and sensors will continue to update.
* Only the task containing the wait will pause until the wait time is
* expired.
*
* @param seconds Length of time to pause
*/
public static void delay(final double seconds) {
if (impl != null) {
impl.delay(seconds);
} else {
throw new BaseSystemNotInitializedException(StaticInterface.class, Timer.class);
}
}
public interface StaticInterface {
double getFPGATimestamp();
double getMatchTime();
void delay(final double seconds);
Interface newTimer();
}
public interface StaticInterface {
double getFPGATimestamp();
private final Interface timer;
public Timer() {
if(impl != null){
timer = impl.newTimer();
} else {
throw new BaseSystemNotInitializedException(StaticInterface.class, Timer.class);
}
}
double getMatchTime();
/**
* Get the current time from the timer. If the clock is running it is derived from
* the current system clock the start time stored in the timer class. If the clock
* is not running, then return the time when it was last stopped.
*
* @return Current time value for this timer in seconds
*/
public double get() {
return timer.get();
}
void delay(final double seconds);
/**
* Reset the timer by setting the time to 0.
* Make the timer startTime the current time so new requests will be relative now
*/
public void reset() {
timer.reset();
}
Interface newTimer();
}
/**
* Start the timer running.
* Just set the running flag to true indicating that all time requests should be
* relative to the system clock.
*/
public void start() {
timer.start();
}
private final Interface timer;
/**
* Stop the timer.
* This computes the time as of now and clears the running flag, causing all
* subsequent time requests to be read from the accumulated time rather than
* looking at the system clock.
*/
public void stop() {
timer.stop();
}
public Timer() {
if (impl != null) {
timer = impl.newTimer();
} else {
throw new BaseSystemNotInitializedException(StaticInterface.class, Timer.class);
}
}
/**
* Check if the period specified has passed and if it has, advance the start
* time by that period. This is useful to decide if it's time to do periodic
* work without drifting later by the time it took to get around to checking.
*
* @param period The period to check for (in seconds).
* @return If the period has passed.
*/
public boolean hasPeriodPassed(double period)
{
return timer.hasPeriodPassed(period);
}
/**
* Get the current time from the timer. If the clock is running it is derived
* from the current system clock the start time stored in the timer class. If
* the clock is not running, then return the time when it was last stopped.
*
* @return Current time value for this timer in seconds
*/
public double get() {
return timer.get();
}
public interface Interface {
/**
* Get the current time from the timer. If the clock is running it is derived from
* the current system clock the start time stored in the timer class. If the clock
* is not running, then return the time when it was last stopped.
*
* @return Current time value for this timer in seconds
*/
public double get();
/**
* Reset the timer by setting the time to 0. Make the timer startTime the
* current time so new requests will be relative now
*/
public void reset() {
timer.reset();
}
/**
* Reset the timer by setting the time to 0.
* Make the timer startTime the current time so new requests will be relative now
*/
public void reset();
/**
* Start the timer running. Just set the running flag to true indicating that
* all time requests should be relative to the system clock.
*/
public void start() {
timer.start();
}
/**
* Start the timer running.
* Just set the running flag to true indicating that all time requests should be
* relative to the system clock.
*/
public void start();
/**
* Stop the timer. This computes the time as of now and clears the running
* flag, causing all subsequent time requests to be read from the accumulated
* time rather than looking at the system clock.
*/
public void stop() {
timer.stop();
}
/**
* Stop the timer.
* This computes the time as of now and clears the running flag, causing all
* subsequent time requests to be read from the accumulated time rather than
* looking at the system clock.
*/
public void stop();
/**
* Check if the period specified has passed and if it has, advance the start
* time by that period. This is useful to decide if it's time to do periodic
* work without drifting later by the time it took to get around to checking.
*
* @param period The period to check for (in seconds).
* @return If the period has passed.
*/
public boolean hasPeriodPassed(double period) {
return timer.hasPeriodPassed(period);
}
public interface Interface {
/**
* Get the current time from the timer. If the clock is running it is
* derived from the current system clock the start time stored in the timer
* class. If the clock is not running, then return the time when it was last
* stopped.
*
* @return Current time value for this timer in seconds
*/
public double get();
/**
* Reset the timer by setting the time to 0. Make the timer startTime the
* current time so new requests will be relative now
*/
public void reset();
/**
* Start the timer running. Just set the running flag to true indicating
* that all time requests should be relative to the system clock.
*/
public void start();
/**
* Stop the timer. This computes the time as of now and clears the running
* flag, causing all subsequent time requests to be read from the
* accumulated time rather than looking at the system clock.
*/
public void stop();
/**
* Check if the period specified has passed and if it has, advance the start
* time by that period. This is useful to decide if it's time to do periodic
* work without drifting later by the time it took to get around to checking.
*
* @param period The period to check for (in seconds).
* @return If the period has passed.
*/
public boolean hasPeriodPassed(double period);
}
/**
* Check if the period specified has passed and if it has, advance the start
* time by that period. This is useful to decide if it's time to do periodic
* work without drifting later by the time it took to get around to
* checking.
*
* @param period The period to check for (in seconds).
* @return If the period has passed.
*/
public boolean hasPeriodPassed(double period);
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.buttons;
@@ -12,59 +12,63 @@ import edu.wpi.first.wpilibj.command.Command;
/**
* This class provides an easy way to link commands to OI inputs.
*
* It is very easy to link a button to a command. For instance, you could
* link the trigger button of a joystick to a "score" command.
* It is very easy to link a button to a command. For instance, you could link
* the trigger button of a joystick to a "score" command.
*
* This class represents a subclass of Trigger that is specifically aimed at
* buttons on an operator interface as a common use case of the more generalized
* Trigger objects. This is a simple wrapper around Trigger with the method names
* renamed to fit the Button object use.
* Trigger objects. This is a simple wrapper around Trigger with the method
* names renamed to fit the Button object use.
*
* @author brad
*/
public abstract class Button extends Trigger {
/**
* Starts the given command whenever the button is newly pressed.
* @param command the command to start
*/
public void whenPressed(final Command command) {
whenActive(command);
}
/**
* Starts the given command whenever the button is newly pressed.
*$
* @param command the command to start
*/
public void whenPressed(final Command command) {
whenActive(command);
}
/**
* Constantly starts the given command while the button is held.
*
* {@link Command#start()} will be called repeatedly while the button is held,
* and will be canceled when the button is released.
*
* @param command the command to start
*/
public void whileHeld(final Command command) {
whileActive(command);
}
/**
* Constantly starts the given command while the button is held.
*
* {@link Command#start()} will be called repeatedly while the button is held,
* and will be canceled when the button is released.
*
* @param command the command to start
*/
public void whileHeld(final Command command) {
whileActive(command);
}
/**
* Starts the command when the button is released
* @param command the command to start
*/
public void whenReleased(final Command command) {
whenInactive(command);
}
/**
* Starts the command when the button is released
*$
* @param command the command to start
*/
public void whenReleased(final Command command) {
whenInactive(command);
}
/**
* Toggles the command whenever the button is pressed (on then off then on)
* @param command the command to start
*/
public void toggleWhenPressed(final Command command) {
toggleWhenActive(command);
}
/**
* Toggles the command whenever the button is pressed (on then off then on)
*$
* @param command the command to start
*/
public void toggleWhenPressed(final Command command) {
toggleWhenActive(command);
}
/**
* Cancel the command when the button is pressed
* @param command the command to start
*/
public void cancelWhenPressed(final Command command) {
cancelWhenActive(command);
}
/**
* Cancel the command when the button is pressed
*$
* @param command the command to start
*/
public void cancelWhenPressed(final Command command) {
cancelWhenActive(command);
}
}

View File

@@ -1,48 +1,50 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.buttons;
/**
* This class is intended to be used within a program. The programmer can manually set its value.
* Also includes a setting for whether or not it should invert its value.
* This class is intended to be used within a program. The programmer can
* manually set its value. Also includes a setting for whether or not it should
* invert its value.
*
* @author Joe
*/
public class InternalButton extends Button {
boolean pressed;
boolean inverted;
boolean pressed;
boolean inverted;
/**
* Creates an InternalButton that is not inverted.
*/
public InternalButton() {
this(false);
}
/**
* Creates an InternalButton that is not inverted.
*/
public InternalButton() {
this(false);
}
/**
* Creates an InternalButton which is inverted depending on the input.
*
* @param inverted if false, then this button is pressed when set to true, otherwise it is pressed when set to false.
*/
public InternalButton(boolean inverted) {
this.pressed = this.inverted = inverted;
}
/**
* Creates an InternalButton which is inverted depending on the input.
*
* @param inverted if false, then this button is pressed when set to true,
* otherwise it is pressed when set to false.
*/
public InternalButton(boolean inverted) {
this.pressed = this.inverted = inverted;
}
public void setInverted(boolean inverted) {
this.inverted = inverted;
}
public void setInverted(boolean inverted) {
this.inverted = inverted;
}
public void setPressed(boolean pressed) {
this.pressed = pressed;
}
public void setPressed(boolean pressed) {
this.pressed = pressed;
}
public boolean get() {
return pressed ^ inverted;
}
public boolean get() {
return pressed ^ inverted;
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.buttons;
@@ -15,24 +15,28 @@ import edu.wpi.first.wpilibj.GenericHID;
*/
public class JoystickButton extends Button {
GenericHID m_joystick;
int m_buttonNumber;
GenericHID m_joystick;
int m_buttonNumber;
/**
* Create a joystick button for triggering commands
* @param joystick The GenericHID object that has the button (e.g. Joystick, KinectStick, etc)
* @param buttonNumber The button number (see {@link GenericHID#getRawButton(int) }
*/
public JoystickButton(GenericHID joystick, int buttonNumber) {
m_joystick = joystick;
m_buttonNumber = buttonNumber;
}
/**
* Create a joystick button for triggering commands
*$
* @param joystick The GenericHID object that has the button (e.g. Joystick,
* KinectStick, etc)
* @param buttonNumber The button number (see
* {@link GenericHID#getRawButton(int) }
*/
public JoystickButton(GenericHID joystick, int buttonNumber) {
m_joystick = joystick;
m_buttonNumber = buttonNumber;
}
/**
* Gets the value of the joystick button
* @return The value of the joystick button
*/
public boolean get() {
return m_joystick.getRawButton(m_buttonNumber);
}
/**
* Gets the value of the joystick button
*$
* @return The value of the joystick button
*/
public boolean get() {
return m_joystick.getRawButton(m_buttonNumber);
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.buttons;
@@ -15,19 +15,19 @@ import edu.wpi.first.wpilibj.networktables.NetworkTable;
*/
public class NetworkButton extends Button {
NetworkTable table;
String field;
NetworkTable table;
String field;
public NetworkButton(String table, String field) {
this(NetworkTable.getTable(table), field);
}
public NetworkButton(String table, String field) {
this(NetworkTable.getTable(table), field);
}
public NetworkButton(NetworkTable table, String field) {
this.table = table;
this.field = field;
}
public NetworkButton(NetworkTable table, String field) {
this.table = table;
this.field = field;
}
public boolean get() {
return table.isConnected() && table.getBoolean(field, false);
}
public boolean get() {
return table.isConnected() && table.getBoolean(field, false);
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.buttons;
@@ -15,186 +15,200 @@ import edu.wpi.first.wpilibj.tables.ITable;
/**
* This class provides an easy way to link commands to inputs.
*
* It is very easy to link a button to a command. For instance, you could
* link the trigger button of a joystick to a "score" command.
* It is very easy to link a button to a command. For instance, you could link
* the trigger button of a joystick to a "score" command.
*
* It is encouraged that teams write a subclass of Trigger if they want to have
* something unusual (for instance, if they want to react to the user holding
* a button while the robot is reading a certain sensor input). For this, they
* only have to write the {@link Trigger#get()} method to get the full functionality
* of the Trigger class.
* something unusual (for instance, if they want to react to the user holding a
* button while the robot is reading a certain sensor input). For this, they
* only have to write the {@link Trigger#get()} method to get the full
* functionality of the Trigger class.
*
* @author Joe Grinstead
*/
public abstract class Trigger implements Sendable {
/**
* Returns whether or not the trigger is active
*
* This method will be called repeatedly a command is linked to the Trigger.
*
* @return whether or not the trigger condition is active.
*/
public abstract boolean get();
/**
* Returns whether or not the trigger is active
*
* This method will be called repeatedly a command is linked to the Trigger.
*
* @return whether or not the trigger condition is active.
*/
public abstract boolean get();
/**
* Returns whether get() return true or the internal table for SmartDashboard use is pressed.
* @return whether get() return true or the internal table for SmartDashboard use is pressed
*/
private boolean grab() {
return get() || (table != null /*&& table.isConnected()*/ && table.getBoolean("pressed", false));//FIXME make is connected work?
}
/**
* Returns whether get() return true or the internal table for SmartDashboard
* use is pressed.
*$
* @return whether get() return true or the internal table for SmartDashboard
* use is pressed
*/
private boolean grab() {
return get()
|| (table != null /* && table.isConnected() */&& table.getBoolean("pressed", false));// FIXME
// make
// is
// connected
// work?
}
/**
* Starts the given command whenever the trigger just becomes active.
* @param command the command to start
*/
public void whenActive(final Command command) {
new ButtonScheduler() {
/**
* Starts the given command whenever the trigger just becomes active.
*$
* @param command the command to start
*/
public void whenActive(final Command command) {
new ButtonScheduler() {
boolean pressedLast = grab();
boolean pressedLast = grab();
public void execute() {
if (grab()) {
if (!pressedLast) {
pressedLast = true;
command.start();
}
} else {
pressedLast = false;
}
}
} .start();
}
/**
* Constantly starts the given command while the button is held.
*
* {@link Command#start()} will be called repeatedly while the trigger is active,
* and will be canceled when the trigger becomes inactive.
*
* @param command the command to start
*/
public void whileActive(final Command command) {
new ButtonScheduler() {
boolean pressedLast = grab();
public void execute() {
if (grab()) {
pressedLast = true;
command.start();
} else {
if (pressedLast) {
pressedLast = false;
command.cancel();
}
}
}
} .start();
}
/**
* Starts the command when the trigger becomes inactive
* @param command the command to start
*/
public void whenInactive(final Command command) {
new ButtonScheduler() {
boolean pressedLast = grab();
public void execute() {
if (grab()) {
pressedLast = true;
} else {
if (pressedLast) {
pressedLast = false;
command.start();
}
}
}
} .start();
}
/**
* Toggles a command when the trigger becomes active
* @param command the command to toggle
*/
public void toggleWhenActive(final Command command) {
new ButtonScheduler() {
boolean pressedLast = grab();
public void execute() {
if (grab()) {
if (!pressedLast) {
pressedLast = true;
if (command.isRunning()) {
command.cancel();
} else {
command.start();
}
}
} else {
pressedLast = false;
}
}
} .start();
}
/**
* Cancels a command when the trigger becomes active
* @param command the command to cancel
*/
public void cancelWhenActive(final Command command) {
new ButtonScheduler() {
boolean pressedLast = grab();
public void execute() {
if (grab()) {
if (!pressedLast) {
pressedLast = true;
command.cancel();
}
} else {
pressedLast = false;
}
}
} .start();
}
/**
* An internal class of {@link Trigger}. The user should ignore this, it is
* only public to interface between packages.
*/
public abstract class ButtonScheduler {
public abstract void execute();
protected void start() {
Scheduler.getInstance().addButton(this);
public void execute() {
if (grab()) {
if (!pressedLast) {
pressedLast = true;
command.start();
}
} else {
pressedLast = false;
}
}
}
}.start();
}
/**
* These methods continue to return the "Button" SmartDashboard type until we decided
* to create a Trigger widget type for the dashboard.
*/
public String getSmartDashboardType() {
return "Button";
}
private ITable table;
public void initTable(ITable table) {
this.table = table;
if(table!=null) {
table.putBoolean("pressed", get());
/**
* Constantly starts the given command while the button is held.
*
* {@link Command#start()} will be called repeatedly while the trigger is
* active, and will be canceled when the trigger becomes inactive.
*
* @param command the command to start
*/
public void whileActive(final Command command) {
new ButtonScheduler() {
boolean pressedLast = grab();
public void execute() {
if (grab()) {
pressedLast = true;
command.start();
} else {
if (pressedLast) {
pressedLast = false;
command.cancel();
}
}
}
}
}.start();
}
/**
* {@inheritDoc}
*/
public ITable getTable() {
return table;
/**
* Starts the command when the trigger becomes inactive
*$
* @param command the command to start
*/
public void whenInactive(final Command command) {
new ButtonScheduler() {
boolean pressedLast = grab();
public void execute() {
if (grab()) {
pressedLast = true;
} else {
if (pressedLast) {
pressedLast = false;
command.start();
}
}
}
}.start();
}
/**
* Toggles a command when the trigger becomes active
*$
* @param command the command to toggle
*/
public void toggleWhenActive(final Command command) {
new ButtonScheduler() {
boolean pressedLast = grab();
public void execute() {
if (grab()) {
if (!pressedLast) {
pressedLast = true;
if (command.isRunning()) {
command.cancel();
} else {
command.start();
}
}
} else {
pressedLast = false;
}
}
}.start();
}
/**
* Cancels a command when the trigger becomes active
*$
* @param command the command to cancel
*/
public void cancelWhenActive(final Command command) {
new ButtonScheduler() {
boolean pressedLast = grab();
public void execute() {
if (grab()) {
if (!pressedLast) {
pressedLast = true;
command.cancel();
}
} else {
pressedLast = false;
}
}
}.start();
}
/**
* An internal class of {@link Trigger}. The user should ignore this, it is
* only public to interface between packages.
*/
public abstract class ButtonScheduler {
public abstract void execute();
protected void start() {
Scheduler.getInstance().addButton(this);
}
}
/**
* These methods continue to return the "Button" SmartDashboard type until we
* decided to create a Trigger widget type for the dashboard.
*/
public String getSmartDashboardType() {
return "Button";
}
private ITable table;
public void initTable(ITable table) {
this.table = table;
if (table != null) {
table.putBoolean("pressed", get());
}
}
/**
* {@inheritDoc}
*/
public ITable getTable() {
return table;
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
@@ -13,17 +13,25 @@ import java.util.Vector;
/**
* A {@link CommandGroup} is a list of commands which are executed in sequence.
*
* <p>Commands in a {@link CommandGroup} are added using the {@link CommandGroup#addSequential(Command) addSequential(...)} method
* and are called sequentially.
* {@link CommandGroup CommandGroups} are themselves {@link Command commands}
* and can be given to other {@link CommandGroup CommandGroups}.</p>
* <p>
* Commands in a {@link CommandGroup} are added using the
* {@link CommandGroup#addSequential(Command) addSequential(...)} method and are
* called sequentially. {@link CommandGroup CommandGroups} are themselves
* {@link Command commands} and can be given to other {@link CommandGroup
* CommandGroups}.
* </p>
*
* <p>{@link CommandGroup CommandGroups} will carry all of the requirements of their {@link Command subcommands}. Additional
* requirements can be specified by calling {@link CommandGroup#requires(Subsystem) requires(...)}
* normally in the constructor.</P>
* <p>
* {@link CommandGroup CommandGroups} will carry all of the requirements of
* their {@link Command subcommands}. Additional requirements can be specified
* by calling {@link CommandGroup#requires(Subsystem) requires(...)} normally in
* the constructor.
* </P>
*
* <p>CommandGroups can also execute commands in parallel, simply by adding them
* using {@link CommandGroup#addParallel(Command) addParallel(...)}.</p>
* <p>
* CommandGroups can also execute commands in parallel, simply by adding them
* using {@link CommandGroup#addParallel(Command) addParallel(...)}.
* </p>
*
* @author Brad Miller
* @author Joe Grinstead
@@ -33,366 +41,396 @@ import java.util.Vector;
*/
public class CommandGroup extends Command {
/** The commands in this group (stored in entries) */
Vector m_commands = new Vector();
/** The active children in this group (stored in entries) */
Vector m_children = new Vector();
/** The current command, -1 signifies that none have been run */
int m_currentCommandIndex = -1;
/** The commands in this group (stored in entries) */
Vector m_commands = new Vector();
/** The active children in this group (stored in entries) */
Vector m_children = new Vector();
/** The current command, -1 signifies that none have been run */
int m_currentCommandIndex = -1;
/**
* Creates a new {@link CommandGroup CommandGroup}.
* The name of this command will be set to its class name.
*/
public CommandGroup() {
/**
* Creates a new {@link CommandGroup CommandGroup}. The name of this command
* will be set to its class name.
*/
public CommandGroup() {}
/**
* Creates a new {@link CommandGroup CommandGroup} with the given name.
*$
* @param name the name for this command group
* @throws IllegalArgumentException if name is null
*/
public CommandGroup(String name) {
super(name);
}
/**
* Adds a new {@link Command Command} to the group. The {@link Command
* Command} will be started after all the previously added {@link Command
* Commands}.
*
* <p>
* Note that any requirements the given {@link Command Command} has will be
* added to the group. For this reason, a {@link Command Command's}
* requirements can not be changed after being added to a group.
* </p>
*
* <p>
* It is recommended that this method be called in the constructor.
* </p>
*
* @param command The {@link Command Command} to be added
* @throws IllegalUseOfCommandException if the group has been started before
* or been given to another group
* @throws IllegalArgumentException if command is null
*/
public synchronized final void addSequential(Command command) {
validate("Can not add new command to command group");
if (command == null) {
throw new IllegalArgumentException("Given null command");
}
/**
* Creates a new {@link CommandGroup CommandGroup} with the given name.
* @param name the name for this command group
* @throws IllegalArgumentException if name is null
*/
public CommandGroup(String name) {
super(name);
command.setParent(this);
m_commands.addElement(new Entry(command, Entry.IN_SEQUENCE));
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
requires((Subsystem) e.nextElement());
}
}
/**
* Adds a new {@link Command Command} to the group with a given timeout. The
* {@link Command Command} will be started after all the previously added
* commands.
*
* <p>
* Once the {@link Command Command} is started, it will be run until it
* finishes or the time expires, whichever is sooner. Note that the given
* {@link Command Command} will have no knowledge that it is on a timer.
* </p>
*
* <p>
* Note that any requirements the given {@link Command Command} has will be
* added to the group. For this reason, a {@link Command Command's}
* requirements can not be changed after being added to a group.
* </p>
*
* <p>
* It is recommended that this method be called in the constructor.
* </p>
*
* @param command The {@link Command Command} to be added
* @param timeout The timeout (in seconds)
* @throws IllegalUseOfCommandException if the group has been started before
* or been given to another group or if the {@link Command Command}
* has been started before or been given to another group
* @throws IllegalArgumentException if command is null or timeout is negative
*/
public synchronized final void addSequential(Command command, double timeout) {
validate("Can not add new command to command group");
if (command == null) {
throw new IllegalArgumentException("Given null command");
}
if (timeout < 0) {
throw new IllegalArgumentException("Can not be given a negative timeout");
}
/**
* Adds a new {@link Command Command} to the group. The {@link Command Command} will be started after
* all the previously added {@link Command Commands}.
*
* <p>Note that any requirements the given {@link Command Command} has will be added to the
* group. For this reason, a {@link Command Command's} requirements can not be changed after
* being added to a group.</p>
*
* <p>It is recommended that this method be called in the constructor.</p>
*
* @param command The {@link Command Command} to be added
* @throws IllegalUseOfCommandException if the group has been started before or been given to another group
* @throws IllegalArgumentException if command is null
*/
public synchronized final void addSequential(Command command) {
validate("Can not add new command to command group");
if (command == null) {
throw new IllegalArgumentException("Given null command");
}
command.setParent(this);
command.setParent(this);
m_commands.addElement(new Entry(command, Entry.IN_SEQUENCE, timeout));
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
requires((Subsystem) e.nextElement());
}
}
m_commands.addElement(new Entry(command, Entry.IN_SEQUENCE));
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
requires((Subsystem) e.nextElement());
}
/**
* Adds a new child {@link Command} to the group. The {@link Command} will be
* started after all the previously added {@link Command Commands}.
*
* <p>
* Instead of waiting for the child to finish, a {@link CommandGroup} will
* have it run at the same time as the subsequent {@link Command Commands}.
* The child will run until either it finishes, a new child with conflicting
* requirements is started, or the main sequence runs a {@link Command} with
* conflicting requirements. In the latter two cases, the child will be
* canceled even if it says it can't be interrupted.
* </p>
*
* <p>
* Note that any requirements the given {@link Command Command} has will be
* added to the group. For this reason, a {@link Command Command's}
* requirements can not be changed after being added to a group.
* </p>
*
* <p>
* It is recommended that this method be called in the constructor.
* </p>
*
* @param command The command to be added
* @throws IllegalUseOfCommandException if the group has been started before
* or been given to another command group
* @throws IllegalArgumentException if command is null
*/
public synchronized final void addParallel(Command command) {
validate("Can not add new command to command group");
if (command == null) {
throw new NullPointerException("Given null command");
}
/**
* Adds a new {@link Command Command} to the group with a given timeout.
* The {@link Command Command} will be started after all the previously added commands.
*
* <p>Once the {@link Command Command} is started, it will be run until it finishes or the time
* expires, whichever is sooner. Note that the given {@link Command Command} will have no
* knowledge that it is on a timer.</p>
*
* <p>Note that any requirements the given {@link Command Command} has will be added to the
* group. For this reason, a {@link Command Command's} requirements can not be changed after
* being added to a group.</p>
*
* <p>It is recommended that this method be called in the constructor.</p>
*
* @param command The {@link Command Command} to be added
* @param timeout The timeout (in seconds)
* @throws IllegalUseOfCommandException if the group has been started before or been given to another group or
* if the {@link Command Command} has been started before or been given to another group
* @throws IllegalArgumentException if command is null or timeout is negative
*/
public synchronized final void addSequential(Command command, double timeout) {
validate("Can not add new command to command group");
if (command == null) {
throw new IllegalArgumentException("Given null command");
}
if (timeout < 0) {
throw new IllegalArgumentException("Can not be given a negative timeout");
}
command.setParent(this);
command.setParent(this);
m_commands.addElement(new Entry(command, Entry.BRANCH_CHILD));
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
requires((Subsystem) e.nextElement());
}
}
m_commands.addElement(new Entry(command, Entry.IN_SEQUENCE, timeout));
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
requires((Subsystem) e.nextElement());
}
/**
* Adds a new child {@link Command} to the group with the given timeout. The
* {@link Command} will be started after all the previously added
* {@link Command Commands}.
*
* <p>
* Once the {@link Command Command} is started, it will run until it finishes,
* is interrupted, or the time expires, whichever is sooner. Note that the
* given {@link Command Command} will have no knowledge that it is on a timer.
* </p>
*
* <p>
* Instead of waiting for the child to finish, a {@link CommandGroup} will
* have it run at the same time as the subsequent {@link Command Commands}.
* The child will run until either it finishes, the timeout expires, a new
* child with conflicting requirements is started, or the main sequence runs a
* {@link Command} with conflicting requirements. In the latter two cases, the
* child will be canceled even if it says it can't be interrupted.
* </p>
*
* <p>
* Note that any requirements the given {@link Command Command} has will be
* added to the group. For this reason, a {@link Command Command's}
* requirements can not be changed after being added to a group.
* </p>
*
* <p>
* It is recommended that this method be called in the constructor.
* </p>
*
* @param command The command to be added
* @param timeout The timeout (in seconds)
* @throws IllegalUseOfCommandException if the group has been started before
* or been given to another command group
* @throws IllegalArgumentException if command is null
*/
public synchronized final void addParallel(Command command, double timeout) {
validate("Can not add new command to command group");
if (command == null) {
throw new NullPointerException("Given null command");
}
if (timeout < 0) {
throw new IllegalArgumentException("Can not be given a negative timeout");
}
/**
* Adds a new child {@link Command} to the group. The {@link Command} will be started after
* all the previously added {@link Command Commands}.
*
* <p>Instead of waiting for the child to finish, a {@link CommandGroup} will have it
* run at the same time as the subsequent {@link Command Commands}. The child will run until either
* it finishes, a new child with conflicting requirements is started, or
* the main sequence runs a {@link Command} with conflicting requirements. In the latter
* two cases, the child will be canceled even if it says it can't be
* interrupted.</p>
*
* <p>Note that any requirements the given {@link Command Command} has will be added to the
* group. For this reason, a {@link Command Command's} requirements can not be changed after
* being added to a group.</p>
*
* <p>It is recommended that this method be called in the constructor.</p>
*
* @param command The command to be added
* @throws IllegalUseOfCommandException if the group has been started before or been given to another command group
* @throws IllegalArgumentException if command is null
*/
public synchronized final void addParallel(Command command) {
validate("Can not add new command to command group");
if (command == null) {
throw new NullPointerException("Given null command");
}
command.setParent(this);
command.setParent(this);
m_commands.addElement(new Entry(command, Entry.BRANCH_CHILD, timeout));
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
requires((Subsystem) e.nextElement());
}
}
m_commands.addElement(new Entry(command, Entry.BRANCH_CHILD));
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
requires((Subsystem) e.nextElement());
}
void _initialize() {
m_currentCommandIndex = -1;
}
void _execute() {
Entry entry = null;
Command cmd = null;
boolean firstRun = false;
if (m_currentCommandIndex == -1) {
firstRun = true;
m_currentCommandIndex = 0;
}
/**
* Adds a new child {@link Command} to the group with the given timeout. The {@link Command} will be started after
* all the previously added {@link Command Commands}.
*
* <p>Once the {@link Command Command} is started, it will run until it finishes, is interrupted,
* or the time expires, whichever is sooner. Note that the given {@link Command Command} will have no
* knowledge that it is on a timer.</p>
*
* <p>Instead of waiting for the child to finish, a {@link CommandGroup} will have it
* run at the same time as the subsequent {@link Command Commands}. The child will run until either
* it finishes, the timeout expires, a new child with conflicting requirements is started, or
* the main sequence runs a {@link Command} with conflicting requirements. In the latter
* two cases, the child will be canceled even if it says it can't be
* interrupted.</p>
*
* <p>Note that any requirements the given {@link Command Command} has will be added to the
* group. For this reason, a {@link Command Command's} requirements can not be changed after
* being added to a group.</p>
*
* <p>It is recommended that this method be called in the constructor.</p>
*
* @param command The command to be added
* @param timeout The timeout (in seconds)
* @throws IllegalUseOfCommandException if the group has been started before or been given to another command group
* @throws IllegalArgumentException if command is null
*/
public synchronized final void addParallel(Command command, double timeout) {
validate("Can not add new command to command group");
if (command == null) {
throw new NullPointerException("Given null command");
}
if (timeout < 0) {
throw new IllegalArgumentException("Can not be given a negative timeout");
}
while (m_currentCommandIndex < m_commands.size()) {
command.setParent(this);
m_commands.addElement(new Entry(command, Entry.BRANCH_CHILD, timeout));
for (Enumeration e = command.getRequirements(); e.hasMoreElements();) {
requires((Subsystem) e.nextElement());
if (cmd != null) {
if (entry.isTimedOut()) {
cmd._cancel();
}
if (cmd.run()) {
break;
} else {
cmd.removed();
m_currentCommandIndex++;
firstRun = true;
cmd = null;
continue;
}
}
entry = (Entry) m_commands.elementAt(m_currentCommandIndex);
cmd = null;
switch (entry.state) {
case Entry.IN_SEQUENCE:
cmd = entry.command;
if (firstRun) {
cmd.startRunning();
cancelConflicts(cmd);
}
firstRun = false;
break;
case Entry.BRANCH_PEER:
m_currentCommandIndex++;
entry.command.start();
break;
case Entry.BRANCH_CHILD:
m_currentCommandIndex++;
cancelConflicts(entry.command);
entry.command.startRunning();
m_children.addElement(entry);
break;
}
}
void _initialize() {
m_currentCommandIndex = -1;
// Run Children
for (int i = 0; i < m_children.size(); i++) {
entry = (Entry) m_children.elementAt(i);
Command child = entry.command;
if (entry.isTimedOut()) {
child._cancel();
}
if (!child.run()) {
child.removed();
m_children.removeElementAt(i--);
}
}
}
void _end() {
// Theoretically, we don't have to check this, but we do if teams override
// the isFinished method
if (m_currentCommandIndex != -1 && m_currentCommandIndex < m_commands.size()) {
Command cmd = ((Entry) m_commands.elementAt(m_currentCommandIndex)).command;
cmd._cancel();
cmd.removed();
}
void _execute() {
Entry entry = null;
Command cmd = null;
boolean firstRun = false;
if (m_currentCommandIndex == -1) {
firstRun = true;
m_currentCommandIndex = 0;
}
Enumeration children = m_children.elements();
while (children.hasMoreElements()) {
Command cmd = ((Entry) children.nextElement()).command;
cmd._cancel();
cmd.removed();
}
m_children.removeAllElements();
}
while (m_currentCommandIndex < m_commands.size()) {
void _interrupted() {
_end();
}
if (cmd != null) {
if (entry.isTimedOut()) {
cmd._cancel();
}
if (cmd.run()) {
break;
} else {
cmd.removed();
m_currentCommandIndex++;
firstRun = true;
cmd = null;
continue;
}
}
/**
* Returns true if all the {@link Command Commands} in this group have been
* started and have finished.
*
* <p>
* Teams may override this method, although they should probably reference
* super.isFinished() if they do.
* </p>
*
* @return whether this {@link CommandGroup} is finished
*/
protected boolean isFinished() {
return m_currentCommandIndex >= m_commands.size() && m_children.isEmpty();
}
entry = (Entry) m_commands.elementAt(m_currentCommandIndex);
cmd = null;
// Can be overwritten by teams
protected void initialize() {}
switch (entry.state) {
case Entry.IN_SEQUENCE:
cmd = entry.command;
if (firstRun) {
cmd.startRunning();
cancelConflicts(cmd);
}
firstRun = false;
break;
case Entry.BRANCH_PEER:
m_currentCommandIndex++;
entry.command.start();
break;
case Entry.BRANCH_CHILD:
m_currentCommandIndex++;
cancelConflicts(entry.command);
entry.command.startRunning();
m_children.addElement(entry);
break;
}
}
// Can be overwritten by teams
protected void execute() {}
// Run Children
for (int i = 0; i < m_children.size(); i++) {
entry = (Entry) m_children.elementAt(i);
Command child = entry.command;
if (entry.isTimedOut()) {
child._cancel();
}
if (!child.run()) {
child.removed();
m_children.removeElementAt(i--);
}
}
// Can be overwritten by teams
protected void end() {}
// Can be overwritten by teams
protected void interrupted() {}
/**
* Returns whether or not this group is interruptible. A command group will be
* uninterruptible if {@link CommandGroup#setInterruptible(boolean)
* setInterruptable(false)} was called or if it is currently running an
* uninterruptible command or child.
*
* @return whether or not this {@link CommandGroup} is interruptible.
*/
public synchronized boolean isInterruptible() {
if (!super.isInterruptible()) {
return false;
}
void _end() {
// Theoretically, we don't have to check this, but we do if teams override the isFinished method
if (m_currentCommandIndex != -1 && m_currentCommandIndex < m_commands.size()) {
Command cmd = ((Entry) m_commands.elementAt(m_currentCommandIndex)).command;
cmd._cancel();
cmd.removed();
if (m_currentCommandIndex != -1 && m_currentCommandIndex < m_commands.size()) {
Command cmd = ((Entry) m_commands.elementAt(m_currentCommandIndex)).command;
if (!cmd.isInterruptible()) {
return false;
}
}
for (int i = 0; i < m_children.size(); i++) {
if (!((Entry) m_children.elementAt(i)).command.isInterruptible()) {
return false;
}
}
return true;
}
private void cancelConflicts(Command command) {
for (int i = 0; i < m_children.size(); i++) {
Command child = ((Entry) m_children.elementAt(i)).command;
Enumeration requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
Object requirement = requirements.nextElement();
if (child.doesRequire((Subsystem) requirement)) {
child._cancel();
child.removed();
m_children.removeElementAt(i--);
break;
}
}
}
}
Enumeration children = m_children.elements();
while (children.hasMoreElements()) {
Command cmd = ((Entry) children.nextElement()).command;
cmd._cancel();
cmd.removed();
}
m_children.removeAllElements();
private static class Entry {
private static final int IN_SEQUENCE = 0;
private static final int BRANCH_PEER = 1;
private static final int BRANCH_CHILD = 2;
Command command;
int state;
double timeout;
Entry(Command command, int state) {
this.command = command;
this.state = state;
this.timeout = -1;
}
void _interrupted() {
_end();
Entry(Command command, int state, double timeout) {
this.command = command;
this.state = state;
this.timeout = timeout;
}
/**
* Returns true if all the {@link Command Commands} in this group
* have been started and have finished.
*
* <p>Teams may override this method, although they should probably
* reference super.isFinished() if they do.</p>
*
* @return whether this {@link CommandGroup} is finished
*/
protected boolean isFinished() {
return m_currentCommandIndex >= m_commands.size() && m_children.isEmpty();
}
// Can be overwritten by teams
protected void initialize() {
}
// Can be overwritten by teams
protected void execute() {
}
// Can be overwritten by teams
protected void end() {
}
// Can be overwritten by teams
protected void interrupted() {
}
/**
* Returns whether or not this group is interruptible.
* A command group will be uninterruptible if {@link CommandGroup#setInterruptible(boolean) setInterruptable(false)}
* was called or if it is currently running an uninterruptible command
* or child.
*
* @return whether or not this {@link CommandGroup} is interruptible.
*/
public synchronized boolean isInterruptible() {
if (!super.isInterruptible()) {
return false;
}
if (m_currentCommandIndex != -1 && m_currentCommandIndex < m_commands.size()) {
Command cmd = ((Entry) m_commands.elementAt(m_currentCommandIndex)).command;
if (!cmd.isInterruptible()) {
return false;
}
}
for (int i = 0; i < m_children.size(); i++) {
if (!((Entry) m_children.elementAt(i)).command.isInterruptible()) {
return false;
}
}
return true;
}
private void cancelConflicts(Command command) {
for (int i = 0; i < m_children.size(); i++) {
Command child = ((Entry) m_children.elementAt(i)).command;
Enumeration requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
Object requirement = requirements.nextElement();
if (child.doesRequire((Subsystem) requirement)) {
child._cancel();
child.removed();
m_children.removeElementAt(i--);
break;
}
}
}
}
private static class Entry {
private static final int IN_SEQUENCE = 0;
private static final int BRANCH_PEER = 1;
private static final int BRANCH_CHILD = 2;
Command command;
int state;
double timeout;
Entry(Command command, int state) {
this.command = command;
this.state = state;
this.timeout = -1;
}
Entry(Command command, int state, double timeout) {
this.command = command;
this.state = state;
this.timeout = timeout;
}
boolean isTimedOut() {
if (timeout == -1) {
return false;
} else {
double time = command.timeSinceInitialized();
return time == 0 ? false : time >= timeout;
}
}
boolean isTimedOut() {
if (timeout == -1) {
return false;
} else {
double time = command.timeSinceInitialized();
return time == 0 ? false : time >= timeout;
}
}
}
}

View File

@@ -1,38 +1,43 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
/**
* This exception will be thrown if a command is used illegally. There are
* This exception will be thrown if a command is used illegally. There are
* several ways for this to happen.
*
* <p>Basically, a command becomes "locked" after it is first started or added
* to a command group.</p>
* <p>
* Basically, a command becomes "locked" after it is first started or added to a
* command group.
* </p>
*
* <p>This exception should be thrown if (after a command has been locked) its requirements
* change, it is put into multiple command groups,
* it is started from outside its command group, or it adds a new child.</p>
* <p>
* This exception should be thrown if (after a command has been locked) its
* requirements change, it is put into multiple command groups, it is started
* from outside its command group, or it adds a new child.
* </p>
*
* @author Joe Grinstead
*/
public class IllegalUseOfCommandException extends RuntimeException {
/**
* Instantiates an {@link IllegalUseOfCommandException}.
*/
public IllegalUseOfCommandException() {
}
/**
* Instantiates an {@link IllegalUseOfCommandException}.
*/
public IllegalUseOfCommandException() {}
/**
* Instantiates an {@link IllegalUseOfCommandException} with the given message.
* @param message the message
*/
public IllegalUseOfCommandException(String message) {
super(message);
}
/**
* Instantiates an {@link IllegalUseOfCommandException} with the given
* message.
*$
* @param message the message
*/
public IllegalUseOfCommandException(String message) {
super(message);
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
@@ -12,55 +12,54 @@ package edu.wpi.first.wpilibj.command;
* @author Greg
*/
class LinkedListElement {
private LinkedListElement next;
private LinkedListElement previous;
private Command data;
private LinkedListElement next;
private LinkedListElement previous;
private Command data;
public LinkedListElement() {
public LinkedListElement() {}
public void setData(Command newData) {
data = newData;
}
public Command getData() {
return data;
}
public LinkedListElement getNext() {
return next;
}
public LinkedListElement getPrevious() {
return previous;
}
public void add(LinkedListElement l) {
if (next == null) {
next = l;
next.previous = this;
} else {
next.previous = l;
l.next = next;
l.previous = this;
next = l;
}
}
public void setData(Command newData) {
data = newData;
}
public Command getData() {
return data;
}
public LinkedListElement getNext() {
return next;
}
public LinkedListElement getPrevious() {
return previous;
}
public void add(LinkedListElement l) {
if(next == null) {
next = l;
next.previous = this;
} else {
next.previous = l;
l.next = next;
l.previous = this;
next = l;
}
}
public LinkedListElement remove() {
if(previous == null && next == null) {
} else if(next == null) {
previous.next = null;
} else if(previous == null) {
next.previous = null;
} else {
next.previous = previous;
previous.next = next;
}
LinkedListElement n = next;
next = null;
previous = null;
return n;
public LinkedListElement remove() {
if (previous == null && next == null) {
} else if (next == null) {
previous.next = null;
} else if (previous == null) {
next.previous = null;
} else {
next.previous = previous;
previous.next = next;
}
LinkedListElement n = next;
next = null;
previous = null;
return n;
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
@@ -16,182 +16,207 @@ import edu.wpi.first.wpilibj.tables.ITable;
/**
* This class defines a {@link Command} which interacts heavily with a PID loop.
*
* <p>It provides some convenience methods to run an internal {@link PIDController}.
* It will also start and stop said {@link PIDController} when the {@link PIDCommand} is
* first initialized and ended/interrupted.</p>
* <p>
* It provides some convenience methods to run an internal {@link PIDController}
* . It will also start and stop said {@link PIDController} when the
* {@link PIDCommand} is first initialized and ended/interrupted.
* </p>
*
* @author Joe Grinstead
*/
public abstract class PIDCommand extends Command implements Sendable {
/** The internal {@link PIDController} */
private PIDController controller;
/** An output which calls {@link PIDCommand#usePIDOutput(double)} */
private PIDOutput output = new PIDOutput() {
/** The internal {@link PIDController} */
private PIDController controller;
/** An output which calls {@link PIDCommand#usePIDOutput(double)} */
private PIDOutput output = new PIDOutput() {
public void pidWrite(double output) {
usePIDOutput(output);
}
};
/** A source which calls {@link PIDCommand#returnPIDInput()} */
private PIDSource source = new PIDSource() {
public double pidGet() {
return returnPIDInput();
}
};
/**
* Instantiates a {@link PIDCommand} that will use the given p, i and d values.
* @param name the name of the command
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
public PIDCommand(String name, double p, double i, double d) {
super(name);
controller = new PIDController(p, i, d, source, output);
public void pidWrite(double output) {
usePIDOutput(output);
}
};
/** A source which calls {@link PIDCommand#returnPIDInput()} */
private PIDSource source = new PIDSource() {
/**
* Instantiates a {@link PIDCommand} that will use the given p, i and d values. It will also space the time
* between PID loop calculations to be equal to the given period.
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param period the time (in seconds) between calculations
*/
public PIDCommand(String name, double p, double i, double d, double period) {
super(name);
controller = new PIDController(p, i, d, source, output, period);
public double pidGet() {
return returnPIDInput();
}
};
/**
* Instantiates a {@link PIDCommand} that will use the given p, i and d values.
* It will use the class name as its name.
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
public PIDCommand(double p, double i, double d) {
controller = new PIDController(p, i, d, source, output);
}
/**
* Instantiates a {@link PIDCommand} that will use the given p, i and d
* values.
*$
* @param name the name of the command
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
public PIDCommand(String name, double p, double i, double d) {
super(name);
controller = new PIDController(p, i, d, source, output);
}
/**
* Instantiates a {@link PIDCommand} that will use the given p, i and d values.
* It will use the class name as its name..
* It will also space the time
* between PID loop calculations to be equal to the given period.
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param period the time (in seconds) between calculations
*/
public PIDCommand(double p, double i, double d, double period) {
controller = new PIDController(p, i, d, source, output, period);
}
/**
* Instantiates a {@link PIDCommand} that will use the given p, i and d
* values. It will also space the time between PID loop calculations to be
* equal to the given period.
*$
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param period the time (in seconds) between calculations
*/
public PIDCommand(String name, double p, double i, double d, double period) {
super(name);
controller = new PIDController(p, i, d, source, output, period);
}
/**
* Returns the {@link PIDController} used by this {@link PIDCommand}.
* Use this if you would like to fine tune the pid loop.
*
* @return the {@link PIDController} used by this {@link PIDCommand}
*/
protected PIDController getPIDController() {
return controller;
}
/**
* Instantiates a {@link PIDCommand} that will use the given p, i and d
* values. It will use the class name as its name.
*$
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
public PIDCommand(double p, double i, double d) {
controller = new PIDController(p, i, d, source, output);
}
void _initialize() {
controller.enable();
}
/**
* Instantiates a {@link PIDCommand} that will use the given p, i and d
* values. It will use the class name as its name.. It will also space the
* time between PID loop calculations to be equal to the given period.
*$
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param period the time (in seconds) between calculations
*/
public PIDCommand(double p, double i, double d, double period) {
controller = new PIDController(p, i, d, source, output, period);
}
void _end() {
controller.disable();
}
/**
* Returns the {@link PIDController} used by this {@link PIDCommand}. Use this
* if you would like to fine tune the pid loop.
*
* @return the {@link PIDController} used by this {@link PIDCommand}
*/
protected PIDController getPIDController() {
return controller;
}
void _interrupted() {
_end();
}
void _initialize() {
controller.enable();
}
/**
* Adds the given value to the setpoint.
* If {@link PIDCommand#setInputRange(double, double) setInputRange(...)} was used,
* then the bounds will still be honored by this method.
* @param deltaSetpoint the change in the setpoint
*/
public void setSetpointRelative(double deltaSetpoint) {
setSetpoint(getSetpoint() + deltaSetpoint);
}
void _end() {
controller.disable();
}
/**
* Sets the setpoint to the given value. If {@link PIDCommand#setInputRange(double, double) setInputRange(...)}
* was called,
* then the given setpoint
* will be trimmed to fit within the range.
* @param setpoint the new setpoint
*/
protected void setSetpoint(double setpoint) {
controller.setSetpoint(setpoint);
}
void _interrupted() {
_end();
}
/**
* Returns the setpoint.
* @return the setpoint
*/
protected double getSetpoint() {
return controller.getSetpoint();
}
/**
* Adds the given value to the setpoint. If
* {@link PIDCommand#setInputRange(double, double) setInputRange(...)} was
* used, then the bounds will still be honored by this method.
*$
* @param deltaSetpoint the change in the setpoint
*/
public void setSetpointRelative(double deltaSetpoint) {
setSetpoint(getSetpoint() + deltaSetpoint);
}
/**
* Returns the current position
* @return the current position
*/
protected double getPosition() {
return returnPIDInput();
}
/**
* Sets the maximum and minimum values expected from the input and setpoint.
*
* @param minimumInput the minimum value expected from the input and setpoint
* @param maximumInput the maximum value expected from the input and setpoint
*/
protected void setInputRange(double minimumInput, double maximumInput) {
controller.setInputRange(minimumInput, maximumInput);
}
/**
* Sets the setpoint to the given value. If
* {@link PIDCommand#setInputRange(double, double) setInputRange(...)} was
* called, then the given setpoint will be trimmed to fit within the range.
*$
* @param setpoint the new setpoint
*/
protected void setSetpoint(double setpoint) {
controller.setSetpoint(setpoint);
}
/**
* Returns the input for the pid loop.
*
* <p>It returns the input for the pid loop, so if this command was based
* off of a gyro, then it should return the angle of the gyro</p>
*
* <p>All subclasses of {@link PIDCommand} must override this method.</p>
*
* <p>This method will be called in a different thread then the {@link Scheduler} thread.</p>
*
* @return the value the pid loop should use as input
*/
protected abstract double returnPIDInput();
/**
* Returns the setpoint.
*$
* @return the setpoint
*/
protected double getSetpoint() {
return controller.getSetpoint();
}
/**
* Uses the value that the pid loop calculated. The calculated value is the "output" parameter.
* This method is a good time to set motor values, maybe something along the lines of <code>driveline.tankDrive(output, -output)</code>
*
* <p>All subclasses of {@link PIDCommand} must override this method.</p>
*
* <p>This method will be called in a different thread then the {@link Scheduler} thread.</p>
*
* @param output the value the pid loop calculated
*/
protected abstract void usePIDOutput(double output);
/**
* Returns the current position
*$
* @return the current position
*/
protected double getPosition() {
return returnPIDInput();
}
public String getSmartDashboardType() {
return "PIDCommand";
}
public void initTable(ITable table) {
controller.initTable(table);
super.initTable(table);
}
/**
* Sets the maximum and minimum values expected from the input and setpoint.
*
* @param minimumInput the minimum value expected from the input and setpoint
* @param maximumInput the maximum value expected from the input and setpoint
*/
protected void setInputRange(double minimumInput, double maximumInput) {
controller.setInputRange(minimumInput, maximumInput);
}
/**
* Returns the input for the pid loop.
*
* <p>
* It returns the input for the pid loop, so if this command was based off of
* a gyro, then it should return the angle of the gyro
* </p>
*
* <p>
* All subclasses of {@link PIDCommand} must override this method.
* </p>
*
* <p>
* This method will be called in a different thread then the {@link Scheduler}
* thread.
* </p>
*
* @return the value the pid loop should use as input
*/
protected abstract double returnPIDInput();
/**
* Uses the value that the pid loop calculated. The calculated value is the
* "output" parameter. This method is a good time to set motor values, maybe
* something along the lines of
* <code>driveline.tankDrive(output, -output)</code>
*
* <p>
* All subclasses of {@link PIDCommand} must override this method.
* </p>
*
* <p>
* This method will be called in a different thread then the {@link Scheduler}
* thread.
* </p>
*
* @param output the value the pid loop calculated
*/
protected abstract void usePIDOutput(double output);
public String getSmartDashboardType() {
return "PIDCommand";
}
public void initTable(ITable table) {
controller.initTable(table);
super.initTable(table);
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
@@ -15,250 +15,274 @@ import edu.wpi.first.wpilibj.tables.ITable;
/**
* This class is designed to handle the case where there is a {@link Subsystem}
* which uses a single {@link PIDController} almost constantly (for instance,
* an elevator which attempts to stay at a constant height).
* which uses a single {@link PIDController} almost constantly (for instance, an
* elevator which attempts to stay at a constant height).
*
* <p>It provides some convenience methods to run an internal {@link PIDController}.
* It also allows access to the internal {@link PIDController} in order to give total control
* to the programmer.</p>
* <p>
* It provides some convenience methods to run an internal {@link PIDController}
* . It also allows access to the internal {@link PIDController} in order to
* give total control to the programmer.
* </p>
*
* @author Joe Grinstead
*/
public abstract class PIDSubsystem extends Subsystem implements Sendable {
/** The internal {@link PIDController} */
private PIDController controller;
/** An output which calls {@link PIDCommand#usePIDOutput(double)} */
private PIDOutput output = new PIDOutput() {
/** The internal {@link PIDController} */
private PIDController controller;
/** An output which calls {@link PIDCommand#usePIDOutput(double)} */
private PIDOutput output = new PIDOutput() {
public void pidWrite(double output) {
usePIDOutput(output);
}
};
/** A source which calls {@link PIDCommand#returnPIDInput()} */
private PIDSource source = new PIDSource() {
public double pidGet() {
return returnPIDInput();
}
};
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
public PIDSubsystem(String name, double p, double i, double d) {
super(name);
controller = new PIDController(p, i, d, source, output);
public void pidWrite(double output) {
usePIDOutput(output);
}
};
/** A source which calls {@link PIDCommand#returnPIDInput()} */
private PIDSource source = new PIDSource() {
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feed forward value
*/
public PIDSubsystem(String name, double p, double i, double d, double f) {
super(name);
controller = new PIDController(p, i, d, f, source, output);
public double pidGet() {
return returnPIDInput();
}
};
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values. It will also space the time
* between PID loop calculations to be equal to the given period.
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param period the time (in seconds) between calculations
*/
public PIDSubsystem(String name, double p, double i, double d, double f, double period) {
super(name);
controller = new PIDController(p, i, d, f, source, output, period);
}
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d
* values.
*$
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
public PIDSubsystem(String name, double p, double i, double d) {
super(name);
controller = new PIDController(p, i, d, source, output);
}
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
* It will use the class name as its name.
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
public PIDSubsystem(double p, double i, double d) {
controller = new PIDController(p, i, d, source, output);
}
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d
* values.
*$
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feed forward value
*/
public PIDSubsystem(String name, double p, double i, double d, double f) {
super(name);
controller = new PIDController(p, i, d, f, source, output);
}
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
* It will use the class name as its name.
* It will also space the time
* between PID loop calculations to be equal to the given period.
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feed forward coefficient
* @param period the time (in seconds) between calculations
*/
public PIDSubsystem(double p, double i, double d, double period, double f) {
controller = new PIDController(p, i, d, f, source, output, period);
}
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d
* values. It will also space the time between PID loop calculations to be
* equal to the given period.
*$
* @param name the name
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param period the time (in seconds) between calculations
*/
public PIDSubsystem(String name, double p, double i, double d, double f, double period) {
super(name);
controller = new PIDController(p, i, d, f, source, output, period);
}
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d values.
* It will use the class name as its name.
* It will also space the time
* between PID loop calculations to be equal to the given period.
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param period the time (in seconds) between calculations
*/
public PIDSubsystem(double p, double i, double d, double period) {
controller = new PIDController(p, i, d, source, output, period);
}
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d
* values. It will use the class name as its name.
*$
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
*/
public PIDSubsystem(double p, double i, double d) {
controller = new PIDController(p, i, d, source, output);
}
/**
* Returns the {@link PIDController} used by this {@link PIDSubsystem}.
* Use this if you would like to fine tune the pid loop.
*
* @return the {@link PIDController} used by this {@link PIDSubsystem}
*/
public PIDController getPIDController() {
return controller;
}
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d
* values. It will use the class name as its name. It will also space the time
* between PID loop calculations to be equal to the given period.
*$
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param f the feed forward coefficient
* @param period the time (in seconds) between calculations
*/
public PIDSubsystem(double p, double i, double d, double period, double f) {
controller = new PIDController(p, i, d, f, source, output, period);
}
/**
* Instantiates a {@link PIDSubsystem} that will use the given p, i and d
* values. It will use the class name as its name. It will also space the time
* between PID loop calculations to be equal to the given period.
*$
* @param p the proportional value
* @param i the integral value
* @param d the derivative value
* @param period the time (in seconds) between calculations
*/
public PIDSubsystem(double p, double i, double d, double period) {
controller = new PIDController(p, i, d, source, output, period);
}
/**
* Returns the {@link PIDController} used by this {@link PIDSubsystem}. Use
* this if you would like to fine tune the pid loop.
*
* @return the {@link PIDController} used by this {@link PIDSubsystem}
*/
public PIDController getPIDController() {
return controller;
}
/**
* Adds the given value to the setpoint.
* If {@link PIDSubsystem#setInputRange(double, double) setInputRange(...)} was used,
* then the bounds will still be honored by this method.
* @param deltaSetpoint the change in the setpoint
*/
public void setSetpointRelative(double deltaSetpoint) {
setSetpoint(getPosition() + deltaSetpoint);
}
/**
* Adds the given value to the setpoint. If
* {@link PIDSubsystem#setInputRange(double, double) setInputRange(...)} was
* used, then the bounds will still be honored by this method.
*$
* @param deltaSetpoint the change in the setpoint
*/
public void setSetpointRelative(double deltaSetpoint) {
setSetpoint(getPosition() + deltaSetpoint);
}
/**
* Sets the setpoint to the given value. If {@link PIDSubsystem#setInputRange(double, double) setInputRange(...)}
* was called,
* then the given setpoint
* will be trimmed to fit within the range.
* @param setpoint the new setpoint
*/
public void setSetpoint(double setpoint) {
controller.setSetpoint(setpoint);
}
/**
* Sets the setpoint to the given value. If
* {@link PIDSubsystem#setInputRange(double, double) setInputRange(...)} was
* called, then the given setpoint will be trimmed to fit within the range.
*$
* @param setpoint the new setpoint
*/
public void setSetpoint(double setpoint) {
controller.setSetpoint(setpoint);
}
/**
* Returns the setpoint.
* @return the setpoint
*/
public double getSetpoint() {
return controller.getSetpoint();
}
/**
* Returns the setpoint.
*$
* @return the setpoint
*/
public double getSetpoint() {
return controller.getSetpoint();
}
/**
* Returns the current position
* @return the current position
*/
public double getPosition() {
return returnPIDInput();
}
/**
* Returns the current position
*$
* @return the current position
*/
public double getPosition() {
return returnPIDInput();
}
/**
* Sets the maximum and minimum values expected from the input.
*
* @param minimumInput the minimum value expected from the input
* @param maximumInput the maximum value expected from the output
*/
public void setInputRange(double minimumInput, double maximumInput) {
controller.setInputRange(minimumInput, maximumInput);
}
/**
* Sets the maximum and minimum values expected from the input.
*
* @param minimumInput the minimum value expected from the input
* @param maximumInput the maximum value expected from the output
*/
public void setInputRange(double minimumInput, double maximumInput) {
controller.setInputRange(minimumInput, maximumInput);
}
/**
* Sets the maximum and minimum values to write.
*
* @param minimumOutput the minimum value to write to the output
* @param maximumOutput the maximum value to write to the output
*/
public void setOutputRange(double minimumOutput, double maximumOutput) {
controller.setOutputRange(minimumOutput, maximumOutput);
}
/**
* Sets the maximum and minimum values to write.
*
* @param minimumOutput the minimum value to write to the output
* @param maximumOutput the maximum value to write to the output
*/
public void setOutputRange(double minimumOutput, double maximumOutput) {
controller.setOutputRange(minimumOutput, maximumOutput);
}
/**
* Set the absolute error which is considered tolerable for use with
* OnTarget. The value is in the same range as the PIDInput values.
* @param t the absolute tolerance
*/
public void setAbsoluteTolerance(double t) {
controller.setAbsoluteTolerance(t);
}
/**
* Set the absolute error which is considered tolerable for use with OnTarget.
* The value is in the same range as the PIDInput values.
*$
* @param t the absolute tolerance
*/
public void setAbsoluteTolerance(double t) {
controller.setAbsoluteTolerance(t);
}
/**
* Set the percentage error which is considered tolerable for use with
* OnTarget. (Value of 15.0 == 15 percent)
* @param p the percent tolerance
*/
public void setPercentTolerance(double p) {
controller.setPercentTolerance(p);
}
/**
* Set the percentage error which is considered tolerable for use with
* OnTarget. (Value of 15.0 == 15 percent)
*$
* @param p the percent tolerance
*/
public void setPercentTolerance(double p) {
controller.setPercentTolerance(p);
}
/**
* Return true if the error is within the percentage of the total input range,
* determined by setTolerance. This assumes that the maximum and minimum input
* were set using setInput.
* @return true if the error is less than the tolerance
*/
public boolean onTarget() {
return controller.onTarget();
}
/**
* Return true if the error is within the percentage of the total input range,
* determined by setTolerance. This assumes that the maximum and minimum input
* were set using setInput.
*$
* @return true if the error is less than the tolerance
*/
public boolean onTarget() {
return controller.onTarget();
}
/**
* Returns the input for the pid loop.
*
* <p>It returns the input for the pid loop, so if this Subsystem was based
* off of a gyro, then it should return the angle of the gyro</p>
*
* <p>All subclasses of {@link PIDSubsystem} must override this method.</p>
*
* @return the value the pid loop should use as input
*/
protected abstract double returnPIDInput();
/**
* Returns the input for the pid loop.
*
* <p>
* It returns the input for the pid loop, so if this Subsystem was based off
* of a gyro, then it should return the angle of the gyro
* </p>
*
* <p>
* All subclasses of {@link PIDSubsystem} must override this method.
* </p>
*
* @return the value the pid loop should use as input
*/
protected abstract double returnPIDInput();
/**
* Uses the value that the pid loop calculated. The calculated value is the "output" parameter.
* This method is a good time to set motor values, maybe something along the lines of <code>driveline.tankDrive(output, -output)</code>
*
* <p>All subclasses of {@link PIDSubsystem} must override this method.</p>
*
* @param output the value the pid loop calculated
*/
protected abstract void usePIDOutput(double output);
/**
* Uses the value that the pid loop calculated. The calculated value is the
* "output" parameter. This method is a good time to set motor values, maybe
* something along the lines of
* <code>driveline.tankDrive(output, -output)</code>
*
* <p>
* All subclasses of {@link PIDSubsystem} must override this method.
* </p>
*
* @param output the value the pid loop calculated
*/
protected abstract void usePIDOutput(double output);
/**
* Enables the internal {@link PIDController}
*/
public void enable() {
controller.enable();
}
/**
* Enables the internal {@link PIDController}
*/
public void enable() {
controller.enable();
}
/**
* Disables the internal {@link PIDController}
*/
public void disable() {
controller.disable();
}
/**
* Disables the internal {@link PIDController}
*/
public void disable() {
controller.disable();
}
public String getSmartDashboardType() {
return "PIDSubsystem";
}
public void initTable(ITable table) {
controller.initTable(table);
super.initTable(table);
}
public String getSmartDashboardType() {
return "PIDSubsystem";
}
public void initTable(ITable table) {
controller.initTable(table);
super.initTable(table);
}
}

View File

@@ -1,46 +1,46 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
/**
* A {@link PrintCommand} is a command which prints out a string when it is initialized, and then immediately finishes.
* It is useful if you want a {@link CommandGroup} to print out a string when it reaches a certain point.
* A {@link PrintCommand} is a command which prints out a string when it is
* initialized, and then immediately finishes. It is useful if you want a
* {@link CommandGroup} to print out a string when it reaches a certain point.
*
* @author Joe Grinstead
*/
public class PrintCommand extends Command {
/** The message to print out */
private String message;
/** The message to print out */
private String message;
/**
* Instantiates a {@link PrintCommand} which will print the given message when it is run.
* @param message the message to print
*/
public PrintCommand(String message) {
super("Print(\"" + message + "\"");
this.message = message;
}
/**
* Instantiates a {@link PrintCommand} which will print the given message when
* it is run.
*$
* @param message the message to print
*/
public PrintCommand(String message) {
super("Print(\"" + message + "\"");
this.message = message;
}
protected void initialize() {
System.out.println(message);
}
protected void initialize() {
System.out.println(message);
}
protected void execute() {
}
protected void execute() {}
protected boolean isFinished() {
return true;
}
protected boolean isFinished() {
return true;
}
protected void end() {
}
protected void end() {}
protected void interrupted() {
}
protected void interrupted() {}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
@@ -19,351 +19,360 @@ import edu.wpi.first.wpilibj.tables.ITable;
/**
* The {@link Scheduler} is a singleton which holds the top-level running
* commands. It is in charge of both calling the command's
* {@link Command#run() run()} method and to make sure that there are no two
* commands with conflicting requirements running.
* commands. It is in charge of both calling the command's {@link Command#run()
* run()} method and to make sure that there are no two commands with
* conflicting requirements running.
*
* <p>It is fine if teams wish to take control of the {@link Scheduler}
* themselves, all that needs to be done is to call
* {@link Scheduler#getInstance() Scheduler.getInstance()}.{@link Scheduler#run() run()}
* often to have {@link Command Commands} function correctly. However, this is
* already done for you if you use the CommandBased Robot template.</p>
* <p>
* It is fine if teams wish to take control of the {@link Scheduler} themselves,
* all that needs to be done is to call {@link Scheduler#getInstance()
* Scheduler.getInstance()}.{@link Scheduler#run() run()} often to have
* {@link Command Commands} function correctly. However, this is already done
* for you if you use the CommandBased Robot template.
* </p>
*
* @author Joe Grinstead
* @see Command
*/
public class Scheduler implements NamedSendable {
/**
* The Singleton Instance
*/
private static Scheduler instance;
/**
* The Singleton Instance
*/
private static Scheduler instance;
/**
* Returns the {@link Scheduler}, creating it if one does not exist.
*
* @return the {@link Scheduler}
*/
public synchronized static Scheduler getInstance() {
return instance == null ? instance = new Scheduler() : instance;
/**
* Returns the {@link Scheduler}, creating it if one does not exist.
*
* @return the {@link Scheduler}
*/
public synchronized static Scheduler getInstance() {
return instance == null ? instance = new Scheduler() : instance;
}
/**
* A hashtable of active {@link Command Commands} to their
* {@link LinkedListElement}
*/
private Hashtable commandTable = new Hashtable();
/**
* The {@link Set} of all {@link Subsystem Subsystems}
*/
private Set subsystems = new Set();
/**
* The first {@link Command} in the list
*/
private LinkedListElement firstCommand;
/**
* The last {@link Command} in the list
*/
private LinkedListElement lastCommand;
/**
* Whether or not we are currently adding a command
*/
private boolean adding = false;
/**
* Whether or not we are currently disabled
*/
private boolean disabled = false;
/**
* A list of all {@link Command Commands} which need to be added
*/
private Vector additions = new Vector();
private ITable m_table;
/**
* A list of all {@link edu.wpi.first.wpilibj.buttons.Trigger.ButtonScheduler
* Buttons}. It is created lazily.
*/
private Vector buttons;
private boolean m_runningCommandsChanged;
/**
* Instantiates a {@link Scheduler}.
*/
private Scheduler() {
HLUsageReporting.reportScheduler();
}
/**
* Adds the command to the {@link Scheduler}. This will not add the
* {@link Command} immediately, but will instead wait for the proper time in
* the {@link Scheduler#run()} loop before doing so. The command returns
* immediately and does nothing if given null.
*
* <p>
* Adding a {@link Command} to the {@link Scheduler} involves the
* {@link Scheduler} removing any {@link Command} which has shared
* requirements.
* </p>
*
* @param command the command to add
*/
public void add(Command command) {
if (command != null) {
additions.addElement(command);
}
/**
* A hashtable of active {@link Command Commands} to their
* {@link LinkedListElement}
*/
private Hashtable commandTable = new Hashtable();
/**
* The {@link Set} of all {@link Subsystem Subsystems}
*/
private Set subsystems = new Set();
/**
* The first {@link Command} in the list
*/
private LinkedListElement firstCommand;
/**
* The last {@link Command} in the list
*/
private LinkedListElement lastCommand;
/**
* Whether or not we are currently adding a command
*/
private boolean adding = false;
/**
* Whether or not we are currently disabled
*/
private boolean disabled = false;
/**
* A list of all {@link Command Commands} which need to be added
*/
private Vector additions = new Vector();
private ITable m_table;
/**
* A list of all
* {@link edu.wpi.first.wpilibj.buttons.Trigger.ButtonScheduler Buttons}. It
* is created lazily.
*/
private Vector buttons;
private boolean m_runningCommandsChanged;
}
/**
* Instantiates a {@link Scheduler}.
*/
private Scheduler() {
HLUsageReporting.reportScheduler();
/**
* Adds a button to the {@link Scheduler}. The {@link Scheduler} will poll the
* button during its {@link Scheduler#run()}.
*
* @param button the button to add
*/
public void addButton(ButtonScheduler button) {
if (buttons == null) {
buttons = new Vector();
}
buttons.addElement(button);
}
/**
* Adds a command immediately to the {@link Scheduler}. This should only be
* called in the {@link Scheduler#run()} loop. Any command with conflicting
* requirements will be removed, unless it is uninterruptable. Giving
* <code>null</code> does nothing.
*
* @param command the {@link Command} to add
*/
private void _add(Command command) {
if (command == null) {
return;
}
/**
* Adds the command to the {@link Scheduler}. This will not add the
* {@link Command} immediately, but will instead wait for the proper time in
* the {@link Scheduler#run()} loop before doing so. The command returns
* immediately and does nothing if given null.
*
* <p>Adding a {@link Command} to the {@link Scheduler} involves the
* {@link Scheduler} removing any {@link Command} which has shared
* requirements.</p>
*
* @param command the command to add
*/
public void add(Command command) {
if (command != null) {
additions.addElement(command);
}
// Check to make sure no adding during adding
if (adding) {
System.err.println("WARNING: Can not start command from cancel method. Ignoring:" + command);
return;
}
/**
* Adds a button to the {@link Scheduler}. The {@link Scheduler} will poll
* the button during its {@link Scheduler#run()}.
*
* @param button the button to add
*/
public void addButton(ButtonScheduler button) {
if (buttons == null) {
buttons = new Vector();
// Only add if not already in
if (!commandTable.containsKey(command)) {
// Check that the requirements can be had
Enumeration requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
Subsystem lock = (Subsystem) requirements.nextElement();
if (lock.getCurrentCommand() != null && !lock.getCurrentCommand().isInterruptible()) {
return;
}
buttons.addElement(button);
}
// Give it the requirements
adding = true;
requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
Subsystem lock = (Subsystem) requirements.nextElement();
if (lock.getCurrentCommand() != null) {
lock.getCurrentCommand().cancel();
remove(lock.getCurrentCommand());
}
lock.setCurrentCommand(command);
}
adding = false;
// Add it to the list
LinkedListElement element = new LinkedListElement();
element.setData(command);
if (firstCommand == null) {
firstCommand = lastCommand = element;
} else {
lastCommand.add(element);
lastCommand = element;
}
commandTable.put(command, element);
m_runningCommandsChanged = true;
command.startRunning();
}
}
/**
* Runs a single iteration of the loop. This method should be called often in
* order to have a functioning {@link Command} system. The loop has five
* stages:
*
* <ol>
* <li>Poll the Buttons</li>
* <li>Execute/Remove the Commands</li>
* <li>Send values to SmartDashboard</li>
* <li>Add Commands</li>
* <li>Add Defaults</li>
* </ol>
*/
public void run() {
m_runningCommandsChanged = false;
if (disabled) {
return;
} // Don't run when disabled
// Get button input (going backwards preserves button priority)
if (buttons != null) {
for (int i = buttons.size() - 1; i >= 0; i--) {
((ButtonScheduler) buttons.elementAt(i)).execute();
}
}
// Loop through the commands
LinkedListElement e = firstCommand;
while (e != null) {
Command c = e.getData();
e = e.getNext();
if (!c.run()) {
remove(c);
m_runningCommandsChanged = true;
}
}
/**
* Adds a command immediately to the {@link Scheduler}. This should only be
* called in the {@link Scheduler#run()} loop. Any command with conflicting
* requirements will be removed, unless it is uninterruptable. Giving
* <code>null</code> does nothing.
*
* @param command the {@link Command} to add
*/
private void _add(Command command) {
if (command == null) {
return;
}
// Add the new things
for (int i = 0; i < additions.size(); i++) {
_add((Command) additions.elementAt(i));
}
additions.removeAllElements();
// Check to make sure no adding during adding
if (adding) {
System.err.println("WARNING: Can not start command from cancel method. Ignoring:" + command);
return;
}
// Add in the defaults
Enumeration locks = subsystems.getElements();
while (locks.hasMoreElements()) {
Subsystem lock = (Subsystem) locks.nextElement();
if (lock.getCurrentCommand() == null) {
_add(lock.getDefaultCommand());
}
lock.confirmCommand();
}
// Only add if not already in
if (!commandTable.containsKey(command)) {
updateTable();
}
// Check that the requirements can be had
Enumeration requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
Subsystem lock = (Subsystem) requirements.nextElement();
if (lock.getCurrentCommand() != null && !lock.getCurrentCommand().isInterruptible()) {
return;
}
/**
* Registers a {@link Subsystem} to this {@link Scheduler}, so that the
* {@link Scheduler} might know if a default {@link Command} needs to be run.
* All {@link Subsystem Subsystems} should call this.
*
* @param system the system
*/
void registerSubsystem(Subsystem system) {
if (system != null) {
subsystems.add(system);
}
}
/**
* Removes the {@link Command} from the {@link Scheduler}.
*
* @param command the command to remove
*/
void remove(Command command) {
if (command == null || !commandTable.containsKey(command)) {
return;
}
LinkedListElement e = (LinkedListElement) commandTable.get(command);
commandTable.remove(command);
if (e.equals(lastCommand)) {
lastCommand = e.getPrevious();
}
if (e.equals(firstCommand)) {
firstCommand = e.getNext();
}
e.remove();
Enumeration requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
((Subsystem) requirements.nextElement()).setCurrentCommand(null);
}
command.removed();
}
/**
* Removes all commands
*/
public void removeAll() {
// TODO: Confirm that this works with "uninteruptible" commands
while (firstCommand != null) {
remove(firstCommand.getData());
}
}
/**
* Disable the command scheduler.
*/
public void disable() {
disabled = true;
}
/**
* Enable the command scheduler.
*/
public void enable() {
disabled = false;
}
public String getName() {
return "Scheduler";
}
public String getType() {
return "Scheduler";
}
private StringArray commands;
private NumberArray ids, toCancel;
/**
* {@inheritDoc}
*/
public void initTable(ITable subtable) {
m_table = subtable;
commands = new StringArray();
ids = new NumberArray();
toCancel = new NumberArray();
m_table.putValue("Names", commands);
m_table.putValue("Ids", ids);
m_table.putValue("Cancel", toCancel);
}
private void updateTable() {
if (m_table != null) {
// Get the commands to cancel
m_table.retrieveValue("Cancel", toCancel);
if (toCancel.size() > 0) {
for (LinkedListElement e = firstCommand; e != null; e = e.getNext()) {
for (int i = 0; i < toCancel.size(); i++) {
if (e.getData().hashCode() == toCancel.get(i)) {
e.getData().cancel();
}
// Give it the requirements
adding = true;
requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
Subsystem lock = (Subsystem) requirements.nextElement();
if (lock.getCurrentCommand() != null) {
lock.getCurrentCommand().cancel();
remove(lock.getCurrentCommand());
}
lock.setCurrentCommand(command);
}
adding = false;
// Add it to the list
LinkedListElement element = new LinkedListElement();
element.setData(command);
if (firstCommand == null) {
firstCommand = lastCommand = element;
} else {
lastCommand.add(element);
lastCommand = element;
}
commandTable.put(command, element);
m_runningCommandsChanged = true;
command.startRunning();
}
}
}
toCancel.setSize(0);
m_table.putValue("Cancel", toCancel);
}
/**
* Runs a single iteration of the loop. This method should be called often
* in order to have a functioning {@link Command} system. The loop has five
* stages:
*
* <ol> <li> Poll the Buttons </li> <li> Execute/Remove the Commands </li>
* <li> Send values to SmartDashboard </li> <li> Add Commands </li> <li> Add
* Defaults </li> </ol>
*/
public void run() {
m_runningCommandsChanged = false;
if (disabled) {
return;
} // Don't run when disabled
// Get button input (going backwards preserves button priority)
if (buttons != null) {
for (int i = buttons.size() - 1; i >= 0; i--) {
((ButtonScheduler) buttons.elementAt(i)).execute();
}
if (m_runningCommandsChanged) {
commands.setSize(0);
ids.setSize(0);
// Set the the running commands
for (LinkedListElement e = firstCommand; e != null; e = e.getNext()) {
commands.add(e.getData().getName());
ids.add(e.getData().hashCode());
}
// Loop through the commands
LinkedListElement e = firstCommand;
while (e != null) {
Command c = e.getData();
e = e.getNext();
if (!c.run()) {
remove(c);
m_runningCommandsChanged = true;
}
}
// Add the new things
for (int i = 0; i < additions.size(); i++) {
_add((Command) additions.elementAt(i));
}
additions.removeAllElements();
// Add in the defaults
Enumeration locks = subsystems.getElements();
while (locks.hasMoreElements()) {
Subsystem lock = (Subsystem) locks.nextElement();
if (lock.getCurrentCommand() == null) {
_add(lock.getDefaultCommand());
}
lock.confirmCommand();
}
updateTable();
}
/**
* Registers a {@link Subsystem} to this {@link Scheduler}, so that the
* {@link Scheduler} might know if a default {@link Command} needs to be
* run. All {@link Subsystem Subsystems} should call this.
*
* @param system the system
*/
void registerSubsystem(Subsystem system) {
if (system != null) {
subsystems.add(system);
}
}
/**
* Removes the {@link Command} from the {@link Scheduler}.
*
* @param command the command to remove
*/
void remove(Command command) {
if (command == null || !commandTable.containsKey(command)) {
return;
}
LinkedListElement e = (LinkedListElement) commandTable.get(command);
commandTable.remove(command);
if (e.equals(lastCommand)) {
lastCommand = e.getPrevious();
}
if (e.equals(firstCommand)) {
firstCommand = e.getNext();
}
e.remove();
Enumeration requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
((Subsystem) requirements.nextElement()).setCurrentCommand(null);
}
command.removed();
}
/**
* Removes all commands
*/
public void removeAll() {
// TODO: Confirm that this works with "uninteruptible" commands
while (firstCommand != null) {
remove(firstCommand.getData());
}
}
/**
* Disable the command scheduler.
*/
public void disable() {
disabled = true;
}
/**
* Enable the command scheduler.
*/
public void enable() {
disabled = false;
}
public String getName() {
return "Scheduler";
}
public String getType() {
return "Scheduler";
}
private StringArray commands;
private NumberArray ids, toCancel;
/**
* {@inheritDoc}
*/
public void initTable(ITable subtable) {
m_table = subtable;
commands = new StringArray();
ids = new NumberArray();
toCancel = new NumberArray();
m_table.putValue("Names", commands);
m_table.putValue("Ids", ids);
m_table.putValue("Cancel", toCancel);
}
}
}
private void updateTable() {
if (m_table != null) {
// Get the commands to cancel
m_table.retrieveValue("Cancel", toCancel);
if (toCancel.size() > 0) {
for (LinkedListElement e = firstCommand; e != null; e = e.getNext()) {
for (int i = 0; i < toCancel.size(); i++) {
if (e.getData().hashCode() == toCancel.get(i)) {
e.getData().cancel();
}
}
}
toCancel.setSize(0);
m_table.putValue("Cancel", toCancel);
}
/**
* {@inheritDoc}
*/
public ITable getTable() {
return m_table;
}
if (m_runningCommandsChanged) {
commands.setSize(0);
ids.setSize(0);
// Set the the running commands
for (LinkedListElement e = firstCommand; e != null; e = e.getNext()) {
commands.add(e.getData().getName());
ids.add(e.getData().hashCode());
}
m_table.putValue("Names", commands);
m_table.putValue("Ids", ids);
}
}
}
/**
* {@inheritDoc}
*/
public ITable getTable() {
return m_table;
}
public String getSmartDashboardType() {
return "Scheduler";
}
public String getSmartDashboardType() {
return "Scheduler";
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
@@ -15,28 +15,28 @@ import java.util.Vector;
* @author Greg
*/
class Set {
Vector set = new Vector();
Vector set = new Vector();
public Set() {
}
public Set() {}
public void add(Object o) {
if(set.contains(o)) return;
set.addElement(o);
}
public void add(Object o) {
if (set.contains(o))
return;
set.addElement(o);
}
public void add(Set s) {
Enumeration stuff = s.getElements();
for(Enumeration e = stuff; e.hasMoreElements();) {
add(e.nextElement());
}
public void add(Set s) {
Enumeration stuff = s.getElements();
for (Enumeration e = stuff; e.hasMoreElements();) {
add(e.nextElement());
}
}
public boolean contains(Object o) {
return set.contains(o);
}
public boolean contains(Object o) {
return set.contains(o);
}
public Enumeration getElements() {
return set.elements();
}
public Enumeration getElements() {
return set.elements();
}
}

View File

@@ -1,47 +1,45 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
/**
* A {@link StartCommand} will call the {@link Command#start() start()} method of another command when it is initialized
* and will finish immediately.
* A {@link StartCommand} will call the {@link Command#start() start()} method
* of another command when it is initialized and will finish immediately.
*
* @author Joe Grinstead
*/
public class StartCommand extends Command {
/** The command to fork */
private Command m_commandToFork;
/** The command to fork */
private Command m_commandToFork;
/**
* Instantiates a {@link StartCommand} which will start the
* given command whenever its {@link Command#initialize() initialize()} is called.
* @param commandToStart the {@link Command} to start
*/
public StartCommand(Command commandToStart) {
super("Start(" + commandToStart + ")");
m_commandToFork = commandToStart;
}
/**
* Instantiates a {@link StartCommand} which will start the given command
* whenever its {@link Command#initialize() initialize()} is called.
*$
* @param commandToStart the {@link Command} to start
*/
public StartCommand(Command commandToStart) {
super("Start(" + commandToStart + ")");
m_commandToFork = commandToStart;
}
protected void initialize() {
m_commandToFork.start();
}
protected void initialize() {
m_commandToFork.start();
}
protected void execute() {
}
protected void execute() {}
protected boolean isFinished() {
return true;
}
protected boolean isFinished() {
return true;
}
protected void end() {
}
protected void end() {}
protected void interrupted() {
}
protected void interrupted() {}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
@@ -15,183 +15,203 @@ import java.util.Vector;
/**
* This class defines a major component of the robot.
*
* <p>A good example of a subsystem is the driveline, or a claw if the robot has one.</p>
* <p>
* A good example of a subsystem is the driveline, or a claw if the robot has
* one.
* </p>
*
* <p>All motors should be a part of a subsystem. For instance, all the wheel motors should be
* a part of some kind of "Driveline" subsystem.</p>
* <p>
* All motors should be a part of a subsystem. For instance, all the wheel
* motors should be a part of some kind of "Driveline" subsystem.
* </p>
*
* <p>Subsystems are used within the command system as requirements for {@link Command}.
* Only one command which requires a subsystem can run at a time. Also, subsystems
* can have default commands which are started if there is no command running which
* requires this subsystem.</p>
* <p>
* Subsystems are used within the command system as requirements for
* {@link Command}. Only one command which requires a subsystem can run at a
* time. Also, subsystems can have default commands which are started if there
* is no command running which requires this subsystem.
* </p>
*
* @author Joe Grinstead
* @see Command
*/
public abstract class Subsystem implements NamedSendable {
/** Whether or not getDefaultCommand() was called */
private boolean initializedDefaultCommand = false;
/** The current command */
private Command currentCommand;
private boolean currentCommandChanged;
/** Whether or not getDefaultCommand() was called */
private boolean initializedDefaultCommand = false;
/** The current command */
private Command currentCommand;
private boolean currentCommandChanged;
/** The default command */
private Command defaultCommand;
/** The name */
private String name;
/** List of all subsystems created */
private static Vector allSubsystems = new Vector();
/** The default command */
private Command defaultCommand;
/** The name */
private String name;
/** List of all subsystems created */
private static Vector allSubsystems = new Vector();
/**
* Creates a subsystem with the given name
* @param name the name of the subsystem
*/
public Subsystem(String name) {
this.name = name;
Scheduler.getInstance().registerSubsystem(this);
/**
* Creates a subsystem with the given name
*$
* @param name the name of the subsystem
*/
public Subsystem(String name) {
this.name = name;
Scheduler.getInstance().registerSubsystem(this);
}
/**
* Creates a subsystem. This will set the name to the name of the class.
*/
public Subsystem() {
this.name = getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1);
Scheduler.getInstance().registerSubsystem(this);
currentCommandChanged = true;
}
/**
* Initialize the default command for a subsystem By default subsystems have
* no default command, but if they do, the default command is set with this
* method. It is called on all Subsystems by CommandBase in the users program
* after all the Subsystems are created.
*/
protected abstract void initDefaultCommand();
/**
* Sets the default command. If this is not called or is called with null,
* then there will be no default command for the subsystem.
*
* <p>
* <b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the
* subsystem is a singleton.
* </p>
*
* @param command the default command (or null if there should be none)
* @throws IllegalUseOfCommandException if the command does not require the
* subsystem
*/
protected void setDefaultCommand(Command command) {
if (command == null) {
defaultCommand = null;
} else {
boolean found = false;
Enumeration requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
if (requirements.nextElement().equals(this)) {
found = true;
// } else {
// throw new
// IllegalUseOfCommandException("A default command cannot require multiple subsystems");
}
}
if (!found) {
throw new IllegalUseOfCommandException("A default command must require the subsystem");
}
defaultCommand = command;
}
/**
* Creates a subsystem. This will set the name to the name of the class.
*/
public Subsystem() {
this.name = getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1);
Scheduler.getInstance().registerSubsystem(this);
currentCommandChanged = true;
if (table != null) {
if (defaultCommand != null) {
table.putBoolean("hasDefault", true);
table.putString("default", defaultCommand.getName());
} else {
table.putBoolean("hasDefault", false);
}
}
}
/**
* Initialize the default command for a subsystem
* By default subsystems have no default command, but if they do, the default command is set
* with this method. It is called on all Subsystems by CommandBase in the users program after
* all the Subsystems are created.
*/
protected abstract void initDefaultCommand();
/**
* Returns the default command (or null if there is none).
*$
* @return the default command
*/
protected Command getDefaultCommand() {
if (!initializedDefaultCommand) {
initializedDefaultCommand = true;
initDefaultCommand();
}
return defaultCommand;
}
/**
* Sets the default command. If this is not called or is called with null,
* then there will be no default command for the subsystem.
*
* <p><b>WARNING:</b> This should <b>NOT</b> be called in a constructor if the subsystem is a
* singleton.</p>
*
* @param command the default command (or null if there should be none)
* @throws IllegalUseOfCommandException if the command does not require the subsystem
*/
protected void setDefaultCommand(Command command) {
if (command == null) {
defaultCommand = null;
/**
* Sets the current command
*$
* @param command the new current command
*/
void setCurrentCommand(Command command) {
currentCommand = command;
currentCommandChanged = true;
}
/**
* Call this to alert Subsystem that the current command is actually the
* command. Sometimes, the {@link Subsystem} is told that it has no command
* while the {@link Scheduler} is going through the loop, only to be soon
* after given a new one. This will avoid that situation.
*/
void confirmCommand() {
if (currentCommandChanged) {
if (table != null) {
if (currentCommand != null) {
table.putBoolean("hasCommand", true);
table.putString("command", currentCommand.getName());
} else {
boolean found = false;
Enumeration requirements = command.getRequirements();
while (requirements.hasMoreElements()) {
if (requirements.nextElement().equals(this)) {
found = true;
// } else {
// throw new IllegalUseOfCommandException("A default command cannot require multiple subsystems");
}
}
if (!found) {
throw new IllegalUseOfCommandException("A default command must require the subsystem");
}
defaultCommand = command;
}
if (table != null) {
if (defaultCommand != null) {
table.putBoolean("hasDefault", true);
table.putString("default", defaultCommand.getName());
} else {
table.putBoolean("hasDefault", false);
}
table.putBoolean("hasCommand", false);
}
}
currentCommandChanged = false;
}
}
/**
* Returns the default command (or null if there is none).
* @return the default command
*/
protected Command getDefaultCommand() {
if (!initializedDefaultCommand) {
initializedDefaultCommand = true;
initDefaultCommand();
}
return defaultCommand;
}
/**
* Returns the command which currently claims this subsystem.
*$
* @return the command which currently claims this subsystem
*/
public Command getCurrentCommand() {
return currentCommand;
}
/**
* Sets the current command
* @param command the new current command
*/
void setCurrentCommand(Command command) {
currentCommand = command;
currentCommandChanged = true;
}
public String toString() {
return getName();
}
/**
* Call this to alert Subsystem that the current command is actually the command.
* Sometimes, the {@link Subsystem} is told that it has no command while the {@link Scheduler}
* is going through the loop, only to be soon after given a new one. This will avoid that situation.
*/
void confirmCommand() {
if (currentCommandChanged) {
if (table != null) {
if (currentCommand != null) {
table.putBoolean("hasCommand", true);
table.putString("command", currentCommand.getName());
} else {
table.putBoolean("hasCommand", false);
}
}
currentCommandChanged = false;
}
}
/**
* Returns the name of this subsystem, which is by default the class name.
*$
* @return the name of this subsystem
*/
public String getName() {
return name;
}
/**
* Returns the command which currently claims this subsystem.
* @return the command which currently claims this subsystem
*/
public Command getCurrentCommand() {
return currentCommand;
}
public String getSmartDashboardType() {
return "Subsystem";
}
public String toString() {
return getName();
}
private ITable table;
/**
* Returns the name of this subsystem, which is by default the class name.
* @return the name of this subsystem
*/
public String getName() {
return name;
public void initTable(ITable table) {
this.table = table;
if (table != null) {
if (defaultCommand != null) {
table.putBoolean("hasDefault", true);
table.putString("default", defaultCommand.getName());
} else {
table.putBoolean("hasDefault", false);
}
if (currentCommand != null) {
table.putBoolean("hasCommand", true);
table.putString("command", currentCommand.getName());
} else {
table.putBoolean("hasCommand", false);
}
}
}
public String getSmartDashboardType() {
return "Subsystem";
}
private ITable table;
public void initTable(ITable table) {
this.table = table;
if(table!=null) {
if (defaultCommand != null) {
table.putBoolean("hasDefault", true);
table.putString("default", defaultCommand.getName());
} else {
table.putBoolean("hasDefault", false);
}
if (currentCommand != null) {
table.putBoolean("hasCommand", true);
table.putString("command", currentCommand.getName());
} else {
table.putBoolean("hasCommand", false);
}
}
}
/**
* {@inheritDoc}
*/
public ITable getTable() {
return table;
}
/**
* {@inheritDoc}
*/
public ITable getTable() {
return table;
}
}

View File

@@ -1,50 +1,50 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
/**
* A {@link WaitCommand} will wait for a certain amount of time before finishing.
* It is useful if you want a {@link CommandGroup} to pause for a moment.
* A {@link WaitCommand} will wait for a certain amount of time before
* finishing. It is useful if you want a {@link CommandGroup} to pause for a
* moment.
*$
* @author Joe Grinstead
* @see CommandGroup
*/
public class WaitCommand extends Command {
/**
* Instantiates a {@link WaitCommand} with the given timeout.
* @param timeout the time the command takes to run
*/
public WaitCommand(double timeout) {
this("Wait(" + timeout + ")", timeout);
}
/**
* Instantiates a {@link WaitCommand} with the given timeout.
*$
* @param timeout the time the command takes to run
*/
public WaitCommand(double timeout) {
this("Wait(" + timeout + ")", timeout);
}
/**
* Instantiates a {@link WaitCommand} with the given timeout.
* @param name the name of the command
* @param timeout the time the command takes to run
*/
public WaitCommand(String name, double timeout) {
super(name, timeout);
}
/**
* Instantiates a {@link WaitCommand} with the given timeout.
*$
* @param name the name of the command
* @param timeout the time the command takes to run
*/
public WaitCommand(String name, double timeout) {
super(name, timeout);
}
protected void initialize() {
}
protected void initialize() {}
protected void execute() {
}
protected void execute() {}
protected boolean isFinished() {
return isTimedOut();
}
protected boolean isFinished() {
return isTimedOut();
}
protected void end() {
}
protected void end() {}
protected void interrupted() {
}
protected void interrupted() {}
}

View File

@@ -1,36 +1,37 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
/**
* This command will only finish if whatever {@link CommandGroup} it is in has no active children.
* If it is not a part of a {@link CommandGroup}, then it will finish immediately. If it is itself an
* active child, then the {@link CommandGroup} will never end.
* This command will only finish if whatever {@link CommandGroup} it is in has
* no active children. If it is not a part of a {@link CommandGroup}, then it
* will finish immediately. If it is itself an active child, then the
* {@link CommandGroup} will never end.
*
* <p>This class is useful for the situation where you want to allow anything running in parallel to finish, before continuing
* in the main {@link CommandGroup} sequence.</p>
* <p>
* This class is useful for the situation where you want to allow anything
* running in parallel to finish, before continuing in the main
* {@link CommandGroup} sequence.
* </p>
*$
* @author Joe Grinstead
*/
public class WaitForChildren extends Command {
protected void initialize() {
}
protected void initialize() {}
protected void execute() {
}
protected void execute() {}
protected void end() {
}
protected void end() {}
protected void interrupted() {
}
protected void interrupted() {}
protected boolean isFinished() {
return getGroup() == null || getGroup().m_children.isEmpty();
}
protected boolean isFinished() {
return getGroup() == null || getGroup().m_children.isEmpty();
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.command;
@@ -10,36 +10,33 @@ package edu.wpi.first.wpilibj.command;
import edu.wpi.first.wpilibj.Timer;
/**
* WaitUntilCommand - waits until an absolute game time.
* This will wait until the game clock reaches some value, then continue to the next command.
* WaitUntilCommand - waits until an absolute game time. This will wait until
* the game clock reaches some value, then continue to the next command.
*$
* @author brad
*
*/
public class WaitUntilCommand extends Command {
private double m_time;
private double m_time;
public WaitUntilCommand(double time) {
super("WaitUntil(" + time + ")");
m_time = time;
}
public WaitUntilCommand(double time) {
super("WaitUntil(" + time + ")");
m_time = time;
}
public void initialize() {
}
public void initialize() {}
public void execute() {
}
public void execute() {}
/**
* Check if we've reached the actual finish time.
*/
public boolean isFinished() {
return Timer.getMatchTime() >= m_time;
}
/**
* Check if we've reached the actual finish time.
*/
public boolean isFinished() {
return Timer.getMatchTime() >= m_time;
}
public void end() {
}
public void end() {}
public void interrupted() {
}
public void interrupted() {}
}

View File

@@ -1,7 +1,7 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 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 $(WIND_BASE)/WPILib. */
/* Copyright (c) FIRST 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 $(WIND_BASE)/WPILib. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.interfaces;
@@ -9,40 +9,37 @@ package edu.wpi.first.wpilibj.interfaces;
* Interface for 3-axis accelerometers
*/
public interface Accelerometer {
public enum Range
{
k2G,
k4G,
k8G,
k16G
}
public enum Range {
k2G, k4G, k8G, k16G
}
/**
* Common interface for setting the measuring range of an accelerometer.
*
* @param range The maximum acceleration, positive or negative, that the
* accelerometer will measure. Not all accelerometers support all ranges.
*/
public void setRange(Range range);
/**
* Common interface for setting the measuring range of an accelerometer.
*
* @param range The maximum acceleration, positive or negative, that the
* accelerometer will measure. Not all accelerometers support all
* ranges.
*/
public void setRange(Range range);
/**
* Common interface for getting the x axis acceleration
*
* @return The acceleration along the x axis in g-forces
*/
public double getX();
/**
* Common interface for getting the x axis acceleration
*
* @return The acceleration along the x axis in g-forces
*/
public double getX();
/**
* Common interface for getting the y axis acceleration
*
* @return The acceleration along the y axis in g-forces
*/
public double getY();
/**
* Common interface for getting the y axis acceleration
*
* @return The acceleration along the y axis in g-forces
*/
public double getY();
/**
* Common interface for getting the z axis acceleration
*
* @return The acceleration along the z axis in g-forces
*/
public double getZ();
/**
* Common interface for getting the z axis acceleration
*
* @return The acceleration along the z axis in g-forces
*/
public double getZ();
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.interfaces;
@@ -13,5 +13,5 @@ import edu.wpi.first.wpilibj.PIDSource;
* @author alex
*/
public interface Potentiometer extends PIDSource {
double get();
double get();
}

View File

@@ -1,6 +1,6 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
package edu.wpi.first.wpilibj.livewindow;
@@ -12,36 +12,39 @@ import java.util.Hashtable;
import java.util.Vector;
/**
* A LiveWindow component is a device (sensor or actuator) that should be added to the
* SmartDashboard in test mode. The components are cached until the first time the robot
* enters Test mode. This allows the components to be inserted, then renamed.
* A LiveWindow component is a device (sensor or actuator) that should be added
* to the SmartDashboard in test mode. The components are cached until the first
* time the robot enters Test mode. This allows the components to be inserted,
* then renamed.
*$
* @author brad
*/
class LiveWindowComponent {
String m_subsystem;
String m_name;
boolean m_isSensor;
String m_subsystem;
String m_name;
boolean m_isSensor;
public LiveWindowComponent(String subsystem, String name, boolean isSensor) {
m_subsystem = subsystem;
m_name = name;
m_isSensor = isSensor;
}
public LiveWindowComponent(String subsystem, String name, boolean isSensor) {
m_subsystem = subsystem;
m_name = name;
m_isSensor = isSensor;
}
public String getName() {
return m_name;
}
public String getName() {
return m_name;
}
public String getSubsystem() {
return m_subsystem;
}
public String getSubsystem() {
return m_subsystem;
}
public boolean isSensor() {
return m_isSensor;
}
public boolean isSensor() {
return m_isSensor;
}
}
/**
* The LiveWindow class is the public interface for putting sensors and
* actuators on the LiveWindow.
@@ -50,172 +53,170 @@ class LiveWindowComponent {
*/
public class LiveWindow {
private static Vector sensors = new Vector();
// private static Vector actuators = new Vector();
private static Hashtable components = new Hashtable();
private static ITable livewindowTable;
private static ITable statusTable;
private static boolean liveWindowEnabled = false;
private static boolean firstTime = true;
private static Vector sensors = new Vector();
// private static Vector actuators = new Vector();
private static Hashtable components = new Hashtable();
private static ITable livewindowTable;
private static ITable statusTable;
private static boolean liveWindowEnabled = false;
private static boolean firstTime = true;
/**
* Initialize all the LiveWindow elements the first time we enter LiveWindow
* mode. By holding off creating the NetworkTable entries, it allows them to
* be redefined before the first time in LiveWindow mode. This allows
* default sensor and actuator values to be created that are replaced with
* the custom names from users calling addActuator and addSensor.
*/
private static void initializeLiveWindowComponents() {
System.out.println("Initializing the components first time");
livewindowTable = NetworkTable.getTable("LiveWindow");
statusTable = livewindowTable.getSubTable("~STATUS~");
for (Enumeration e = components.keys(); e.hasMoreElements();) {
LiveWindowSendable component = (LiveWindowSendable) e.nextElement();
LiveWindowComponent c = (LiveWindowComponent) components.get(component);
String subsystem = c.getSubsystem();
String name = c.getName();
System.out.println("Initializing table for '" + subsystem + "' '" + name + "'");
livewindowTable.getSubTable(subsystem).putString("~TYPE~", "LW Subsystem");
ITable table = livewindowTable.getSubTable(subsystem).getSubTable(name);
table.putString("~TYPE~", component.getSmartDashboardType());
table.putString("Name", name);
table.putString("Subsystem", subsystem);
component.initTable(table);
if (c.isSensor()) {
sensors.addElement(component);
}
}
}
/**
* Set the enabled state of LiveWindow. If it's being enabled, turn off the
* scheduler and remove all the commands from the queue and enable all the
* components registered for LiveWindow. If it's being disabled, stop all
* the registered components and reenable the scheduler. TODO: add code to
* disable PID loops when enabling LiveWindow. The commands should reenable
* the PID loops themselves when they get rescheduled. This prevents arms
* from starting to move around, etc. after a period of adjusting them in
* LiveWindow mode.
*/
public static void setEnabled(boolean enabled) {
if (liveWindowEnabled != enabled) {
if (enabled) {
System.out.println("Starting live window mode.");
if (firstTime) {
initializeLiveWindowComponents();
firstTime = false;
}
Scheduler.getInstance().disable();
Scheduler.getInstance().removeAll();
for (Enumeration e = components.keys(); e.hasMoreElements();) {
LiveWindowSendable component = (LiveWindowSendable) e.nextElement();
component.startLiveWindowMode();
}
} else {
System.out.println("stopping live window mode.");
for (Enumeration e = components.keys(); e.hasMoreElements();) {
LiveWindowSendable component = (LiveWindowSendable) e.nextElement();
component.stopLiveWindowMode();
}
Scheduler.getInstance().enable();
}
liveWindowEnabled = enabled;
statusTable.putBoolean("LW Enabled", enabled);
}
}
/**
* The run method is called repeatedly to keep the values refreshed on the screen in
* test mode.
*/
public static void run() {
updateValues();
}
/**
* Add a Sensor associated with the subsystem and with call it by the given
* name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A LiveWindowSendable component that represents a sensor.
*/
public static void addSensor(String subsystem, String name, LiveWindowSendable component) {
components.put(component, new LiveWindowComponent(subsystem, name, true));
}
/**
* Add an Actuator associated with the subsystem and with call it by the
* given name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A LiveWindowSendable component that represents a
* actuator.
*/
public static void addActuator(String subsystem, String name, LiveWindowSendable component) {
components.put(component, new LiveWindowComponent(subsystem, name, false));
}
/**
* Puts all sensor values on the live window.
*/
private static void updateValues() {
//TODO: gross - needs to be sped up
for (int i = 0; i < sensors.size(); i++) {
LiveWindowSendable lws = (LiveWindowSendable) sensors.elementAt(i);
lws.updateTable();
}
// TODO: Add actuators?
// TODO: Add better rate limiting.
}
/**
* 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 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 channel, LiveWindowSendable component) {
addSensor("Ungrouped", moduleType + "[" + channel + "]", component);
if (sensors.contains(component)) {
sensors.removeElement(component);
}
/**
* Initialize all the LiveWindow elements the first time we enter LiveWindow
* mode. By holding off creating the NetworkTable entries, it allows them to
* be redefined before the first time in LiveWindow mode. This allows default
* sensor and actuator values to be created that are replaced with the custom
* names from users calling addActuator and addSensor.
*/
private static void initializeLiveWindowComponents() {
System.out.println("Initializing the components first time");
livewindowTable = NetworkTable.getTable("LiveWindow");
statusTable = livewindowTable.getSubTable("~STATUS~");
for (Enumeration e = components.keys(); e.hasMoreElements();) {
LiveWindowSendable component = (LiveWindowSendable) e.nextElement();
LiveWindowComponent c = (LiveWindowComponent) components.get(component);
String subsystem = c.getSubsystem();
String name = c.getName();
System.out.println("Initializing table for '" + subsystem + "' '" + name + "'");
livewindowTable.getSubTable(subsystem).putString("~TYPE~", "LW Subsystem");
ITable table = livewindowTable.getSubTable(subsystem).getSubTable(name);
table.putString("~TYPE~", component.getSmartDashboardType());
table.putString("Name", name);
table.putString("Subsystem", subsystem);
component.initTable(table);
if (c.isSensor()) {
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);
/**
* Set the enabled state of LiveWindow. If it's being enabled, turn off the
* scheduler and remove all the commands from the queue and enable all the
* components registered for LiveWindow. If it's being disabled, stop all the
* registered components and reenable the scheduler. TODO: add code to disable
* PID loops when enabling LiveWindow. The commands should reenable the PID
* loops themselves when they get rescheduled. This prevents arms from
* starting to move around, etc. after a period of adjusting them in
* LiveWindow mode.
*/
public static void setEnabled(boolean enabled) {
if (liveWindowEnabled != enabled) {
if (enabled) {
System.out.println("Starting live window mode.");
if (firstTime) {
initializeLiveWindowComponents();
firstTime = false;
}
Scheduler.getInstance().disable();
Scheduler.getInstance().removeAll();
for (Enumeration e = components.keys(); e.hasMoreElements();) {
LiveWindowSendable component = (LiveWindowSendable) e.nextElement();
component.startLiveWindowMode();
}
} else {
System.out.println("stopping live window mode.");
for (Enumeration e = components.keys(); e.hasMoreElements();) {
LiveWindowSendable component = (LiveWindowSendable) e.nextElement();
component.stopLiveWindowMode();
}
Scheduler.getInstance().enable();
}
liveWindowEnabled = enabled;
statusTable.putBoolean("LW Enabled", enabled);
}
}
/**
* 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 moduleNumber The number of the particular module type
* @param channel The channel number the device is plugged into (usually
* PWM)
* @param component The reference to the object being added
*/
public static void addActuator(String moduleType, int moduleNumber, int channel, LiveWindowSendable component) {
addActuator("Ungrouped", moduleType + "[" + moduleNumber + "," + channel + "]", component);
/**
* The run method is called repeatedly to keep the values refreshed on the
* screen in test mode.
*/
public static void run() {
updateValues();
}
/**
* Add a Sensor associated with the subsystem and with call it by the given
* name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A LiveWindowSendable component that represents a sensor.
*/
public static void addSensor(String subsystem, String name, LiveWindowSendable component) {
components.put(component, new LiveWindowComponent(subsystem, name, true));
}
/**
* Add an Actuator associated with the subsystem and with call it by the given
* name.
*
* @param subsystem The subsystem this component is part of.
* @param name The name of this component.
* @param component A LiveWindowSendable component that represents a actuator.
*/
public static void addActuator(String subsystem, String name, LiveWindowSendable component) {
components.put(component, new LiveWindowComponent(subsystem, name, false));
}
/**
* Puts all sensor values on the live window.
*/
private static void updateValues() {
// TODO: gross - needs to be sped up
for (int i = 0; i < sensors.size(); i++) {
LiveWindowSendable lws = (LiveWindowSendable) sensors.elementAt(i);
lws.updateTable();
}
// TODO: Add actuators?
// TODO: Add better rate limiting.
}
/**
* 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 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 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 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 moduleNumber The number of the particular module type
* @param channel The channel number the device is plugged into (usually PWM)
* @param component The reference to the object being added
*/
public static void addActuator(String moduleType, int moduleNumber, int channel,
LiveWindowSendable component) {
addActuator("Ungrouped", moduleType + "[" + moduleNumber + "," + channel + "]", component);
}
}

View File

@@ -1,6 +1,6 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
* To change this template, choose Tools | Templates and open the template in
* the editor.
*/
package edu.wpi.first.wpilibj.livewindow;
@@ -12,21 +12,19 @@ import edu.wpi.first.wpilibj.Sendable;
* @author Alex Henning
*/
public interface LiveWindowSendable extends Sendable {
/**
* Update the table for this sendable object with the latest
* values.
*/
public void updateTable();
/**
* Update the table for this sendable object with the latest values.
*/
public void updateTable();
/**
* Start having this sendable object automatically respond to
* value changes reflect the value on the table.
*/
public void startLiveWindowMode();
/**
* Start having this sendable object automatically respond to value changes
* reflect the value on the table.
*/
public void startLiveWindowMode();
/**
* Stop having this sendable object automatically respond to value
* changes.
*/
public void stopLiveWindowMode();
/**
* Stop having this sendable object automatically respond to value changes.
*/
public void stopLiveWindowMode();
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.smartdashboard;
@@ -16,131 +16,132 @@ import edu.wpi.first.wpilibj.tables.ITable;
* The {@link SendableChooser} class is a useful tool for presenting a selection
* of options to the {@link SmartDashboard}.
*
* <p>For instance, you may wish to be able to select between multiple
* autonomous modes. You can do this by putting every possible {@link Command}
* you want to run as an autonomous into a {@link SendableChooser} and then put
* it into the {@link SmartDashboard} to have a list of options appear on the
* laptop. Once autonomous starts, simply ask the {@link SendableChooser} what
* the selected value is.</p>
* <p>
* For instance, you may wish to be able to select between multiple autonomous
* modes. You can do this by putting every possible {@link Command} you want to
* run as an autonomous into a {@link SendableChooser} and then put it into the
* {@link SmartDashboard} to have a list of options appear on the laptop. Once
* autonomous starts, simply ask the {@link SendableChooser} what the selected
* value is.
* </p>
*
* @author Joe Grinstead
*/
public class SendableChooser implements Sendable {
/**
* The key for the default value
*/
private static final String DEFAULT = "default";
/**
* The key for the selected option
*/
private static final String SELECTED = "selected";
/**
* The key for the option array
*/
private static final String OPTIONS = "options";
/**
* A table linking strings to the objects the represent
*/
private StringArray choices = new StringArray();
private List values = new List();
private String defaultChoice = null;
private Object defaultValue = null;
/**
* The key for the default value
*/
private static final String DEFAULT = "default";
/**
* The key for the selected option
*/
private static final String SELECTED = "selected";
/**
* The key for the option array
*/
private static final String OPTIONS = "options";
/**
* A table linking strings to the objects the represent
*/
private StringArray choices = new StringArray();
private List values = new List();
private String defaultChoice = null;
private Object defaultValue = null;
/**
* Instantiates a {@link SendableChooser}.
*/
public SendableChooser() {
/**
* Instantiates a {@link SendableChooser}.
*/
public SendableChooser() {}
/**
* Adds the given object to the list of options. On the {@link SmartDashboard}
* on the desktop, the object will appear as the given name.
*
* @param name the name of the option
* @param object the option
*/
public void addObject(String name, Object object) {
// if we don't have a default, set the default automatically
if (defaultChoice == null) {
addDefault(name, object);
return;
}
/**
* Adds the given object to the list of options. On the
* {@link SmartDashboard} on the desktop, the object will appear as the
* given name.
*
* @param name the name of the option
* @param object the option
*/
public void addObject(String name, Object object) {
//if we don't have a default, set the default automatically
if (defaultChoice == null) {
addDefault(name, object);
return;
}
for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).equals(name)) {
choices.set(i, name);
values.set(i, object);
return;
}
}
//not found
choices.add(name);
values.add(object);
if (table != null) {
table.putValue(OPTIONS, choices);
}
for (int i = 0; i < choices.size(); ++i) {
if (choices.get(i).equals(name)) {
choices.set(i, name);
values.set(i, object);
return;
}
}
/**
* Add the given object to the list of options and marks it as the default.
* Functionally, this is very close to
* {@link SendableChooser#addObject(java.lang.String, java.lang.Object) addObject(...)}
* except that it will use this as the default option if none other is
* explicitly selected.
*
* @param name the name of the option
* @param object the option
*/
public void addDefault(String name, Object object) {
if (name == null) {
throw new NullPointerException("Name cannot be null");
}
defaultChoice = name;
defaultValue = object;
if (table != null) {
table.putString(DEFAULT, defaultChoice);
}
addObject(name, object);
// not found
choices.add(name);
values.add(object);
if (table != null) {
table.putValue(OPTIONS, choices);
}
}
/**
* Returns the selected option. If there is none selected, it will return
* the default. If there is none selected and no default, then it will
* return {@code null}.
*
* @return the option selected
*/
public Object getSelected() {
String selected = table.getString(SELECTED, null);
for (int i = 0; i < values.size(); ++i) {
if (choices.get(i).equals(selected)) {
return values.get(i);
}
}
return defaultValue;
/**
* Add the given object to the list of options and marks it as the default.
* Functionally, this is very close to
* {@link SendableChooser#addObject(java.lang.String, java.lang.Object)
* addObject(...)} except that it will use this as the default option if none
* other is explicitly selected.
*
* @param name the name of the option
* @param object the option
*/
public void addDefault(String name, Object object) {
if (name == null) {
throw new NullPointerException("Name cannot be null");
}
public String getSmartDashboardType() {
return "String Chooser";
defaultChoice = name;
defaultValue = object;
if (table != null) {
table.putString(DEFAULT, defaultChoice);
}
private ITable table;
addObject(name, object);
}
public void initTable(ITable table) {
this.table = table;
if (table != null) {
table.putValue(OPTIONS, choices);
if (defaultChoice != null) {
table.putString(DEFAULT, defaultChoice);
}
}
/**
* Returns the selected option. If there is none selected, it will return the
* default. If there is none selected and no default, then it will return
* {@code null}.
*
* @return the option selected
*/
public Object getSelected() {
String selected = table.getString(SELECTED, null);
for (int i = 0; i < values.size(); ++i) {
if (choices.get(i).equals(selected)) {
return values.get(i);
}
}
return defaultValue;
/**
* {@inheritDoc}
*/
public ITable getTable() {
return table;
}
public String getSmartDashboardType() {
return "String Chooser";
}
private ITable table;
public void initTable(ITable table) {
this.table = table;
if (table != null) {
table.putValue(OPTIONS, choices);
if (defaultChoice != null) {
table.putString(DEFAULT, defaultChoice);
}
}
}
/**
* {@inheritDoc}
*/
public ITable getTable() {
return table;
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.smartdashboard;
@@ -18,283 +18,312 @@ import java.util.Hashtable;
import java.util.NoSuchElementException;
/**
* The {@link SmartDashboard} class is the bridge between robot programs and the SmartDashboard on the
* laptop.
* The {@link SmartDashboard} class is the bridge between robot programs and the
* SmartDashboard on the laptop.
*
* <p>When a value is put into the SmartDashboard here, it pops up on the SmartDashboard on the laptop.
* Users can put values into and get values from the SmartDashboard</p>
* <p>
* When a value is put into the SmartDashboard here, it pops up on the
* SmartDashboard on the laptop. Users can put values into and get values from
* the SmartDashboard
* </p>
*
* @author Joe Grinstead
*/
public class SmartDashboard {
/** The {@link NetworkTable} used by {@link SmartDashboard} */
private static final NetworkTable table = NetworkTable.getTable("SmartDashboard");
/**
* A table linking tables in the SmartDashboard to the {@link SmartDashboardData} objects
* they came from.
*/
private static final Hashtable tablesToData = new Hashtable();
/** The {@link NetworkTable} used by {@link SmartDashboard} */
private static final NetworkTable table = NetworkTable.getTable("SmartDashboard");
/**
* A table linking tables in the SmartDashboard to the
* {@link SmartDashboardData} objects they came from.
*/
private static final Hashtable tablesToData = new Hashtable();
static {
HLUsageReporting.reportSmartDashboard();
static {
HLUsageReporting.reportSmartDashboard();
}
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*$
* @param key the key
* @param data the value
* @throws IllegalArgumentException if key is null
*/
public static void putData(String key, Sendable data) {
ITable dataTable = table.getSubTable(key);
dataTable.putString("~TYPE~", data.getSmartDashboardType());
data.initTable(dataTable);
tablesToData.put(data, key);
}
// TODO should we reimplement NamedSendable?
/**
* Maps the specified key (where the key is the name of the
* {@link NamedSendable} SmartDashboardNamedData to the specified value in
* this table. The value can be retrieved by calling the get method with a key
* that is equal to the original key.
*$
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putData(NamedSendable value) {
putData(value.getName(), value);
}
/**
* Returns the value at the specified key.
*$
* @param key the key
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the key is null
*/
public static Sendable getData(String key) {
ITable subtable = table.getSubTable(key);
Object data = tablesToData.get(subtable);
if (data == null) {
throw new IllegalArgumentException("SmartDashboard data does not exist: " + key);
} else {
return (Sendable) data;
}
}
/**
* Maps the specified key to the specified value in this table.
* The key can not be null.
* The value can be retrieved by calling the get method with a key that is equal to the original key.
* @param key the key
* @param data the value
* @throws IllegalArgumentException if key is null
*/
public static void putData(String key, Sendable data) {
ITable dataTable = table.getSubTable(key);
dataTable.putString("~TYPE~", data.getSmartDashboardType());
data.initTable(dataTable);
tablesToData.put(data, key);
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*$
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putBoolean(String key, boolean value) {
table.putBoolean(key, value);
}
/**
* Returns the value at the specified key.
*$
* @param key the key
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* boolean
* @throws IllegalArgumentException if the key is null
*/
public static boolean getBoolean(String key) throws TableKeyNotDefinedException {
return table.getBoolean(key);
}
/**
* Returns the value at the specified key.
*$
* @param key the key
* @param defaultValue returned if the key doesn't exist
* @return the value
* @throws IllegalArgumentException if the value mapped to by the key is not a
* boolean
* @throws IllegalArgumentException if the key is null
*/
public static boolean getBoolean(String key, boolean defaultValue) {
return table.getBoolean(key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table. The key can
* not be null. The value can be retrieved by calling the get method with a
* key that is equal to the original key.
*$
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putNumber(String key, double value) {
table.putNumber(key, value);
}
/**
* Returns the value at the specified key.
*$
* @param key the key
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the
* key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* double
* @throws IllegalArgumentException if the key is null
*/
public static double getNumber(String key) throws TableKeyNotDefinedException {
return table.getNumber(key);
}
/**
* Returns the value at the specified key.
*$
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* double
* @throws IllegalArgumentException if the key is null
*/
public static double getNumber(String key, double defaultValue) {
return table.getNumber(key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table. Neither the
* key nor the value can be null. The value can be retrieved by calling the
* get method with a key that is equal to the original key.
*$
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key or value is null
*/
public static void putString(String key, String value) {
table.putString(key, value);
}
/**
* Returns the value at the specified key.
*$
* @param key the key
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* string
* @throws IllegalArgumentException if the key is null
*/
public static String getString(String key) throws TableKeyNotDefinedException {
return table.getString(key);
}
/**
* Returns the value at the specified key.
*$
* @param key the key
* @param defaultValue The value returned if the key is undefined
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* string
* @throws IllegalArgumentException if the key is null
*/
public static String getString(String key, String defaultValue) {
return table.getString(key, defaultValue);
}
/*
* Deprecated Methods
*/
/**
* Maps the specified key to the specified value in this table.
*
* The key can not be null. The value can be retrieved by calling the get
* method with a key that is equal to the original key.
*
* @deprecated Use {@link #putNumber(java.lang.String, double) putNumber
* method} instead
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putInt(String key, int value) {
table.putNumber(key, value);
}
/**
* Returns the value at the specified key.
*
* @deprecated Use {@link #getNumber(java.lang.String) getNumber} instead
* @param key the key
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the
* key
* @throws IllegalArgumentException if the value mapped to by the key is not
* an int
* @throws IllegalArgumentException if the key is null
*/
public static int getInt(String key) throws TableKeyNotDefinedException {
return (int) table.getNumber(key);
}
/**
* Returns the value at the specified key.
*
* @deprecated Use {@link #getNumber(java.lang.String, double) getNumber}
* instead
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the
* key
* @throws IllegalArgumentException if the value mapped to by the key is not
* an int
* @throws IllegalArgumentException if the key is null
*/
public static int getInt(String key, int defaultValue) throws TableKeyNotDefinedException {
try {
return (int) table.getNumber(key);
} catch (NoSuchElementException ex) {
return defaultValue;
}
}
/**
* Maps the specified key to the specified value in this table.
*
* The key can not be null. The value can be retrieved by calling the get
* method with a key that is equal to the original key.
*
* @deprecated Use{@link #putNumber(java.lang.String, double) putNumber}
* instead
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putDouble(String key, double value) {
table.putNumber(key, value);
}
//TODO should we reimplement NamedSendable?
/**
* Maps the specified key (where the key is the name of the {@link NamedSendable} SmartDashboardNamedData
* to the specified value in this table.
* The value can be retrieved by calling the get method with a key that is equal to the original key.
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putData(NamedSendable value) {
putData(value.getName(), value);
}
/**
* Returns the value at the specified key.
*
* @deprecated Use {@link #getNumber(java.lang.String) getNumber} instead
* @param key the key
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the
* key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* double
* @throws IllegalArgumentException if the key is null
*/
public static double getDouble(String key) throws TableKeyNotDefinedException {
return table.getNumber(key);
}
/**
* Returns the value at the specified key.
* @param key the key
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the key is null
*/
public static Sendable getData(String key) {
ITable subtable = table.getSubTable(key);
Object data = tablesToData.get(subtable);
if (data == null) {
throw new IllegalArgumentException("SmartDashboard data does not exist: " + key);
} else {
return (Sendable) data;
}
}
/**
* Maps the specified key to the specified value in this table.
* The key can not be null.
* The value can be retrieved by calling the get method with a key that is equal to the original key.
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putBoolean(String key, boolean value) {
table.putBoolean(key, value);
}
/**
* Returns the value at the specified key.
* @param key the key
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a boolean
* @throws IllegalArgumentException if the key is null
*/
public static boolean getBoolean(String key) throws TableKeyNotDefinedException {
return table.getBoolean(key);
}
/**
* Returns the value at the specified key.
* @param key the key
* @param defaultValue returned if the key doesn't exist
* @return the value
* @throws IllegalArgumentException if the value mapped to by the key is not a boolean
* @throws IllegalArgumentException if the key is null
*/
public static boolean getBoolean(String key, boolean defaultValue) {
return table.getBoolean(key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table.
* The key can not be null.
* The value can be retrieved by calling the get method with a key that is equal to the original key.
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putNumber(String key, double value) {
table.putNumber(key, value);
}
/**
* Returns the value at the specified key.
* @param key the key
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a double
* @throws IllegalArgumentException if the key is null
*/
public static double getNumber(String key) throws TableKeyNotDefinedException {
return table.getNumber(key);
}
/**
* Returns the value at the specified key.
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a double
* @throws IllegalArgumentException if the key is null
*/
public static double getNumber(String key, double defaultValue) {
return table.getNumber(key, defaultValue);
}
/**
* Maps the specified key to the specified value in this table.
* Neither the key nor the value can be null.
* The value can be retrieved by calling the get method with a key that is equal to the original key.
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key or value is null
*/
public static void putString(String key, String value) {
table.putString(key, value);
}
/**
* Returns the value at the specified key.
* @param key the key
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a string
* @throws IllegalArgumentException if the key is null
*/
public static String getString(String key) throws TableKeyNotDefinedException {
return table.getString(key);
}
/**
* Returns the value at the specified key.
* @param key the key
* @param defaultValue The value returned if the key is undefined
* @return the value
* @throws NetworkTableKeyNotDefined if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a string
* @throws IllegalArgumentException if the key is null
*/
public static String getString(String key, String defaultValue) {
return table.getString(key, defaultValue);
}
/*
* Deprecated Methods
*/
/**
* Maps the specified key to the specified value in this table.
*
* The key can not be null.
* The value can be retrieved by calling the get method with a key that is equal to the original key.
*
* @deprecated Use {@link #putNumber(java.lang.String, double) putNumber method} instead
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putInt(String key, int value) {
table.putNumber(key, value);
}
/**
* Returns the value at the specified key.
*
* @deprecated Use {@link #getNumber(java.lang.String) getNumber} instead
* @param key the key
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not an int
* @throws IllegalArgumentException if the key is null
*/
public static int getInt(String key) throws TableKeyNotDefinedException {
return (int) table.getNumber(key);
}
/**
* Returns the value at the specified key.
*
* @deprecated Use {@link #getNumber(java.lang.String, double) getNumber} instead
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not an int
* @throws IllegalArgumentException if the key is null
*/
public static int getInt(String key, int defaultValue) throws TableKeyNotDefinedException {
try {
return (int) table.getNumber(key);
} catch (NoSuchElementException ex) {
return defaultValue;
}
}
/**
* Maps the specified key to the specified value in this table.
*
* The key can not be null.
* The value can be retrieved by calling the get method with a key that is equal to the original key.
*
* @deprecated Use{@link #putNumber(java.lang.String, double) putNumber} instead
* @param key the key
* @param value the value
* @throws IllegalArgumentException if key is null
*/
public static void putDouble(String key, double value) {
table.putNumber(key, value);
}
/**
* Returns the value at the specified key.
*
* @deprecated Use {@link #getNumber(java.lang.String) getNumber} instead
* @param key the key
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a double
* @throws IllegalArgumentException if the key is null
*/
public static double getDouble(String key) throws TableKeyNotDefinedException {
return table.getNumber(key);
}
/**
* Returns the value at the specified key.
*
* @deprecated Use {@link #getNumber(java.lang.String, double) getNumber} instead.
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the key
* @throws IllegalArgumentException if the value mapped to by the key is not a double
* @throws IllegalArgumentException if the key is null
*/
public static double getDouble(String key, double defaultValue) {
return table.getNumber(key, defaultValue);
}
/**
* Returns the value at the specified key.
*
* @deprecated Use {@link #getNumber(java.lang.String, double) getNumber}
* instead.
* @param key the key
* @param defaultValue the value returned if the key is undefined
* @return the value
* @throws TableKeyNotDefinedException if there is no value mapped to by the
* key
* @throws IllegalArgumentException if the value mapped to by the key is not a
* double
* @throws IllegalArgumentException if the key is null
*/
public static double getDouble(String key, double defaultValue) {
return table.getNumber(key, defaultValue);
}
}

View File

@@ -1,23 +1,25 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.util;
/**
* Exception indicating that the resource is already allocated
*$
* @author dtjones
*/
public class AllocationException extends RuntimeException {
/**
* Create a new AllocationException
* @param msg the message to attach to the exception
*/
public AllocationException(String msg) {
super(msg);
}
/**
* Create a new AllocationException
*$
* @param msg the message to attach to the exception
*/
public AllocationException(String msg) {
super(msg);
}
}

View File

@@ -1,35 +1,39 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2014. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.util;
/**
* Thrown if there is an error caused by a basic system or setting
* not being properly initialized before being used.
*
* Thrown if there is an error caused by a basic system or setting not being
* properly initialized before being used.
*$
* @author Jonathan Leitschuh
*/
public class BaseSystemNotInitializedException extends RuntimeException {
/**
* Create a new BaseSystemNotInitializedException
* @param message the message to attach to the exception
*/
public BaseSystemNotInitializedException(String message) {
super(message);
}
/**
* Create a new BaseSystemNotInitializedException using the offending class that was not set and the
* class that was affected.
* @param offender The class or interface that was not properly initialized.
* @param affected The class that was was affected by this missing initialization.
*/
public BaseSystemNotInitializedException(Class<?> offender, Class<?> affected){
super("The " + offender.getSimpleName() + " for the " + affected.getSimpleName() + " was never set.");
}
/**
* Create a new BaseSystemNotInitializedException
*$
* @param message the message to attach to the exception
*/
public BaseSystemNotInitializedException(String message) {
super(message);
}
/**
* Create a new BaseSystemNotInitializedException using the offending class
* that was not set and the class that was affected.
*$
* @param offender The class or interface that was not properly initialized.
* @param affected The class that was was affected by this missing
* initialization.
*/
public BaseSystemNotInitializedException(Class<?> offender, Class<?> affected) {
super("The " + offender.getSimpleName() + " for the " + affected.getSimpleName()
+ " was never set.");
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.util;
@@ -10,53 +10,44 @@ package edu.wpi.first.wpilibj.util;
/**
* This exception represents an error in which a lower limit was set as higher
* than an upper limit.
*
*$
* @author dtjones
*/
public class BoundaryException extends RuntimeException {
/**
* Create a new exception with the given message
*
* @param message
* the message to attach to the exception
*/
public BoundaryException(String message) {
super(message);
}
/**
* Create a new exception with the given message
*$
* @param message the message to attach to the exception
*/
public BoundaryException(String message) {
super(message);
}
/**
* Make sure that the given value is between the upper and lower bounds, and
* throw an exception if they are not.
*
* @param value
* The value to check.
* @param lower
* The minimum acceptable value.
* @param upper
* The maximum acceptable value.
*/
public static void assertWithinBounds(double value, double lower,
double upper) {
if (value < lower || value > upper)
throw new BoundaryException("Value must be between " + lower
+ " and " + upper + ", " + value + " given");
}
/**
* Make sure that the given value is between the upper and lower bounds, and
* throw an exception if they are not.
*$
* @param value The value to check.
* @param lower The minimum acceptable value.
* @param upper The maximum acceptable value.
*/
public static void assertWithinBounds(double value, double lower, double upper) {
if (value < lower || value > upper)
throw new BoundaryException("Value must be between " + lower + " and " + upper + ", " + value
+ " given");
}
/**
* Returns the message for a boundary exception. Used to keep the message
* consistent across all boundary exceptions.
*
* @param value
* The given value
* @param lower
* The lower limit
* @param upper
* The upper limit
* @return the message for a boundary exception
*/
public static String getMessage(double value, double lower, double upper) {
return "Value must be between " + lower + " and " + upper + ", "
+ value + " given";
}
/**
* Returns the message for a boundary exception. Used to keep the message
* consistent across all boundary exceptions.
*$
* @param value The given value
* @param lower The lower limit
* @param upper The upper limit
* @return the message for a boundary exception
*/
public static String getMessage(double value, double lower, double upper) {
return "Value must be between " + lower + " and " + upper + ", " + value + " given";
}
}

View File

@@ -1,24 +1,26 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.util;
/**
* Exception indicating that the resource is already allocated
* This is meant to be thrown by the resource class
* Exception indicating that the resource is already allocated This is meant to
* be thrown by the resource class
*$
* @author dtjones
*/
public class CheckedAllocationException extends Exception {
/**
* Create a new CheckedAllocationException
* @param msg the message to attach to the exception
*/
public CheckedAllocationException(String msg) {
super(msg);
}
/**
* Create a new CheckedAllocationException
*$
* @param msg the message to attach to the exception
*/
public CheckedAllocationException(String msg) {
super(msg);
}
}

View File

@@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.util;
@@ -14,62 +14,66 @@ import java.util.Vector;
*/
public class SortedVector extends Vector {
/**
* Interface used to determine the order to place sorted objects.
*/
public static interface Comparator {
/**
* Compare the given two objects.
* @param object1 First object to compare
* @param object2 Second object to compare
* @return -1, 0, or 1 if the first object is less than, equal to, or
* greater than the second, respectively
*/
public int compare(Object object1, Object object2);
}
Comparator comparator;
/**
* Interface used to determine the order to place sorted objects.
*/
public static interface Comparator {
/**
* Create a new sorted vector and use the given comparator to determine order.
* @param comparator The comparator to use to determine what order to place
* the elements in this vector.
* Compare the given two objects.
*$
* @param object1 First object to compare
* @param object2 Second object to compare
* @return -1, 0, or 1 if the first object is less than, equal to, or
* greater than the second, respectively
*/
public SortedVector(Comparator comparator) {
this.comparator = comparator;
}
public int compare(Object object1, Object object2);
}
/**
* Adds an element in the Vector, sorted from greatest to least.
* @param element The element to add to the Vector
*/
public void addElement(Object element) {
int highBound = size();
int lowBound = 0;
while (highBound - lowBound > 0) {
int index = (highBound + lowBound) / 2;
int result = comparator.compare(element, elementAt(index));
if (result < 0) {
lowBound = index + 1;
} else if (result > 0) {
highBound = index;
} else {
lowBound = index;
highBound = index;
}
}
insertElementAt(element, lowBound);
}
Comparator comparator;
/**
* Sort the vector.
*/
public void sort() {
Object[] array = new Object[size()];
copyInto(array);
removeAllElements();
for (int i = 0; i < array.length; i++) {
addElement(array[i]);
}
/**
* Create a new sorted vector and use the given comparator to determine order.
*$
* @param comparator The comparator to use to determine what order to place
* the elements in this vector.
*/
public SortedVector(Comparator comparator) {
this.comparator = comparator;
}
/**
* Adds an element in the Vector, sorted from greatest to least.
*$
* @param element The element to add to the Vector
*/
public void addElement(Object element) {
int highBound = size();
int lowBound = 0;
while (highBound - lowBound > 0) {
int index = (highBound + lowBound) / 2;
int result = comparator.compare(element, elementAt(index));
if (result < 0) {
lowBound = index + 1;
} else if (result > 0) {
highBound = index;
} else {
lowBound = index;
highBound = index;
}
}
insertElementAt(element, lowBound);
}
/**
* Sort the vector.
*/
public void sort() {
Object[] array = new Object[size()];
copyInto(array);
removeAllElements();
for (int i = 0; i < array.length; i++) {
addElement(array[i]);
}
}
}

View File

@@ -1,58 +1,63 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* 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. */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.util;
/**
* Exception for bad status codes from the chip object
*$
* @author Brian
*/
public final class UncleanStatusException extends IllegalStateException {
private final int statusCode;
private final int statusCode;
/**
* Create a new UncleanStatusException
* @param status the status code that caused the exception
* @param message A message describing the exception
*/
public UncleanStatusException(int status, String message) {
super(message);
statusCode = status;
}
/**
* Create a new UncleanStatusException
*$
* @param status the status code that caused the exception
* @param message A message describing the exception
*/
public UncleanStatusException(int status, String message) {
super(message);
statusCode = status;
}
/**
* Create a new UncleanStatusException
* @param status the status code that caused the exception
*/
public UncleanStatusException(int status) {
this(status, "Status code was non-zero");
}
/**
* Create a new UncleanStatusException
*$
* @param status the status code that caused the exception
*/
public UncleanStatusException(int status) {
this(status, "Status code was non-zero");
}
/**
* Create a new UncleanStatusException
* @param message a message describing the exception
*/
public UncleanStatusException(String message) {
this(-1, message);
}
/**
* Create a new UncleanStatusException
*$
* @param message a message describing the exception
*/
public UncleanStatusException(String message) {
this(-1, message);
}
/**
* Create a new UncleanStatusException
*/
public UncleanStatusException() {
this(-1, "Status code was non-zero");
}
/**
* Create a new UncleanStatusException
*/
public UncleanStatusException() {
this(-1, "Status code was non-zero");
}
/**
* Create a new UncleanStatusException
* @return the status code that caused the exception
*/
public int getStatus() {
return statusCode;
}
/**
* Create a new UncleanStatusException
*$
* @return the status code that caused the exception
*/
public int getStatus() {
return statusCode;
}
}