diff --git a/wpilibc/wpilibC++Devices/include/Relay.h b/wpilibc/wpilibC++Devices/include/Relay.h index de21f0764a..bd1b91c0c4 100644 --- a/wpilibc/wpilibC++Devices/include/Relay.h +++ b/wpilibc/wpilibC++Devices/include/Relay.h @@ -6,6 +6,7 @@ /*----------------------------------------------------------------------------*/ #pragma once +#include "MotorSafety.h" #include "SensorBase.h" #include "tables/ITableListener.h" #include "LiveWindow/LiveWindowSendable.h" @@ -13,6 +14,8 @@ #include +class MotorSafetyHelper; + /** * Class for Spike style relay outputs. * Relays are intended to be connected to spikes or similar relays. The relay @@ -27,7 +30,8 @@ * used independently * for something that does not care about voltage polatiry (like a solenoid). */ -class Relay : public SensorBase, +class Relay : public MotorSafety, + public SensorBase, public ITableListener, public LiveWindowSendable { public: @@ -39,6 +43,15 @@ class Relay : public SensorBase, void Set(Value value); Value Get() const; + uint32_t GetChannel() const; + + void SetExpiration(float timeout) override; + float GetExpiration() const override; + bool IsAlive() const override; + void StopMotor() override; + bool IsSafetyEnabled() const override; + void SetSafetyEnabled(bool enabled) override; + void GetDescription(std::ostringstream& desc) const override; void ValueChanged(ITable* source, llvm::StringRef key, std::shared_ptr value, bool isNew) override; @@ -54,4 +67,6 @@ class Relay : public SensorBase, private: uint32_t m_channel; Direction m_direction; + + std::unique_ptr m_safetyHelper; }; diff --git a/wpilibc/wpilibC++Devices/src/Relay.cpp b/wpilibc/wpilibC++Devices/src/Relay.cpp index f5791e345a..bc3b824b9c 100644 --- a/wpilibc/wpilibC++Devices/src/Relay.cpp +++ b/wpilibc/wpilibC++Devices/src/Relay.cpp @@ -8,6 +8,7 @@ #include "Relay.h" +#include "MotorSafetyHelper.h" //#include "NetworkCommunication/UsageReporting.h" #include "Resource.h" #include "WPIErrors.h" @@ -64,6 +65,9 @@ Relay::Relay(uint32_t channel, Relay::Direction direction) setRelayReverse(m_relay_ports[m_channel], false, &status); wpi_setErrorWithContext(status, getHALErrorMessage(status)); + m_safetyHelper = std::make_unique(this); + m_safetyHelper->SetSafetyEnabled(false); + LiveWindow::GetInstance()->AddActuator("Relay", 1, m_channel, this); } @@ -192,17 +196,66 @@ Relay::Value Relay::Get() const { wpi_setErrorWithContext(status, getHALErrorMessage(status)); } +uint32_t Relay::GetChannel() const { + return m_channel; +} + +/** + * Set the expiration time for the Relay object + * @param timeout The timeout (in seconds) for this relay object + */ +void Relay::SetExpiration(float timeout) { + m_safetyHelper->SetExpiration(timeout); +} + +/** + * Return the expiration time for the relay object. + * @return The expiration time value. + */ +float Relay::GetExpiration() const { return m_safetyHelper->GetExpiration(); } + +/** + * Check if the relay object is currently alive or stopped due to a timeout. + * @returns a bool value that is true if the motor has NOT timed out and should + * still be running. + */ +bool Relay::IsAlive() const { return m_safetyHelper->IsAlive(); } + +/** + * Stop the motor associated with this PWM object. + * This is called by the MotorSafetyHelper object when it has a timeout for this + * relay and needs to stop it from running. + */ +void Relay::StopMotor() { Set(kOff); } + +/** + * Enable/disable motor safety for this device + * Turn on and off the motor safety option for this relay object. + * @param enabled True if motor safety is enforced for this object + */ +void Relay::SetSafetyEnabled(bool enabled) { + m_safetyHelper->SetSafetyEnabled(enabled); +} + +/** + * Check if motor safety is enabled for this object + * @returns True if motor safety is enforced for this object + */ +bool Relay::IsSafetyEnabled() const { + return m_safetyHelper->IsSafetyEnabled(); +} + +void Relay::GetDescription(std::ostringstream& desc) const { + desc << "Relay " << GetChannel(); +} + void Relay::ValueChanged(ITable* source, llvm::StringRef key, std::shared_ptr value, bool isNew) { if (!value->IsString()) return; - if (value->GetString() == "Off") - Set(kOff); - else if (value->GetString() == "On") - Set(kOn); - else if (value->GetString() == "Forward") - Set(kForward); - else if (value->GetString() == "Reverse") - Set(kReverse); + if (value->GetString() == "Off") Set(kOff); + else if (value->GetString() == "Forward") Set(kForward); + else if (value->GetString() == "Reverse") Set(kReverse); + else if (value->GetString() == "On") Set(kOn); } void Relay::UpdateTable() { diff --git a/wpilibc/wpilibC++Sim/include/Relay.h b/wpilibc/wpilibC++Sim/include/Relay.h index 0f5d33c3ee..a96b9b6568 100644 --- a/wpilibc/wpilibC++Sim/include/Relay.h +++ b/wpilibc/wpilibC++Sim/include/Relay.h @@ -5,6 +5,7 @@ /*----------------------------------------------------------------------------*/ #pragma once +#include "MotorSafety.h" #include "SensorBase.h" #include "simulation/SimContinuousOutput.h" #include "tables/ITableListener.h" @@ -13,6 +14,7 @@ #include +class MotorSafetyHelper; class DigitalModule; /** @@ -24,8 +26,10 @@ class DigitalModule; * variable speed. It also allows the two channels (forward and reverse) to be used independently * for something that does not care about voltage polatiry (like a solenoid). */ -class Relay : public SensorBase, public ITableListener, public LiveWindowSendable -{ +class Relay : public MotorSafety, + public SensorBase, + public ITableListener, + public LiveWindowSendable { public: enum Value { @@ -46,6 +50,15 @@ public: void Set(Value value); Value Get() const; + uint32_t GetChannel() const; + + void SetExpiration(float timeout) override; + float GetExpiration() const override; + bool IsAlive() const override; + void StopMotor() override; + bool IsSafetyEnabled() const override; + void SetSafetyEnabled(bool enabled) override; + void GetDescription(std::ostringstream& desc) const override; void ValueChanged(ITable* source, llvm::StringRef key, std::shared_ptr value, bool isNew) override; @@ -61,6 +74,7 @@ public: private: uint32_t m_channel; Direction m_direction; + std::unique_ptr m_safetyHelper; SimContinuousOutput* impl; bool go_pos, go_neg; }; diff --git a/wpilibc/wpilibC++Sim/src/Relay.cpp b/wpilibc/wpilibC++Sim/src/Relay.cpp index 971fe28698..f35d782ebf 100644 --- a/wpilibc/wpilibC++Sim/src/Relay.cpp +++ b/wpilibc/wpilibC++Sim/src/Relay.cpp @@ -6,6 +6,7 @@ #include "Relay.h" +#include "MotorSafetyHelper.h" //#include "NetworkCommunication/UsageReporting.h" #include "WPIErrors.h" #include "LiveWindow/LiveWindow.h" @@ -30,6 +31,9 @@ Relay::Relay(uint32_t channel, Relay::Direction direction) return; } + m_safetyHelper = std::make_unique(this); + m_safetyHelper->SetSafetyEnabled(false); + sprintf(buf, "relay/%d", m_channel); impl = new SimContinuousOutput(buf); // TODO: Allow two different relays (targetting the different halves of a relay) to be combined to control one motor. LiveWindow::GetInstance()->AddActuator("Relay", 1, m_channel, this); @@ -141,12 +145,65 @@ Relay::Value Relay::Get() const { } } +uint32_t Relay::GetChannel() const { + return m_channel; +} + +/** + * Set the expiration time for the Relay object + * @param timeout The timeout (in seconds) for this relay object + */ +void Relay::SetExpiration(float timeout) { + m_safetyHelper->SetExpiration(timeout); +} + +/** + * Return the expiration time for the relay object. + * @return The expiration time value. + */ +float Relay::GetExpiration() const { return m_safetyHelper->GetExpiration(); } + +/** + * Check if the relay object is currently alive or stopped due to a timeout. + * @returns a bool value that is true if the motor has NOT timed out and should + * still be running. + */ +bool Relay::IsAlive() const { return m_safetyHelper->IsAlive(); } + +/** + * Stop the motor associated with this PWM object. + * This is called by the MotorSafetyHelper object when it has a timeout for this + * relay and needs to stop it from running. + */ +void Relay::StopMotor() { Set(kOff); } + +/** + * Enable/disable motor safety for this device + * Turn on and off the motor safety option for this relay object. + * @param enabled True if motor safety is enforced for this object + */ +void Relay::SetSafetyEnabled(bool enabled) { + m_safetyHelper->SetSafetyEnabled(enabled); +} + +/** + * Check if motor safety is enabled for this object + * @returns True if motor safety is enforced for this object + */ +bool Relay::IsSafetyEnabled() const { + return m_safetyHelper->IsSafetyEnabled(); +} + +void Relay::GetDescription(std::ostringstream& desc) const { + desc << "Relay " << GetChannel(); +} + void Relay::ValueChanged(ITable* source, llvm::StringRef key, std::shared_ptr value, bool isNew) { if (!value->IsString()) return; - if (value->GetString() == "Off") Set(kOff); - else if (value->GetString() == "Forward") Set(kForward); - else if (value->GetString() == "Reverse") Set(kReverse); + if (value->GetString() == "Off") Set(kOff); + else if (value->GetString() == "Forward") Set(kForward); + else if (value->GetString() == "Reverse") Set(kReverse); } void Relay::UpdateTable() { diff --git a/wpilibj/wpilibJavaDevices/src/main/java/edu/wpi/first/wpilibj/Relay.java b/wpilibj/wpilibJavaDevices/src/main/java/edu/wpi/first/wpilibj/Relay.java index f48adf62a2..1f6843e981 100644 --- a/wpilibj/wpilibJavaDevices/src/main/java/edu/wpi/first/wpilibj/Relay.java +++ b/wpilibj/wpilibJavaDevices/src/main/java/edu/wpi/first/wpilibj/Relay.java @@ -32,7 +32,8 @@ import edu.wpi.first.wpilibj.util.CheckedAllocationException; * allows the two channels (forward and reverse) to be used independently for * something that does not care about voltage polarity (like a solenoid). */ -public class Relay extends SensorBase implements LiveWindowSendable { +public class Relay extends SensorBase implements MotorSafety, LiveWindowSendable { + private MotorSafetyHelper m_safetyHelper; /** * This class represents errors in trying to set relay values contradictory to @@ -142,6 +143,9 @@ public class Relay extends SensorBase implements LiveWindowSendable { m_port = DIOJNI.initializeDigitalPort(DIOJNI.getPort((byte) m_channel), status.asIntBuffer()); HALUtil.checkStatus(status.asIntBuffer()); + m_safetyHelper = new MotorSafetyHelper(this); + m_safetyHelper.setSafetyEnabled(false); + LiveWindow.addActuator("Relay", m_channel, this); } @@ -290,6 +294,50 @@ public class Relay extends SensorBase implements LiveWindowSendable { } } + /** + * Get the channel number. + * + * @return The channel number. + */ + public int getChannel() { + return m_channel; + } + + @Override + public void setExpiration(double timeout) { + m_safetyHelper.setExpiration(timeout); + } + + @Override + public double getExpiration() { + return m_safetyHelper.getExpiration(); + } + + @Override + public boolean isAlive() { + return m_safetyHelper.isAlive(); + } + + @Override + public void stopMotor() { + set(Value.kOff); + } + + @Override + public boolean isSafetyEnabled() { + return m_safetyHelper.isSafetyEnabled(); + } + + @Override + public void setSafetyEnabled(boolean enabled) { + m_safetyHelper.setSafetyEnabled(enabled); + } + + @Override + public String getDescription() { + return "Relay ID " + getChannel(); + } + /** * Set the Relay Direction * diff --git a/wpilibj/wpilibJavaSim/src/main/java/edu/wpi/first/wpilibj/Relay.java b/wpilibj/wpilibJavaSim/src/main/java/edu/wpi/first/wpilibj/Relay.java index 72c0165ec1..b9925798b6 100644 --- a/wpilibj/wpilibJavaSim/src/main/java/edu/wpi/first/wpilibj/Relay.java +++ b/wpilibj/wpilibJavaSim/src/main/java/edu/wpi/first/wpilibj/Relay.java @@ -23,7 +23,8 @@ import edu.wpi.first.wpilibj.tables.ITableListener; * allows the two channels (forward and reverse) to be used independently for * something that does not care about voltage polarity (like a solenoid). */ -public class Relay extends SensorBase implements LiveWindowSendable { +public class Relay extends SensorBase implements MotorSafety, LiveWindowSendable { + private MotorSafetyHelper m_safetyHelper; /** * This class represents errors in trying to set relay values contradictory * to the direction to which the relay is set. @@ -119,6 +120,10 @@ public class Relay extends SensorBase implements LiveWindowSendable { private void initRelay() { SensorBase.checkRelayChannel(m_channel); impl = new SimSpeedController("simulator/relay/" + m_channel); + + m_safetyHelper = new MotorSafetyHelper(this); + m_safetyHelper.setSafetyEnabled(false); + LiveWindow.addActuator("Relay", m_channel, this); } @@ -246,6 +251,50 @@ public class Relay extends SensorBase implements LiveWindowSendable { } } + /** + * Get the channel number. + * + * @return The channel number. + */ + public int getChannel() { + return m_channel; + } + + @Override + public void setExpiration(double timeout) { + m_safetyHelper.setExpiration(timeout); + } + + @Override + public double getExpiration() { + return m_safetyHelper.getExpiration(); + } + + @Override + public boolean isAlive() { + return m_safetyHelper.isAlive(); + } + + @Override + public void stopMotor() { + set(Value.kOff); + } + + @Override + public boolean isSafetyEnabled() { + return m_safetyHelper.isSafetyEnabled(); + } + + @Override + public void setSafetyEnabled(boolean enabled) { + m_safetyHelper.setSafetyEnabled(enabled); + } + + @Override + public String getDescription() { + return "Relay ID " + getChannel(); + } + /** * Set the Relay Direction *