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