001 /*----------------------------------------------------------------------------*/
002 /* Copyright (c) FIRST 2008-2012. All Rights Reserved. */
003 /* Open Source Software - may be modified and shared by FRC teams. The code */
004 /* must be accompanied by the FIRST BSD license file in the root directory of */
005 /* the project. */
006 /*----------------------------------------------------------------------------*/
007
008 package edu.wpi.first.wpilibj;
009
010 /**
011 * The MotorSafetyHelper object is constructed for every object that wants to implement the Motor
012 * Safety protocol. The helper object has the code to actually do the timing and call the
013 * motors Stop() method when the timeout expires. The motor object is expected to call the
014 * Feed() method whenever the motors value is updated.
015 *
016 * @author brad
017 */
018 public class MotorSafetyHelper {
019
020 double m_expiration;
021 boolean m_enabled;
022 double m_stopTime;
023 MotorSafety m_safeObject;
024 MotorSafetyHelper m_nextHelper;
025 static MotorSafetyHelper m_headHelper = null;
026
027 /**
028 * The constructor for a MotorSafetyHelper object.
029 * The helper object is constructed for every object that wants to implement the Motor
030 * Safety protocol. The helper object has the code to actually do the timing and call the
031 * motors Stop() method when the timeout expires. The motor object is expected to call the
032 * Feed() method whenever the motors value is updated.
033 *
034 * @param safeObject a pointer to the motor object implementing MotorSafety. This is used
035 * to call the Stop() method on the motor.
036 */
037 public MotorSafetyHelper(MotorSafety safeObject) {
038 m_safeObject = safeObject;
039 m_enabled = false;
040 m_expiration = MotorSafety.DEFAULT_SAFETY_EXPIRATION;
041 m_stopTime = Timer.getFPGATimestamp();
042 m_nextHelper = m_headHelper;
043 m_headHelper = this;
044 }
045
046 /**
047 * Feed the motor safety object.
048 * Resets the timer on this object that is used to do the timeouts.
049 */
050 public void feed() {
051 m_stopTime = Timer.getFPGATimestamp() + m_expiration;
052 }
053
054 /**
055 * Set the expiration time for the corresponding motor safety object.
056 * @param expirationTime The timeout value in seconds.
057 */
058 public void setExpiration(double expirationTime) {
059 m_expiration = expirationTime;
060 }
061
062 /**
063 * Retrieve the timeout value for the corresponding motor safety object.
064 * @return the timeout value in seconds.
065 */
066 public double getExpiration() {
067 return m_expiration;
068 }
069
070 /**
071 * Determine of the motor is still operating or has timed out.
072 * @return a true value if the motor is still operating normally and hasn't timed out.
073 */
074 public boolean isAlive() {
075 return !m_enabled || m_stopTime > Timer.getFPGATimestamp();
076 }
077
078 /**
079 * Check if this motor has exceeded its timeout.
080 * This method is called periodically to determine if this motor has exceeded its timeout
081 * value. If it has, the stop method is called, and the motor is shut down until its value is
082 * updated again.
083 */
084 public void check() {
085 DriverStation ds = DriverStation.getInstance();
086 if (!m_enabled || ds.isDisabled() || ds.isTest())
087 return;
088 if (m_stopTime < Timer.getFPGATimestamp()) {
089 System.err.println(m_safeObject.getDescription() + "... Output not updated often enough.");
090
091 m_safeObject.stopMotor();
092 }
093 }
094
095 /**
096 * Enable/disable motor safety for this device
097 * Turn on and off the motor safety option for this PWM object.
098 * @param enabled True if motor safety is enforced for this object
099 */
100 public void setSafetyEnabled(boolean enabled) {
101 m_enabled = enabled;
102 }
103
104 /**
105 * Return the state of the motor safety enabled flag
106 * Return if the motor safety is currently enabled for this devicce.
107 * @return True if motor safety is enforced for this device
108 */
109 public boolean isSafetyEnabled() {
110 return m_enabled;
111 }
112
113 /**
114 * Check the motors to see if any have timed out.
115 * This static method is called periodically to poll all the motors and stop any that have
116 * timed out.
117 */
118 //TODO: these should be synchronized with the setting methods in case it's called from a different thread
119 public static void checkMotors() {
120 for (MotorSafetyHelper msh = m_headHelper; msh != null; msh = msh.m_nextHelper) {
121 msh.check();
122 }
123 }
124 }