blob: 47db1771426d60d7d7f21dcd9d2a4c4c7edfaf6f [file] [log] [blame]
Brian Silverman26e4e522015-12-17 01:56:40 -05001/*----------------------------------------------------------------------------*/
Brian Silverman1a675112016-02-20 20:42:49 -05002/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
Brian Silverman26e4e522015-12-17 01:56:40 -05003/* Open Source Software - may be modified and shared by FRC teams. The code */
Brian Silverman1a675112016-02-20 20:42:49 -05004/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
Brian Silverman26e4e522015-12-17 01:56:40 -05006/*----------------------------------------------------------------------------*/
7
8#include "MotorSafetyHelper.h"
9
10#include "DriverStation.h"
11#include "MotorSafety.h"
12#include "Timer.h"
13#include "WPIErrors.h"
14
15#include <stdio.h>
16#include <sstream>
17
18std::set<MotorSafetyHelper*> MotorSafetyHelper::m_helperList;
19priority_recursive_mutex MotorSafetyHelper::m_listMutex;
20
21/**
22 * The constructor for a MotorSafetyHelper object.
23 * The helper object is constructed for every object that wants to implement the
24 * Motor
25 * Safety protocol. The helper object has the code to actually do the timing and
26 * call the
27 * motors Stop() method when the timeout expires. The motor object is expected
28 * to call the
29 * Feed() method whenever the motors value is updated.
30 * @param safeObject a pointer to the motor object implementing MotorSafety.
31 * This is used
32 * to call the Stop() method on the motor.
33 */
34MotorSafetyHelper::MotorSafetyHelper(MotorSafety *safeObject)
35 : m_safeObject(safeObject) {
36 m_enabled = false;
37 m_expiration = DEFAULT_SAFETY_EXPIRATION;
38 m_stopTime = Timer::GetFPGATimestamp();
39
40 std::lock_guard<priority_recursive_mutex> sync(m_listMutex);
41 m_helperList.insert(this);
42}
43
44MotorSafetyHelper::~MotorSafetyHelper() {
45 std::lock_guard<priority_recursive_mutex> sync(m_listMutex);
46 m_helperList.erase(this);
47}
48
49/**
50 * Feed the motor safety object.
51 * Resets the timer on this object that is used to do the timeouts.
52 */
53void MotorSafetyHelper::Feed() {
54 std::lock_guard<priority_recursive_mutex> sync(m_syncMutex);
55 m_stopTime = Timer::GetFPGATimestamp() + m_expiration;
56}
57
58/**
59 * Set the expiration time for the corresponding motor safety object.
60 * @param expirationTime The timeout value in seconds.
61 */
62void MotorSafetyHelper::SetExpiration(float expirationTime) {
63 std::lock_guard<priority_recursive_mutex> sync(m_syncMutex);
64 m_expiration = expirationTime;
65}
66
67/**
68 * Retrieve the timeout value for the corresponding motor safety object.
69 * @return the timeout value in seconds.
70 */
71float MotorSafetyHelper::GetExpiration() const {
72 std::lock_guard<priority_recursive_mutex> sync(m_syncMutex);
73 return m_expiration;
74}
75
76/**
77 * Determine if the motor is still operating or has timed out.
78 * @return a true value if the motor is still operating normally and hasn't
79 * timed out.
80 */
81bool MotorSafetyHelper::IsAlive() const {
82 std::lock_guard<priority_recursive_mutex> sync(m_syncMutex);
83 return !m_enabled || m_stopTime > Timer::GetFPGATimestamp();
84}
85
86/**
87 * Check if this motor has exceeded its timeout.
88 * This method is called periodically to determine if this motor has exceeded
89 * its timeout
90 * value. If it has, the stop method is called, and the motor is shut down until
91 * its value is
92 * updated again.
93 */
94void MotorSafetyHelper::Check()
95{
96 DriverStation &ds = DriverStation::GetInstance();
97 if (!m_enabled || ds.IsDisabled() || ds.IsTest()) return;
98
99 std::lock_guard<priority_recursive_mutex> sync(m_syncMutex);
100 if (m_stopTime < Timer::GetFPGATimestamp()) {
101 std::ostringstream desc;
102 m_safeObject->GetDescription(desc);
103 desc << "... Output not updated often enough.";
104 wpi_setWPIErrorWithContext(Timeout, desc.str().c_str());
105 m_safeObject->StopMotor();
106 }
107}
108
109/**
110 * Enable/disable motor safety for this device
111 * Turn on and off the motor safety option for this PWM object.
112 * @param enabled True if motor safety is enforced for this object
113 */
114void MotorSafetyHelper::SetSafetyEnabled(bool enabled) {
115 std::lock_guard<priority_recursive_mutex> sync(m_syncMutex);
116 m_enabled = enabled;
117}
118
119/**
120 * Return the state of the motor safety enabled flag
121 * Return if the motor safety is currently enabled for this devicce.
122 * @return True if motor safety is enforced for this device
123 */
124bool MotorSafetyHelper::IsSafetyEnabled() const {
125 std::lock_guard<priority_recursive_mutex> sync(m_syncMutex);
126 return m_enabled;
127}
128
129/**
130 * Check the motors to see if any have timed out.
131 * This static method is called periodically to poll all the motors and stop
132 * any that have
133 * timed out.
134 */
135void MotorSafetyHelper::CheckMotors() {
136 std::lock_guard<priority_recursive_mutex> sync(m_listMutex);
137 for (auto elem : m_helperList) {
138 elem->Check();
139 }
140}