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