mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-24 01:31:46 +00:00
[hal, wpilib] Add REV PneumaticsHub (#3600)
This commit is contained in:
@@ -12,9 +12,11 @@ public interface PneumaticsBase extends AutoCloseable {
|
||||
* @param type module type
|
||||
* @return module
|
||||
*/
|
||||
static PneumaticsControlModule getForType(int module, PneumaticsModuleType type) {
|
||||
static PneumaticsBase getForType(int module, PneumaticsModuleType type) {
|
||||
if (type == PneumaticsModuleType.CTREPCM) {
|
||||
return new PneumaticsControlModule();
|
||||
return new PneumaticsControlModule(module);
|
||||
} else if (type == PneumaticsModuleType.REVPH) {
|
||||
return new PneumaticsHub(module);
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown module type");
|
||||
}
|
||||
@@ -28,6 +30,8 @@ public interface PneumaticsBase extends AutoCloseable {
|
||||
static int getDefaultForType(PneumaticsModuleType type) {
|
||||
if (type == PneumaticsModuleType.CTREPCM) {
|
||||
return SensorUtil.getDefaultCTREPCMModule();
|
||||
} else if (type == PneumaticsModuleType.REVPH) {
|
||||
return SensorUtil.getDefaultREVPHModule();
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown module type");
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ public class PneumaticsControlModule implements PneumaticsBase {
|
||||
|
||||
@Override
|
||||
public int getModuleNumber() {
|
||||
return m_dataStore.m_handle;
|
||||
return m_dataStore.m_module;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
203
wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsHub.java
Normal file
203
wpilibj/src/main/java/edu/wpi/first/wpilibj/PneumaticsHub.java
Normal file
@@ -0,0 +1,203 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.hal.REVPHJNI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** Module class for controlling a REV Robotics Pneumatics Hub. */
|
||||
public class PneumaticsHub implements PneumaticsBase {
|
||||
private static class DataStore implements AutoCloseable {
|
||||
public final int m_module;
|
||||
public final int m_handle;
|
||||
private int m_refCount;
|
||||
private int m_reservedMask;
|
||||
private boolean m_compressorReserved;
|
||||
private final Object m_reserveLock = new Object();
|
||||
|
||||
DataStore(int module) {
|
||||
m_handle = REVPHJNI.initialize(module);
|
||||
m_module = module;
|
||||
m_handleMap.put(module, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
REVPHJNI.free(m_handle);
|
||||
m_handleMap.remove(m_module);
|
||||
}
|
||||
|
||||
public void addRef() {
|
||||
m_refCount++;
|
||||
}
|
||||
|
||||
public void removeRef() {
|
||||
m_refCount--;
|
||||
if (m_refCount == 0) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<Integer, DataStore> m_handleMap = new HashMap<>();
|
||||
private static final Object m_handleLock = new Object();
|
||||
|
||||
private static DataStore getForModule(int module) {
|
||||
synchronized (m_handleLock) {
|
||||
Integer moduleBoxed = module;
|
||||
DataStore pcm = m_handleMap.get(moduleBoxed);
|
||||
if (pcm == null) {
|
||||
pcm = new DataStore(module);
|
||||
}
|
||||
pcm.addRef();
|
||||
return pcm;
|
||||
}
|
||||
}
|
||||
|
||||
private static void freeModule(DataStore store) {
|
||||
synchronized (m_handleLock) {
|
||||
store.removeRef();
|
||||
}
|
||||
}
|
||||
|
||||
private final DataStore m_dataStore;
|
||||
private final int m_handle;
|
||||
|
||||
/** Constructs a PneumaticsHub with the default id (1). */
|
||||
public PneumaticsHub() {
|
||||
this(SensorUtil.getDefaultREVPHModule());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PneumaticsHub.
|
||||
*
|
||||
* @param module module number to construct
|
||||
*/
|
||||
public PneumaticsHub(int module) {
|
||||
m_dataStore = getForModule(module);
|
||||
m_handle = m_dataStore.m_handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
freeModule(m_dataStore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCompressor() {
|
||||
return REVPHJNI.getCompressor(m_handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClosedLoopControl(boolean enabled) {
|
||||
REVPHJNI.setClosedLoopControl(m_handle, enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getClosedLoopControl() {
|
||||
return REVPHJNI.getClosedLoopControl(m_handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getPressureSwitch() {
|
||||
return REVPHJNI.getPressureSwitch(m_handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCompressorCurrent() {
|
||||
return REVPHJNI.getCompressorCurrent(m_handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSolenoids(int mask, int values) {
|
||||
REVPHJNI.setSolenoids(m_handle, mask, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSolenoids() {
|
||||
return REVPHJNI.getSolenoids(m_handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getModuleNumber() {
|
||||
return m_dataStore.m_module;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireOneShot(int index) {
|
||||
// TODO Combine APIs
|
||||
// REVPHJNI.fireOneShot(m_handle, index, durMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOneShotDuration(int index, int durMs) {
|
||||
// TODO Combine APIs
|
||||
// REVPHJNI.setOneShotDuration(m_handle, index, durMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkSolenoidChannel(int channel) {
|
||||
return REVPHJNI.checkSolenoidChannel(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int checkAndReserveSolenoids(int mask) {
|
||||
synchronized (m_dataStore.m_reserveLock) {
|
||||
if ((m_dataStore.m_reservedMask & mask) != 0) {
|
||||
return m_dataStore.m_reservedMask & mask;
|
||||
}
|
||||
m_dataStore.m_reservedMask |= mask;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unreserveSolenoids(int mask) {
|
||||
synchronized (m_dataStore.m_reserveLock) {
|
||||
m_dataStore.m_reservedMask &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Solenoid makeSolenoid(int channel) {
|
||||
return new Solenoid(m_dataStore.m_module, PneumaticsModuleType.REVPH, channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoubleSolenoid makeDoubleSolenoid(int forwardChannel, int reverseChannel) {
|
||||
return new DoubleSolenoid(
|
||||
m_dataStore.m_module, PneumaticsModuleType.REVPH, forwardChannel, reverseChannel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Compressor makeCompressor() {
|
||||
return new Compressor(m_dataStore.m_module, PneumaticsModuleType.REVPH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reserveCompressor() {
|
||||
synchronized (m_dataStore.m_reserveLock) {
|
||||
if (m_dataStore.m_compressorReserved) {
|
||||
return false;
|
||||
}
|
||||
m_dataStore.m_compressorReserved = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unreserveCompressor() {
|
||||
synchronized (m_dataStore.m_reserveLock) {
|
||||
m_dataStore.m_compressorReserved = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSolenoidDisabledList() {
|
||||
// TODO Get this working
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,10 @@ public final class SensorUtil {
|
||||
/** Number of PCM Modules. */
|
||||
public static final int kCTREPCMModules = PortsJNI.getNumCTREPCMModules();
|
||||
|
||||
public static final int kREVPHChannels = PortsJNI.getNumREVPHChannels();
|
||||
|
||||
public static final int kREVPHModules = PortsJNI.getNumREVPHModules();
|
||||
|
||||
/**
|
||||
* Check that the digital channel number is valid. Verify that the channel number is one of the
|
||||
* legal channel numbers. Channel numbers are 0-based.
|
||||
@@ -142,5 +146,15 @@ public final class SensorUtil {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of the default solenoid module.
|
||||
*
|
||||
* @return The number of the default solenoid module.
|
||||
*/
|
||||
@SuppressWarnings("AbbreviationAsWordInName")
|
||||
public static int getDefaultREVPHModule() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
private SensorUtil() {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.wpilibj.simulation;
|
||||
|
||||
import edu.wpi.first.hal.simulation.NotifyCallback;
|
||||
import edu.wpi.first.hal.simulation.REVPHDataJNI;
|
||||
import edu.wpi.first.wpilibj.PneumaticsBase;
|
||||
import edu.wpi.first.wpilibj.SensorUtil;
|
||||
|
||||
/** Class to control a simulated PneumaticsHub (PH). */
|
||||
@SuppressWarnings("AbbreviationAsWordInName")
|
||||
public class REVPHSim {
|
||||
private final int m_index;
|
||||
|
||||
/** Constructs for the default PH. */
|
||||
public REVPHSim() {
|
||||
m_index = SensorUtil.getDefaultREVPHModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs from a PH module number (CAN ID).
|
||||
*
|
||||
* @param module module number
|
||||
*/
|
||||
public REVPHSim(int module) {
|
||||
m_index = module;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs from a Compressor object.
|
||||
*
|
||||
* @param module PCM module to simulate
|
||||
*/
|
||||
public REVPHSim(PneumaticsBase module) {
|
||||
m_index = module.getModuleNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the solenoid output on a channel changes.
|
||||
*
|
||||
* @param channel the channel to monitor
|
||||
* @param callback the callback
|
||||
* @param initialNotify should the callback be run with the initial value
|
||||
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
|
||||
* this object so GC doesn't cancel the callback.
|
||||
*/
|
||||
public CallbackStore registerSolenoidOutputCallback(
|
||||
int channel, NotifyCallback callback, boolean initialNotify) {
|
||||
int uid =
|
||||
REVPHDataJNI.registerSolenoidOutputCallback(m_index, channel, callback, initialNotify);
|
||||
return new CallbackStore(m_index, channel, uid, REVPHDataJNI::cancelSolenoidOutputCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the solenoid output on a specific channel.
|
||||
*
|
||||
* @param channel the channel to check
|
||||
* @return the solenoid output
|
||||
*/
|
||||
public boolean getSolenoidOutput(int channel) {
|
||||
return REVPHDataJNI.getSolenoidOutput(m_index, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the solenoid output on a specific channel.
|
||||
*
|
||||
* @param channel the channel to check
|
||||
* @param solenoidOutput the new solenoid output
|
||||
*/
|
||||
public void setSolenoidOutput(int channel, boolean solenoidOutput) {
|
||||
REVPHDataJNI.setSolenoidOutput(m_index, channel, solenoidOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the compressor is initialized.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether to run the callback with the initial state
|
||||
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
|
||||
* this object so GC doesn't cancel the callback.
|
||||
*/
|
||||
public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = REVPHDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, REVPHDataJNI::cancelInitializedCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the compressor has been initialized.
|
||||
*
|
||||
* @return true if initialized
|
||||
*/
|
||||
public boolean getInitialized() {
|
||||
return REVPHDataJNI.getInitialized(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define whether the compressor has been initialized.
|
||||
*
|
||||
* @param initialized whether the compressor is initialized
|
||||
*/
|
||||
public void setInitialized(boolean initialized) {
|
||||
REVPHDataJNI.setInitialized(m_index, initialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the compressor activates.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether to run the callback with the initial state
|
||||
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
|
||||
* this object so GC doesn't cancel the callback.
|
||||
*/
|
||||
public CallbackStore registerCompressorOnCallback(
|
||||
NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = REVPHDataJNI.registerCompressorOnCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, REVPHDataJNI::cancelCompressorOnCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the compressor is on.
|
||||
*
|
||||
* @return true if the compressor is active
|
||||
*/
|
||||
public boolean getCompressorOn() {
|
||||
return REVPHDataJNI.getCompressorOn(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the compressor is active.
|
||||
*
|
||||
* @param compressorOn the new value
|
||||
*/
|
||||
public void setCompressorOn(boolean compressorOn) {
|
||||
REVPHDataJNI.setCompressorOn(m_index, compressorOn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run whenever the closed loop state changes.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether the callback should be called with the initial value
|
||||
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
|
||||
* this object so GC doesn't cancel the callback.
|
||||
*/
|
||||
public CallbackStore registerClosedLoopEnabledCallback(
|
||||
NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = REVPHDataJNI.registerClosedLoopEnabledCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, REVPHDataJNI::cancelClosedLoopEnabledCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the closed loop compressor control is active.
|
||||
*
|
||||
* @return true if active
|
||||
*/
|
||||
public boolean getClosedLoopEnabled() {
|
||||
return REVPHDataJNI.getClosedLoopEnabled(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on/off the closed loop control of the compressor.
|
||||
*
|
||||
* @param closedLoopEnabled whether the control loop is active
|
||||
*/
|
||||
public void setClosedLoopEnabled(boolean closedLoopEnabled) {
|
||||
REVPHDataJNI.setClosedLoopEnabled(m_index, closedLoopEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run whenever the pressure switch value changes.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether the callback should be called with the initial value
|
||||
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
|
||||
* this object so GC doesn't cancel the callback.
|
||||
*/
|
||||
public CallbackStore registerPressureSwitchCallback(
|
||||
NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = REVPHDataJNI.registerPressureSwitchCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, REVPHDataJNI::cancelPressureSwitchCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the value of the pressure switch.
|
||||
*
|
||||
* @return the pressure switch value
|
||||
*/
|
||||
public boolean getPressureSwitch() {
|
||||
return REVPHDataJNI.getPressureSwitch(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the pressure switch.
|
||||
*
|
||||
* @param pressureSwitch the new value
|
||||
*/
|
||||
public void setPressureSwitch(boolean pressureSwitch) {
|
||||
REVPHDataJNI.setPressureSwitch(m_index, pressureSwitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run whenever the compressor current changes.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether to call the callback with the initial state
|
||||
* @return the {@link CallbackStore} object associated with this callback. Save a reference to
|
||||
* this object so GC doesn't cancel the callback.
|
||||
*/
|
||||
public CallbackStore registerCompressorCurrentCallback(
|
||||
NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = REVPHDataJNI.registerCompressorCurrentCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, REVPHDataJNI::cancelCompressorCurrentCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the compressor current.
|
||||
*
|
||||
* @return the current of the compressor connected to this module
|
||||
*/
|
||||
public double getCompressorCurrent() {
|
||||
return REVPHDataJNI.getCompressorCurrent(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the compressor current.
|
||||
*
|
||||
* @param compressorCurrent the new compressor current
|
||||
*/
|
||||
public void setCompressorCurrent(double compressorCurrent) {
|
||||
REVPHDataJNI.setCompressorCurrent(m_index, compressorCurrent);
|
||||
}
|
||||
|
||||
/** Reset all simulation data for this object. */
|
||||
public void resetData() {
|
||||
REVPHDataJNI.resetData(m_index);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user