mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[hal, wpilib] PWM Rewrite (#7845)
The HAL will only contain the output period and the raw microseconds. Higher level things such as SimDevice can handle everything else.
This commit is contained in:
@@ -123,13 +123,6 @@ public class DIOJNI extends JNIWrapper {
|
||||
*/
|
||||
public static native boolean isAnyPulsing();
|
||||
|
||||
/**
|
||||
* Gets the loop timing of the PWM system.
|
||||
*
|
||||
* @return the loop time in clock ticks
|
||||
*/
|
||||
public static native short getLoopTiming();
|
||||
|
||||
/**
|
||||
* Allocates a DO PWM Generator.
|
||||
*
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
// 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.hal;
|
||||
|
||||
/** Structure for holding the config data result for PWM. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public class PWMConfigDataResult {
|
||||
PWMConfigDataResult(int max, int deadbandMax, int center, int deadbandMin, int min) {
|
||||
this.max = max;
|
||||
this.deadbandMax = deadbandMax;
|
||||
this.center = center;
|
||||
this.deadbandMin = deadbandMin;
|
||||
this.min = min;
|
||||
}
|
||||
|
||||
/** The maximum PWM value in microseconds. */
|
||||
public int max;
|
||||
|
||||
/** The deadband maximum PWM value in microseconds. */
|
||||
public int deadbandMax;
|
||||
|
||||
/** The center PWM value in microseconds. */
|
||||
public int center;
|
||||
|
||||
/** The deadband minimum PWM value in microseconds. */
|
||||
public int deadbandMin;
|
||||
|
||||
/** The minimum PWM value in microseconds. */
|
||||
public int min;
|
||||
}
|
||||
@@ -34,50 +34,13 @@ public class PWMJNI extends DIOJNI {
|
||||
public static native void freePWMPort(int pwmPortHandle);
|
||||
|
||||
/**
|
||||
* Sets the configuration settings for the PWM channel.
|
||||
* Indicates the pwm is used by a simulated device.
|
||||
*
|
||||
* <p>All values are in microseconds.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle
|
||||
* @param maxPwm the maximum PWM value
|
||||
* @param deadbandMaxPwm the high range of the center deadband
|
||||
* @param centerPwm the center PWM value
|
||||
* @param deadbandMinPwm the low range of the center deadband
|
||||
* @param minPwm the minimum PWM value
|
||||
* @param handle the pwm handle
|
||||
* @param device simulated device handle
|
||||
* @see "HAL_SetPWMSimDevice"
|
||||
*/
|
||||
public static native void setPWMConfigMicroseconds(
|
||||
int pwmPortHandle,
|
||||
int maxPwm,
|
||||
int deadbandMaxPwm,
|
||||
int centerPwm,
|
||||
int deadbandMinPwm,
|
||||
int minPwm);
|
||||
|
||||
/**
|
||||
* Gets the pwm configuration settings for the PWM channel.
|
||||
*
|
||||
* <p>Values are in microseconds.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle
|
||||
* @return the pwm configuration settings
|
||||
*/
|
||||
public static native PWMConfigDataResult getPWMConfigMicroseconds(int pwmPortHandle);
|
||||
|
||||
/**
|
||||
* Sets if the FPGA should output the center value if the input value is within the deadband.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle
|
||||
* @param eliminateDeadband true to eliminate deadband, otherwise false
|
||||
*/
|
||||
public static native void setPWMEliminateDeadband(int pwmPortHandle, boolean eliminateDeadband);
|
||||
|
||||
/**
|
||||
* Gets the current eliminate deadband value.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle
|
||||
* @return true if set, otherwise false
|
||||
*/
|
||||
public static native boolean getPWMEliminateDeadband(int pwmPortHandle);
|
||||
public static native void setPWMSimDevice(int handle, int device);
|
||||
|
||||
/**
|
||||
* Sets a PWM channel to the desired pulse width in microseconds.
|
||||
@@ -87,28 +50,6 @@ public class PWMJNI extends DIOJNI {
|
||||
*/
|
||||
public static native void setPulseTimeMicroseconds(int pwmPortHandle, int microsecondPulseTime);
|
||||
|
||||
/**
|
||||
* Sets a PWM channel to the desired scaled value.
|
||||
*
|
||||
* <p>The values range from -1 to 1 and the period is controlled by the PWM Period and MinHigh
|
||||
* registers.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle
|
||||
* @param speed the scaled PWM value to set
|
||||
*/
|
||||
public static native void setPWMSpeed(int pwmPortHandle, double speed);
|
||||
|
||||
/**
|
||||
* Sets a PWM channel to the desired position value.
|
||||
*
|
||||
* <p>The values range from 0 to 1 and the period is controlled by the PWM Period and MinHigh
|
||||
* registers.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle
|
||||
* @param position the positional PWM value to set
|
||||
*/
|
||||
public static native void setPWMPosition(int pwmPortHandle, double position);
|
||||
|
||||
/**
|
||||
* Gets the current microsecond pulse time from a PWM channel.
|
||||
*
|
||||
@@ -118,56 +59,12 @@ public class PWMJNI extends DIOJNI {
|
||||
public static native int getPulseTimeMicroseconds(int pwmPortHandle);
|
||||
|
||||
/**
|
||||
* Gets a scaled value from a PWM channel.
|
||||
*
|
||||
* <p>The values range from -1 to 1.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle
|
||||
* @return the current speed PWM value
|
||||
*/
|
||||
public static native double getPWMSpeed(int pwmPortHandle);
|
||||
|
||||
/**
|
||||
* Gets a position value from a PWM channel.
|
||||
*
|
||||
* <p>The values range from 0 to 1.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle
|
||||
* @return the current positional PWM value
|
||||
*/
|
||||
public static native double getPWMPosition(int pwmPortHandle);
|
||||
|
||||
/**
|
||||
* Sets a PWM channel to be disabled.
|
||||
*
|
||||
* <p>The channel is disabled until the next time it is set. Note this is different from just
|
||||
* setting a 0 speed, as this will actively stop all signaling on the channel.
|
||||
* Sets the PWM output period.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle.
|
||||
* @param period 0 for 5ms, 1 or 2 for 10ms, 3 for 20ms
|
||||
*/
|
||||
public static native void setPWMDisabled(int pwmPortHandle);
|
||||
|
||||
/**
|
||||
* Forces a PWM signal to go to 0 temporarily.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle.
|
||||
*/
|
||||
public static native void latchPWMZero(int pwmPortHandle);
|
||||
|
||||
/**
|
||||
* Sets the PWM output to be a continuous high signal while enabled.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle.
|
||||
*/
|
||||
public static native void setAlwaysHighMode(int pwmPortHandle);
|
||||
|
||||
/**
|
||||
* Sets how how often the PWM signal is squelched, thus scaling the period.
|
||||
*
|
||||
* @param pwmPortHandle the PWM handle.
|
||||
* @param squelchMask the 2-bit mask of outputs to squelch
|
||||
*/
|
||||
public static native void setPWMPeriodScale(int pwmPortHandle, int squelchMask);
|
||||
public static native void setPWMOutputPeriod(int pwmPortHandle, int period);
|
||||
|
||||
/** Utility class. */
|
||||
private PWMJNI() {}
|
||||
|
||||
@@ -26,41 +26,14 @@ public class PWMDataJNI extends JNIWrapper {
|
||||
|
||||
public static native void setPulseMicrosecond(int index, int microsecondPulseTime);
|
||||
|
||||
public static native int registerSpeedCallback(
|
||||
public static native int registerOutputPeriodCallback(
|
||||
int index, NotifyCallback callback, boolean initialNotify);
|
||||
|
||||
public static native void cancelSpeedCallback(int index, int uid);
|
||||
public static native void cancelOutputPeriodCallback(int index, int uid);
|
||||
|
||||
public static native double getSpeed(int index);
|
||||
public static native int getOutputPeriod(int index);
|
||||
|
||||
public static native void setSpeed(int index, double speed);
|
||||
|
||||
public static native int registerPositionCallback(
|
||||
int index, NotifyCallback callback, boolean initialNotify);
|
||||
|
||||
public static native void cancelPositionCallback(int index, int uid);
|
||||
|
||||
public static native double getPosition(int index);
|
||||
|
||||
public static native void setPosition(int index, double position);
|
||||
|
||||
public static native int registerPeriodScaleCallback(
|
||||
int index, NotifyCallback callback, boolean initialNotify);
|
||||
|
||||
public static native void cancelPeriodScaleCallback(int index, int uid);
|
||||
|
||||
public static native int getPeriodScale(int index);
|
||||
|
||||
public static native void setPeriodScale(int index, int periodScale);
|
||||
|
||||
public static native int registerZeroLatchCallback(
|
||||
int index, NotifyCallback callback, boolean initialNotify);
|
||||
|
||||
public static native void cancelZeroLatchCallback(int index, int uid);
|
||||
|
||||
public static native boolean getZeroLatch(int index);
|
||||
|
||||
public static native void setZeroLatch(int index, boolean zeroLatch);
|
||||
public static native void setOutputPeriod(int index, int period);
|
||||
|
||||
public static native void resetData(int index);
|
||||
|
||||
|
||||
@@ -190,21 +190,6 @@ Java_edu_wpi_first_hal_DIOJNI_isAnyPulsing
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_DIOJNI
|
||||
* Method: getLoopTiming
|
||||
* Signature: ()S
|
||||
*/
|
||||
JNIEXPORT jshort JNICALL
|
||||
Java_edu_wpi_first_hal_DIOJNI_getLoopTiming
|
||||
(JNIEnv* env, jclass)
|
||||
{
|
||||
int32_t status = 0;
|
||||
jshort returnValue = HAL_GetPWMLoopTiming(&status);
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_DIOJNI
|
||||
* Method: allocateDigitalPWM
|
||||
|
||||
@@ -44,7 +44,6 @@ static JException halHandleExCls;
|
||||
static JException uncleanStatusExCls;
|
||||
static JException nullPointerEx;
|
||||
static JClass powerDistributionVersionCls;
|
||||
static JClass pwmConfigDataResultCls;
|
||||
static JClass canStatusCls;
|
||||
static JClass matchInfoDataCls;
|
||||
static JClass canReceiveMessageCls;
|
||||
@@ -56,7 +55,6 @@ static JClass canStreamOverflowExCls;
|
||||
static const JClassInit classes[] = {
|
||||
{"edu/wpi/first/hal/PowerDistributionVersion",
|
||||
&powerDistributionVersionCls},
|
||||
{"edu/wpi/first/hal/PWMConfigDataResult", &pwmConfigDataResultCls},
|
||||
{"edu/wpi/first/hal/can/CANStatus", &canStatusCls},
|
||||
{"edu/wpi/first/hal/MatchInfoData", &matchInfoDataCls},
|
||||
{"edu/wpi/first/hal/can/CANReceiveMessage", &canReceiveMessageCls},
|
||||
@@ -180,17 +178,6 @@ void ThrowBoundaryException(JNIEnv* env, double value, double lower,
|
||||
env->Throw(static_cast<jthrowable>(ex));
|
||||
}
|
||||
|
||||
jobject CreatePWMConfigDataResult(JNIEnv* env, int32_t maxPwm,
|
||||
int32_t deadbandMaxPwm, int32_t centerPwm,
|
||||
int32_t deadbandMinPwm, int32_t minPwm) {
|
||||
static jmethodID constructor =
|
||||
env->GetMethodID(pwmConfigDataResultCls, "<init>", "(IIIII)V");
|
||||
return env->NewObject(
|
||||
pwmConfigDataResultCls, constructor, static_cast<jint>(maxPwm),
|
||||
static_cast<jint>(deadbandMaxPwm), static_cast<jint>(centerPwm),
|
||||
static_cast<jint>(deadbandMinPwm), static_cast<jint>(minPwm));
|
||||
}
|
||||
|
||||
jobject CreateREVPHVersion(JNIEnv* env, uint32_t firmwareMajor,
|
||||
uint32_t firmwareMinor, uint32_t firmwareFix,
|
||||
uint32_t hardwareMinor, uint32_t hardwareMajor,
|
||||
|
||||
@@ -49,10 +49,6 @@ void ThrowIllegalArgumentException(JNIEnv* env, std::string_view msg);
|
||||
void ThrowBoundaryException(JNIEnv* env, double value, double lower,
|
||||
double upper);
|
||||
|
||||
jobject CreatePWMConfigDataResult(JNIEnv* env, int32_t maxPwm,
|
||||
int32_t deadbandMaxPwm, int32_t centerPwm,
|
||||
int32_t deadbandMinPwm, int32_t minPwm);
|
||||
|
||||
jobject CreateREVPHVersion(JNIEnv* env, uint32_t firmwareMajor,
|
||||
uint32_t firmwareMinor, uint32_t firmwareFix,
|
||||
uint32_t hardwareMinor, uint32_t hardwareMajor,
|
||||
|
||||
@@ -63,69 +63,14 @@ Java_edu_wpi_first_hal_PWMJNI_freePWMPort
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: setPWMConfigMicroseconds
|
||||
* Signature: (IIIIII)V
|
||||
* Method: setPWMSimDevice
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_setPWMConfigMicroseconds
|
||||
(JNIEnv* env, jclass, jint id, jint maxPwm, jint deadbandMaxPwm,
|
||||
jint centerPwm, jint deadbandMinPwm, jint minPwm)
|
||||
Java_edu_wpi_first_hal_PWMJNI_setPWMSimDevice
|
||||
(JNIEnv* env, jclass, jint handle, jint device)
|
||||
{
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMConfigMicroseconds((HAL_DigitalHandle)id, maxPwm, deadbandMaxPwm,
|
||||
centerPwm, deadbandMinPwm, minPwm, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: getPWMConfigMicroseconds
|
||||
* Signature: (I)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_getPWMConfigMicroseconds
|
||||
(JNIEnv* env, jclass, jint id)
|
||||
{
|
||||
int32_t status = 0;
|
||||
int32_t maxPwm = 0;
|
||||
int32_t deadbandMaxPwm = 0;
|
||||
int32_t centerPwm = 0;
|
||||
int32_t deadbandMinPwm = 0;
|
||||
int32_t minPwm = 0;
|
||||
HAL_GetPWMConfigMicroseconds((HAL_DigitalHandle)id, &maxPwm, &deadbandMaxPwm,
|
||||
¢erPwm, &deadbandMinPwm, &minPwm, &status);
|
||||
CheckStatus(env, status);
|
||||
return CreatePWMConfigDataResult(env, maxPwm, deadbandMaxPwm, centerPwm,
|
||||
deadbandMinPwm, minPwm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: setPWMEliminateDeadband
|
||||
* Signature: (IZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_setPWMEliminateDeadband
|
||||
(JNIEnv* env, jclass, jint id, jboolean value)
|
||||
{
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMEliminateDeadband((HAL_DigitalHandle)id, value, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: getPWMEliminateDeadband
|
||||
* Signature: (I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_getPWMEliminateDeadband
|
||||
(JNIEnv* env, jclass, jint id)
|
||||
{
|
||||
int32_t status = 0;
|
||||
auto val = HAL_GetPWMEliminateDeadband((HAL_DigitalHandle)id, &status);
|
||||
CheckStatus(env, status);
|
||||
return (jboolean)val;
|
||||
HAL_SetPWMSimDevice((HAL_DigitalHandle)handle, (HAL_SimDeviceHandle)device);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -142,34 +87,6 @@ Java_edu_wpi_first_hal_PWMJNI_setPulseTimeMicroseconds
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: setPWMSpeed
|
||||
* Signature: (ID)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_setPWMSpeed
|
||||
(JNIEnv* env, jclass, jint id, jdouble value)
|
||||
{
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMSpeed((HAL_DigitalHandle)id, value, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: setPWMPosition
|
||||
* Signature: (ID)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_setPWMPosition
|
||||
(JNIEnv* env, jclass, jint id, jdouble value)
|
||||
{
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMPosition((HAL_DigitalHandle)id, value, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: getPulseTimeMicroseconds
|
||||
@@ -188,87 +105,15 @@ Java_edu_wpi_first_hal_PWMJNI_getPulseTimeMicroseconds
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: getPWMSpeed
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_getPWMSpeed
|
||||
(JNIEnv* env, jclass, jint id)
|
||||
{
|
||||
int32_t status = 0;
|
||||
jdouble returnValue = HAL_GetPWMSpeed((HAL_DigitalHandle)id, &status);
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: getPWMPosition
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_getPWMPosition
|
||||
(JNIEnv* env, jclass, jint id)
|
||||
{
|
||||
int32_t status = 0;
|
||||
jdouble returnValue = HAL_GetPWMPosition((HAL_DigitalHandle)id, &status);
|
||||
CheckStatus(env, status);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: setPWMDisabled
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_setPWMDisabled
|
||||
(JNIEnv* env, jclass, jint id)
|
||||
{
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMDisabled((HAL_DigitalHandle)id, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: latchPWMZero
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_latchPWMZero
|
||||
(JNIEnv* env, jclass, jint id)
|
||||
{
|
||||
int32_t status = 0;
|
||||
HAL_LatchPWMZero((HAL_DigitalHandle)id, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: setAlwaysHighMode
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_setAlwaysHighMode
|
||||
(JNIEnv* env, jclass, jint id)
|
||||
{
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMAlwaysHighMode((HAL_DigitalHandle)id, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_PWMJNI
|
||||
* Method: setPWMPeriodScale
|
||||
* Method: setPWMOutputPeriod
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_PWMJNI_setPWMPeriodScale
|
||||
Java_edu_wpi_first_hal_PWMJNI_setPWMOutputPeriod
|
||||
(JNIEnv* env, jclass, jint id, jint value)
|
||||
{
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMPeriodScale((HAL_DigitalHandle)id, value, &status);
|
||||
HAL_SetPWMOutputPeriod((HAL_DigitalHandle)id, value, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,201 +114,52 @@ Java_edu_wpi_first_hal_simulation_PWMDataJNI_setPulseMicrosecond
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: registerSpeedCallback
|
||||
* Method: registerOutputPeriodCallback
|
||||
* Signature: (ILjava/lang/Object;Z)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_registerSpeedCallback
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_registerOutputPeriodCallback
|
||||
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
|
||||
{
|
||||
return sim::AllocateCallback(env, index, callback, initialNotify,
|
||||
&HALSIM_RegisterPWMSpeedCallback);
|
||||
&HALSIM_RegisterPWMOutputPeriodCallback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: cancelSpeedCallback
|
||||
* Method: cancelOutputPeriodCallback
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_cancelSpeedCallback
|
||||
(JNIEnv* env, jclass, jint index, jint handle)
|
||||
{
|
||||
return sim::FreeCallback(env, handle, index, &HALSIM_CancelPWMSpeedCallback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: getSpeed
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_getSpeed
|
||||
(JNIEnv*, jclass, jint index)
|
||||
{
|
||||
return HALSIM_GetPWMSpeed(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: setSpeed
|
||||
* Signature: (ID)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_setSpeed
|
||||
(JNIEnv*, jclass, jint index, jdouble value)
|
||||
{
|
||||
HALSIM_SetPWMSpeed(index, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: registerPositionCallback
|
||||
* Signature: (ILjava/lang/Object;Z)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_registerPositionCallback
|
||||
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
|
||||
{
|
||||
return sim::AllocateCallback(env, index, callback, initialNotify,
|
||||
&HALSIM_RegisterPWMPositionCallback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: cancelPositionCallback
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_cancelPositionCallback
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_cancelOutputPeriodCallback
|
||||
(JNIEnv* env, jclass, jint index, jint handle)
|
||||
{
|
||||
return sim::FreeCallback(env, handle, index,
|
||||
&HALSIM_CancelPWMPositionCallback);
|
||||
&HALSIM_CancelPWMOutputPeriodCallback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: getPosition
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_getPosition
|
||||
(JNIEnv*, jclass, jint index)
|
||||
{
|
||||
return HALSIM_GetPWMPosition(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: setPosition
|
||||
* Signature: (ID)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_setPosition
|
||||
(JNIEnv*, jclass, jint index, jdouble value)
|
||||
{
|
||||
HALSIM_SetPWMPosition(index, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: registerPeriodScaleCallback
|
||||
* Signature: (ILjava/lang/Object;Z)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_registerPeriodScaleCallback
|
||||
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
|
||||
{
|
||||
return sim::AllocateCallback(env, index, callback, initialNotify,
|
||||
&HALSIM_RegisterPWMPeriodScaleCallback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: cancelPeriodScaleCallback
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_cancelPeriodScaleCallback
|
||||
(JNIEnv* env, jclass, jint index, jint handle)
|
||||
{
|
||||
return sim::FreeCallback(env, handle, index,
|
||||
&HALSIM_CancelPWMPeriodScaleCallback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: getPeriodScale
|
||||
* Method: getOutputPeriod
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_getPeriodScale
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_getOutputPeriod
|
||||
(JNIEnv*, jclass, jint index)
|
||||
{
|
||||
return HALSIM_GetPWMPeriodScale(index);
|
||||
return HALSIM_GetPWMOutputPeriod(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: setPeriodScale
|
||||
* Method: setOutputPeriod
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_setPeriodScale
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_setOutputPeriod
|
||||
(JNIEnv*, jclass, jint index, jint value)
|
||||
{
|
||||
HALSIM_SetPWMPeriodScale(index, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: registerZeroLatchCallback
|
||||
* Signature: (ILjava/lang/Object;Z)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_registerZeroLatchCallback
|
||||
(JNIEnv* env, jclass, jint index, jobject callback, jboolean initialNotify)
|
||||
{
|
||||
return sim::AllocateCallback(env, index, callback, initialNotify,
|
||||
&HALSIM_RegisterPWMZeroLatchCallback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: cancelZeroLatchCallback
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_cancelZeroLatchCallback
|
||||
(JNIEnv* env, jclass, jint index, jint handle)
|
||||
{
|
||||
return sim::FreeCallback(env, handle, index,
|
||||
&HALSIM_CancelPWMZeroLatchCallback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: getZeroLatch
|
||||
* Signature: (I)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_getZeroLatch
|
||||
(JNIEnv*, jclass, jint index)
|
||||
{
|
||||
return HALSIM_GetPWMZeroLatch(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_hal_simulation_PWMDataJNI
|
||||
* Method: setZeroLatch
|
||||
* Signature: (IZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_PWMDataJNI_setZeroLatch
|
||||
(JNIEnv*, jclass, jint index, jboolean value)
|
||||
{
|
||||
HALSIM_SetPWMZeroLatch(index, value);
|
||||
HALSIM_SetPWMOutputPeriod(index, value);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -47,61 +47,12 @@ void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle);
|
||||
HAL_Bool HAL_CheckPWMChannel(int32_t channel);
|
||||
|
||||
/**
|
||||
* Sets the configuration settings for the PWM channel.
|
||||
* Indicates the pwm is used by a simulated device.
|
||||
*
|
||||
* All values are in microseconds.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle
|
||||
* @param[in] maxPwm the maximum PWM value
|
||||
* @param[in] deadbandMaxPwm the high range of the center deadband
|
||||
* @param[in] centerPwm the center PWM value
|
||||
* @param[in] deadbandMinPwm the low range of the center deadband
|
||||
* @param[in] minPwm the minimum PWM value
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @param handle the pwm handle
|
||||
* @param device simulated device handle
|
||||
*/
|
||||
void HAL_SetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t maxPwm, int32_t deadbandMaxPwm,
|
||||
int32_t centerPwm, int32_t deadbandMinPwm,
|
||||
int32_t minPwm, int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets the pwm configuration settings for the PWM channel.
|
||||
*
|
||||
* Values are in microseconds.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle
|
||||
* @param[in] maxPwm the maximum PWM value
|
||||
* @param[in] deadbandMaxPwm the high range of the center deadband
|
||||
* @param[in] centerPwm the center PWM value
|
||||
* @param[in] deadbandMinPwm the low range of the center deadband
|
||||
* @param[in] minPwm the minimum PWM value
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_GetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* maxPwm, int32_t* deadbandMaxPwm,
|
||||
int32_t* centerPwm, int32_t* deadbandMinPwm,
|
||||
int32_t* minPwm, int32_t* status);
|
||||
|
||||
/**
|
||||
* Sets if the FPGA should output the center value if the input value is within
|
||||
* the deadband.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle
|
||||
* @param[in] eliminateDeadband true to eliminate deadband, otherwise false
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_SetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
|
||||
HAL_Bool eliminateDeadband, int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets the current eliminate deadband value.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @return true if set, otherwise false
|
||||
*/
|
||||
HAL_Bool HAL_GetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* status);
|
||||
void HAL_SetPWMSimDevice(HAL_DigitalHandle handle, HAL_SimDeviceHandle device);
|
||||
|
||||
/**
|
||||
* Sets a PWM channel to the desired pulse width in microseconds.
|
||||
@@ -115,44 +66,6 @@ void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t microsecondPulseTime,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Sets a PWM channel to the desired scaled value.
|
||||
*
|
||||
* The values range from -1 to 1 and the period is controlled by the PWM Period
|
||||
* and MinHigh registers.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle
|
||||
* @param[in] speed the scaled PWM value to set
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_SetPWMSpeed(HAL_DigitalHandle pwmPortHandle, double speed,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Sets a PWM channel to the desired position value.
|
||||
*
|
||||
* The values range from 0 to 1 and the period is controlled by the PWM Period
|
||||
* and MinHigh registers.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle
|
||||
* @param[in] position the positional PWM value to set
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_SetPWMPosition(HAL_DigitalHandle pwmPortHandle, double position,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Sets a PWM channel to be disabled.
|
||||
*
|
||||
* The channel is disabled until the next time it is set. Note this is different
|
||||
* from just setting a 0 speed, as this will actively stop all signaling on the
|
||||
* channel.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle.
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_SetPWMDisabled(HAL_DigitalHandle pwmPortHandle, int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets the current microsecond pulse time from a PWM channel.
|
||||
*
|
||||
@@ -164,70 +77,14 @@ int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets a scaled value from a PWM channel.
|
||||
*
|
||||
* The values range from -1 to 1.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @return the current speed PWM value
|
||||
*/
|
||||
double HAL_GetPWMSpeed(HAL_DigitalHandle pwmPortHandle, int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets a position value from a PWM channel.
|
||||
*
|
||||
* The values range from 0 to 1.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @return the current positional PWM value
|
||||
*/
|
||||
double HAL_GetPWMPosition(HAL_DigitalHandle pwmPortHandle, int32_t* status);
|
||||
|
||||
/**
|
||||
* Forces a PWM signal to go to 0 temporarily.
|
||||
* Sets the PWM output period.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle.
|
||||
* @param[in] period 0 for 5ms, 1 or 2 for 10ms, 3 for 20ms
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_LatchPWMZero(HAL_DigitalHandle pwmPortHandle, int32_t* status);
|
||||
|
||||
/**
|
||||
* Sets how how often the PWM signal is squelched, thus scaling the period.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle.
|
||||
* @param[in] squelchMask the 2-bit mask of outputs to squelch
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_SetPWMPeriodScale(HAL_DigitalHandle pwmPortHandle, int32_t squelchMask,
|
||||
int32_t* status);
|
||||
|
||||
/**
|
||||
* Sets the PWM output to be a continuous high signal while enabled.
|
||||
*
|
||||
* @param[in] pwmPortHandle the PWM handle.
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
*/
|
||||
void HAL_SetPWMAlwaysHighMode(HAL_DigitalHandle pwmPortHandle, int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets the loop timing of the PWM system.
|
||||
*
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @return the loop time in clock ticks
|
||||
*/
|
||||
int32_t HAL_GetPWMLoopTiming(int32_t* status);
|
||||
|
||||
/**
|
||||
* Gets the pwm starting cycle time.
|
||||
*
|
||||
* This time is relative to the FPGA time.
|
||||
*
|
||||
* @param[out] status Error status variable. 0 on success.
|
||||
* @return the pwm cycle start time
|
||||
*/
|
||||
uint64_t HAL_GetPWMCycleStartTime(int32_t* status);
|
||||
void HAL_SetPWMOutputPeriod(HAL_DigitalHandle pwmPortHandle, int32_t period,
|
||||
int32_t* status);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,8 @@ void HALSIM_CancelPWMInitializedCallback(int32_t index, int32_t uid);
|
||||
HAL_Bool HALSIM_GetPWMInitialized(int32_t index);
|
||||
void HALSIM_SetPWMInitialized(int32_t index, HAL_Bool initialized);
|
||||
|
||||
HAL_SimDeviceHandle HALSIM_GetPWMSimDevice(int32_t index);
|
||||
|
||||
int32_t HALSIM_RegisterPWMPulseMicrosecondCallback(int32_t index,
|
||||
HAL_NotifyCallback callback,
|
||||
void* param,
|
||||
@@ -28,35 +30,13 @@ void HALSIM_CancelPWMPulseMicrosecondCallback(int32_t index, int32_t uid);
|
||||
int32_t HALSIM_GetPWMPulseMicrosecond(int32_t index);
|
||||
void HALSIM_SetPWMPulseMicrosecond(int32_t index, int32_t microsecondPulseTime);
|
||||
|
||||
int32_t HALSIM_RegisterPWMSpeedCallback(int32_t index,
|
||||
HAL_NotifyCallback callback,
|
||||
void* param, HAL_Bool initialNotify);
|
||||
void HALSIM_CancelPWMSpeedCallback(int32_t index, int32_t uid);
|
||||
double HALSIM_GetPWMSpeed(int32_t index);
|
||||
void HALSIM_SetPWMSpeed(int32_t index, double speed);
|
||||
|
||||
int32_t HALSIM_RegisterPWMPositionCallback(int32_t index,
|
||||
HAL_NotifyCallback callback,
|
||||
void* param, HAL_Bool initialNotify);
|
||||
void HALSIM_CancelPWMPositionCallback(int32_t index, int32_t uid);
|
||||
double HALSIM_GetPWMPosition(int32_t index);
|
||||
void HALSIM_SetPWMPosition(int32_t index, double position);
|
||||
|
||||
int32_t HALSIM_RegisterPWMPeriodScaleCallback(int32_t index,
|
||||
HAL_NotifyCallback callback,
|
||||
void* param,
|
||||
HAL_Bool initialNotify);
|
||||
void HALSIM_CancelPWMPeriodScaleCallback(int32_t index, int32_t uid);
|
||||
int32_t HALSIM_GetPWMPeriodScale(int32_t index);
|
||||
void HALSIM_SetPWMPeriodScale(int32_t index, int32_t periodScale);
|
||||
|
||||
int32_t HALSIM_RegisterPWMZeroLatchCallback(int32_t index,
|
||||
HAL_NotifyCallback callback,
|
||||
void* param,
|
||||
HAL_Bool initialNotify);
|
||||
void HALSIM_CancelPWMZeroLatchCallback(int32_t index, int32_t uid);
|
||||
HAL_Bool HALSIM_GetPWMZeroLatch(int32_t index);
|
||||
void HALSIM_SetPWMZeroLatch(int32_t index, HAL_Bool zeroLatch);
|
||||
int32_t HALSIM_RegisterPWMOutputPeriodCallback(int32_t index,
|
||||
HAL_NotifyCallback callback,
|
||||
void* param,
|
||||
HAL_Bool initialNotify);
|
||||
void HALSIM_CancelPWMOutputPeriodCallback(int32_t index, int32_t uid);
|
||||
int32_t HALSIM_GetPWMOutputPeriod(int32_t index);
|
||||
void HALSIM_SetPWMOutputPeriod(int32_t index, int32_t periodScale);
|
||||
|
||||
void HALSIM_RegisterPWMAllCallbacks(int32_t index, HAL_NotifyCallback callback,
|
||||
void* param, HAL_Bool initialNotify);
|
||||
|
||||
@@ -42,13 +42,6 @@ constexpr int32_t kPwmDisabled = 0;
|
||||
|
||||
struct DigitalPort {
|
||||
uint8_t channel;
|
||||
bool configSet = false;
|
||||
bool eliminateDeadband = false;
|
||||
int32_t maxPwm = 0;
|
||||
int32_t deadbandMaxPwm = 0;
|
||||
int32_t centerPwm = 0;
|
||||
int32_t deadbandMinPwm = 0;
|
||||
int32_t minPwm = 0;
|
||||
int32_t filterIndex = 0;
|
||||
std::string previousAllocation;
|
||||
};
|
||||
|
||||
@@ -21,46 +21,6 @@ namespace hal::init {
|
||||
void InitializePWM() {}
|
||||
} // namespace hal::init
|
||||
|
||||
static inline int32_t GetMaxPositivePwm(DigitalPort* port) {
|
||||
return port->maxPwm;
|
||||
}
|
||||
|
||||
static inline int32_t GetMinPositivePwm(DigitalPort* port) {
|
||||
if (port->eliminateDeadband) {
|
||||
return port->deadbandMaxPwm;
|
||||
} else {
|
||||
return port->centerPwm + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int32_t GetCenterPwm(DigitalPort* port) {
|
||||
return port->centerPwm;
|
||||
}
|
||||
|
||||
static inline int32_t GetMaxNegativePwm(DigitalPort* port) {
|
||||
if (port->eliminateDeadband) {
|
||||
return port->deadbandMinPwm;
|
||||
} else {
|
||||
return port->centerPwm - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int32_t GetMinNegativePwm(DigitalPort* port) {
|
||||
return port->minPwm;
|
||||
}
|
||||
|
||||
static inline int32_t GetPositiveScaleFactor(DigitalPort* port) {
|
||||
return GetMaxPositivePwm(port) - GetMinPositivePwm(port);
|
||||
} ///< The scale for positive speeds.
|
||||
|
||||
static inline int32_t GetNegativeScaleFactor(DigitalPort* port) {
|
||||
return GetMaxNegativePwm(port) - GetMinNegativePwm(port);
|
||||
} ///< The scale for negative speeds.
|
||||
|
||||
static inline int32_t GetFullRangeScaleFactor(DigitalPort* port) {
|
||||
return GetMaxPositivePwm(port) - GetMinNegativePwm(port);
|
||||
} ///< The scale for positions.
|
||||
|
||||
extern "C" {
|
||||
|
||||
HAL_DigitalHandle HAL_InitializePWMPort(int32_t channel,
|
||||
@@ -103,8 +63,8 @@ HAL_DigitalHandle HAL_InitializePWMPort(int32_t channel,
|
||||
|
||||
SimPWMData[origChannel].initialized = true;
|
||||
|
||||
// Defaults to allow an always valid config.
|
||||
HAL_SetPWMConfigMicroseconds(handle, 2000, 1501, 1500, 1499, 1000, status);
|
||||
// Disable output.
|
||||
HAL_SetPWMPulseTimeMicroseconds(handle, 0, status);
|
||||
|
||||
port->previousAllocation = allocationLocation ? allocationLocation : "";
|
||||
|
||||
@@ -125,58 +85,12 @@ HAL_Bool HAL_CheckPWMChannel(int32_t channel) {
|
||||
return channel < kNumPWMChannels && channel >= 0;
|
||||
}
|
||||
|
||||
void HAL_SetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle, int32_t max,
|
||||
int32_t deadbandMax, int32_t center,
|
||||
int32_t deadbandMin, int32_t min,
|
||||
int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
void HAL_SetPWMSimDevice(HAL_DigitalHandle handle, HAL_SimDeviceHandle device) {
|
||||
auto port = digitalChannelHandles->Get(handle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
port->maxPwm = max;
|
||||
port->deadbandMaxPwm = deadbandMax;
|
||||
port->deadbandMinPwm = deadbandMin;
|
||||
port->centerPwm = center;
|
||||
port->minPwm = min;
|
||||
port->configSet = true;
|
||||
}
|
||||
|
||||
void HAL_GetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* maxPwm, int32_t* deadbandMaxPwm,
|
||||
int32_t* centerPwm, int32_t* deadbandMinPwm,
|
||||
int32_t* minPwm, int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
*maxPwm = port->maxPwm;
|
||||
*deadbandMaxPwm = port->deadbandMaxPwm;
|
||||
*deadbandMinPwm = port->deadbandMinPwm;
|
||||
*centerPwm = port->centerPwm;
|
||||
*minPwm = port->minPwm;
|
||||
}
|
||||
|
||||
void HAL_SetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
|
||||
HAL_Bool eliminateDeadband, int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
port->eliminateDeadband = eliminateDeadband;
|
||||
}
|
||||
|
||||
HAL_Bool HAL_GetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return false;
|
||||
}
|
||||
return port->eliminateDeadband;
|
||||
SimPWMData[port->channel].simDevice = device;
|
||||
}
|
||||
|
||||
void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
@@ -188,129 +102,6 @@ void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
}
|
||||
|
||||
SimPWMData[port->channel].pulseMicrosecond = value;
|
||||
|
||||
DigitalPort* dPort = port.get();
|
||||
double speed = 0.0;
|
||||
|
||||
if (value == kPwmDisabled) {
|
||||
speed = 0.0;
|
||||
} else if (value > GetMaxPositivePwm(dPort)) {
|
||||
speed = 1.0;
|
||||
} else if (value < GetMinNegativePwm(dPort)) {
|
||||
speed = -1.0;
|
||||
} else if (value > GetMinPositivePwm(dPort)) {
|
||||
speed = static_cast<double>(value - GetMinPositivePwm(dPort)) /
|
||||
static_cast<double>(GetPositiveScaleFactor(dPort));
|
||||
} else if (value < GetMaxNegativePwm(dPort)) {
|
||||
speed = static_cast<double>(value - GetMaxNegativePwm(dPort)) /
|
||||
static_cast<double>(GetNegativeScaleFactor(dPort));
|
||||
} else {
|
||||
speed = 0.0;
|
||||
}
|
||||
|
||||
SimPWMData[port->channel].speed = speed;
|
||||
|
||||
double pos = 0.0;
|
||||
|
||||
if (value < GetMinNegativePwm(dPort)) {
|
||||
pos = 0.0;
|
||||
} else if (value > GetMaxPositivePwm(dPort)) {
|
||||
pos = 1.0;
|
||||
} else {
|
||||
pos = static_cast<double>(value - GetMinNegativePwm(dPort)) /
|
||||
static_cast<double>(GetFullRangeScaleFactor(dPort));
|
||||
}
|
||||
|
||||
SimPWMData[port->channel].position = pos;
|
||||
}
|
||||
|
||||
void HAL_SetPWMSpeed(HAL_DigitalHandle pwmPortHandle, double speed,
|
||||
int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
if (!port->configSet) {
|
||||
*status = INCOMPATIBLE_STATE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::isfinite(speed)) {
|
||||
speed = std::clamp(speed, -1.0, 1.0);
|
||||
} else {
|
||||
speed = 0.0;
|
||||
}
|
||||
|
||||
DigitalPort* dPort = port.get();
|
||||
|
||||
// calculate the desired output pwm value by scaling the speed appropriately
|
||||
int32_t rawValue;
|
||||
if (speed == 0.0) {
|
||||
rawValue = GetCenterPwm(dPort);
|
||||
} else if (speed > 0.0) {
|
||||
rawValue =
|
||||
std::lround(speed * static_cast<double>(GetPositiveScaleFactor(dPort)) +
|
||||
static_cast<double>(GetMinPositivePwm(dPort)));
|
||||
} else {
|
||||
rawValue =
|
||||
std::lround(speed * static_cast<double>(GetNegativeScaleFactor(dPort)) +
|
||||
static_cast<double>(GetMaxNegativePwm(dPort)));
|
||||
}
|
||||
|
||||
if (!((rawValue >= GetMinNegativePwm(dPort)) &&
|
||||
(rawValue <= GetMaxPositivePwm(dPort))) ||
|
||||
rawValue == kPwmDisabled) {
|
||||
*status = HAL_PWM_SCALE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, rawValue, status);
|
||||
}
|
||||
|
||||
void HAL_SetPWMPosition(HAL_DigitalHandle pwmPortHandle, double pos,
|
||||
int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
if (!port->configSet) {
|
||||
*status = INCOMPATIBLE_STATE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos < 0.0) {
|
||||
pos = 0.0;
|
||||
} else if (pos > 1.0) {
|
||||
pos = 1.0;
|
||||
}
|
||||
|
||||
DigitalPort* dPort = port.get();
|
||||
|
||||
// note, need to perform the multiplication below as floating point before
|
||||
// converting to int
|
||||
int32_t rawValue = static_cast<int32_t>(
|
||||
(pos * static_cast<double>(GetFullRangeScaleFactor(dPort))) +
|
||||
GetMinNegativePwm(dPort));
|
||||
|
||||
if (rawValue == kPwmDisabled) {
|
||||
*status = HAL_PWM_SCALE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, rawValue, status);
|
||||
}
|
||||
|
||||
void HAL_SetPWMDisabled(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
SimPWMData[port->channel].pulseMicrosecond = 0;
|
||||
SimPWMData[port->channel].position = 0;
|
||||
SimPWMData[port->channel].speed = 0;
|
||||
}
|
||||
|
||||
int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
@@ -324,88 +115,15 @@ int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
return SimPWMData[port->channel].pulseMicrosecond;
|
||||
}
|
||||
|
||||
double HAL_GetPWMSpeed(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
if (!port->configSet) {
|
||||
*status = INCOMPATIBLE_STATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double speed = SimPWMData[port->channel].speed;
|
||||
if (speed > 1) {
|
||||
speed = 1;
|
||||
}
|
||||
if (speed < -1) {
|
||||
speed = -1;
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
double HAL_GetPWMPosition(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
if (!port->configSet) {
|
||||
*status = INCOMPATIBLE_STATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double position = SimPWMData[port->channel].position;
|
||||
if (position > 1) {
|
||||
position = 1;
|
||||
}
|
||||
if (position < 0) {
|
||||
position = 0;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
void HAL_LatchPWMZero(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
||||
void HAL_SetPWMOutputPeriod(HAL_DigitalHandle pwmPortHandle, int32_t period,
|
||||
int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
SimPWMData[port->channel].zeroLatch = true;
|
||||
SimPWMData[port->channel].zeroLatch = false;
|
||||
SimPWMData[port->channel].outputPeriod = period;
|
||||
}
|
||||
|
||||
void HAL_SetPWMAlwaysHighMode(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
SimPWMData[port->channel].pulseMicrosecond = 0xFFFF;
|
||||
SimPWMData[port->channel].position = 0xFFFF;
|
||||
SimPWMData[port->channel].speed = 0xFFFF;
|
||||
}
|
||||
|
||||
void HAL_SetPWMPeriodScale(HAL_DigitalHandle pwmPortHandle, int32_t squelchMask,
|
||||
int32_t* status) {
|
||||
auto port = digitalChannelHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
SimPWMData[port->channel].periodScale = squelchMask;
|
||||
}
|
||||
|
||||
int32_t HAL_GetPWMLoopTiming(int32_t* status) {
|
||||
return kExpectedLoopTiming;
|
||||
}
|
||||
|
||||
uint64_t HAL_GetPWMCycleStartTime(int32_t* status) {
|
||||
return 0;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -17,11 +17,9 @@ void InitializePWMData() {
|
||||
PWMData* hal::SimPWMData;
|
||||
void PWMData::ResetData() {
|
||||
initialized.Reset(false);
|
||||
simDevice = 0;
|
||||
pulseMicrosecond.Reset(0);
|
||||
speed.Reset(0);
|
||||
position.Reset(0);
|
||||
periodScale.Reset(0);
|
||||
zeroLatch.Reset(false);
|
||||
outputPeriod.Reset(0);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
@@ -29,16 +27,17 @@ void HALSIM_ResetPWMData(int32_t index) {
|
||||
SimPWMData[index].ResetData();
|
||||
}
|
||||
|
||||
HAL_SimDeviceHandle HALSIM_GetPWMSimDevice(int32_t index) {
|
||||
return SimPWMData[index].simDevice;
|
||||
}
|
||||
|
||||
#define DEFINE_CAPI(TYPE, CAPINAME, LOWERNAME) \
|
||||
HAL_SIMDATAVALUE_DEFINE_CAPI(TYPE, HALSIM, PWM##CAPINAME, SimPWMData, \
|
||||
LOWERNAME)
|
||||
|
||||
DEFINE_CAPI(HAL_Bool, Initialized, initialized)
|
||||
DEFINE_CAPI(int32_t, PulseMicrosecond, pulseMicrosecond)
|
||||
DEFINE_CAPI(double, Speed, speed)
|
||||
DEFINE_CAPI(double, Position, position)
|
||||
DEFINE_CAPI(int32_t, PeriodScale, periodScale)
|
||||
DEFINE_CAPI(HAL_Bool, ZeroLatch, zeroLatch)
|
||||
DEFINE_CAPI(int32_t, OutputPeriod, outputPeriod)
|
||||
|
||||
#define REGISTER(NAME) \
|
||||
SimPWMData[index].NAME.RegisterCallback(callback, param, initialNotify)
|
||||
@@ -47,9 +46,6 @@ void HALSIM_RegisterPWMAllCallbacks(int32_t index, HAL_NotifyCallback callback,
|
||||
void* param, HAL_Bool initialNotify) {
|
||||
REGISTER(initialized);
|
||||
REGISTER(pulseMicrosecond);
|
||||
REGISTER(speed);
|
||||
REGISTER(position);
|
||||
REGISTER(periodScale);
|
||||
REGISTER(zeroLatch);
|
||||
REGISTER(outputPeriod);
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -11,20 +11,15 @@ namespace hal {
|
||||
class PWMData {
|
||||
HAL_SIMDATAVALUE_DEFINE_NAME(Initialized)
|
||||
HAL_SIMDATAVALUE_DEFINE_NAME(PulseMicrosecond)
|
||||
HAL_SIMDATAVALUE_DEFINE_NAME(Speed)
|
||||
HAL_SIMDATAVALUE_DEFINE_NAME(Position)
|
||||
HAL_SIMDATAVALUE_DEFINE_NAME(PeriodScale)
|
||||
HAL_SIMDATAVALUE_DEFINE_NAME(ZeroLatch)
|
||||
HAL_SIMDATAVALUE_DEFINE_NAME(OutputPeriod)
|
||||
|
||||
public:
|
||||
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetInitializedName> initialized{
|
||||
false};
|
||||
std::atomic<HAL_SimDeviceHandle> simDevice;
|
||||
SimDataValue<int32_t, HAL_MakeInt, GetPulseMicrosecondName> pulseMicrosecond{
|
||||
0};
|
||||
SimDataValue<double, HAL_MakeDouble, GetSpeedName> speed{0};
|
||||
SimDataValue<double, HAL_MakeDouble, GetPositionName> position{0};
|
||||
SimDataValue<int32_t, HAL_MakeInt, GetPeriodScaleName> periodScale{0};
|
||||
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetZeroLatchName> zeroLatch{false};
|
||||
SimDataValue<int32_t, HAL_MakeInt, GetOutputPeriodName> outputPeriod{0};
|
||||
|
||||
virtual void ResetData();
|
||||
};
|
||||
|
||||
@@ -22,46 +22,6 @@
|
||||
|
||||
using namespace hal;
|
||||
|
||||
static inline int32_t GetMaxPositivePwm(SmartIo* port) {
|
||||
return port->maxPwm;
|
||||
}
|
||||
|
||||
static inline int32_t GetMinPositivePwm(SmartIo* port) {
|
||||
if (port->eliminateDeadband) {
|
||||
return port->deadbandMaxPwm;
|
||||
} else {
|
||||
return port->centerPwm + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int32_t GetCenterPwm(SmartIo* port) {
|
||||
return port->centerPwm;
|
||||
}
|
||||
|
||||
static inline int32_t GetMaxNegativePwm(SmartIo* port) {
|
||||
if (port->eliminateDeadband) {
|
||||
return port->deadbandMinPwm;
|
||||
} else {
|
||||
return port->centerPwm - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int32_t GetMinNegativePwm(SmartIo* port) {
|
||||
return port->minPwm;
|
||||
}
|
||||
|
||||
static inline int32_t GetPositiveScaleFactor(SmartIo* port) {
|
||||
return GetMaxPositivePwm(port) - GetMinPositivePwm(port);
|
||||
} ///< The scale for positive speeds.
|
||||
|
||||
static inline int32_t GetNegativeScaleFactor(SmartIo* port) {
|
||||
return GetMaxNegativePwm(port) - GetMinNegativePwm(port);
|
||||
} ///< The scale for negative speeds.
|
||||
|
||||
static inline int32_t GetFullRangeScaleFactor(SmartIo* port) {
|
||||
return GetMaxPositivePwm(port) - GetMinNegativePwm(port);
|
||||
} ///< The scale for positions.
|
||||
|
||||
namespace hal::init {
|
||||
void InitializePWM() {}
|
||||
} // namespace hal::init
|
||||
@@ -104,8 +64,8 @@ HAL_DigitalHandle HAL_InitializePWMPort(int32_t channel,
|
||||
return HAL_kInvalidHandle;
|
||||
}
|
||||
|
||||
// Defaults to allow an always valid config.
|
||||
HAL_SetPWMConfigMicroseconds(handle, 2000, 1501, 1500, 1499, 1000, status);
|
||||
// Disable the PWM output.
|
||||
HAL_SetPWMPulseTimeMicroseconds(handle, 0, status);
|
||||
if (*status != 0) {
|
||||
smartIoHandles->Free(handle, HAL_HandleEnum::PWM);
|
||||
return HAL_kInvalidHandle;
|
||||
@@ -137,63 +97,13 @@ void HAL_FreePWMPort(HAL_DigitalHandle pwmPortHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_SetPWMSimDevice(HAL_DigitalHandle handle, HAL_SimDeviceHandle device) {
|
||||
}
|
||||
|
||||
HAL_Bool HAL_CheckPWMChannel(int32_t channel) {
|
||||
return channel < kNumSmartIo && channel >= 0;
|
||||
}
|
||||
|
||||
void HAL_SetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle, int32_t max,
|
||||
int32_t deadbandMax, int32_t center,
|
||||
int32_t deadbandMin, int32_t min,
|
||||
int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
port->maxPwm = max;
|
||||
port->deadbandMaxPwm = deadbandMax;
|
||||
port->deadbandMinPwm = deadbandMin;
|
||||
port->centerPwm = center;
|
||||
port->minPwm = min;
|
||||
port->configSet = true;
|
||||
}
|
||||
|
||||
void HAL_GetPWMConfigMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* maxPwm, int32_t* deadbandMaxPwm,
|
||||
int32_t* centerPwm, int32_t* deadbandMinPwm,
|
||||
int32_t* minPwm, int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
*maxPwm = port->maxPwm;
|
||||
*deadbandMaxPwm = port->deadbandMaxPwm;
|
||||
*deadbandMinPwm = port->deadbandMinPwm;
|
||||
*centerPwm = port->centerPwm;
|
||||
*minPwm = port->minPwm;
|
||||
}
|
||||
|
||||
void HAL_SetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
|
||||
HAL_Bool eliminateDeadband, int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
port->eliminateDeadband = eliminateDeadband;
|
||||
}
|
||||
|
||||
HAL_Bool HAL_GetPWMEliminateDeadband(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return false;
|
||||
}
|
||||
return port->eliminateDeadband;
|
||||
}
|
||||
|
||||
void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t microsecondPulseTime,
|
||||
int32_t* status) {
|
||||
@@ -216,87 +126,6 @@ void HAL_SetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
*status = port->SetPwmMicroseconds(microsecondPulseTime);
|
||||
}
|
||||
|
||||
void HAL_SetPWMSpeed(HAL_DigitalHandle pwmPortHandle, double speed,
|
||||
int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
if (!port->configSet) {
|
||||
*status = INCOMPATIBLE_STATE;
|
||||
return;
|
||||
}
|
||||
|
||||
SmartIo* dPort = port.get();
|
||||
|
||||
if (std::isfinite(speed)) {
|
||||
speed = std::clamp(speed, -1.0, 1.0);
|
||||
} else {
|
||||
speed = 0.0;
|
||||
}
|
||||
|
||||
// calculate the desired output pwm value by scaling the speed appropriately
|
||||
int32_t rawValue;
|
||||
if (speed == 0.0) {
|
||||
rawValue = GetCenterPwm(dPort);
|
||||
} else if (speed > 0.0) {
|
||||
rawValue =
|
||||
std::lround(speed * static_cast<double>(GetPositiveScaleFactor(dPort)) +
|
||||
static_cast<double>(GetMinPositivePwm(dPort)));
|
||||
} else {
|
||||
rawValue =
|
||||
std::lround(speed * static_cast<double>(GetNegativeScaleFactor(dPort)) +
|
||||
static_cast<double>(GetMaxNegativePwm(dPort)));
|
||||
}
|
||||
|
||||
if (!((rawValue >= GetMinNegativePwm(dPort)) &&
|
||||
(rawValue <= GetMaxPositivePwm(dPort))) ||
|
||||
rawValue == kPwmDisabled) {
|
||||
*status = HAL_PWM_SCALE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, rawValue, status);
|
||||
}
|
||||
|
||||
void HAL_SetPWMPosition(HAL_DigitalHandle pwmPortHandle, double pos,
|
||||
int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
if (!port->configSet) {
|
||||
*status = INCOMPATIBLE_STATE;
|
||||
return;
|
||||
}
|
||||
SmartIo* dPort = port.get();
|
||||
|
||||
if (pos < 0.0) {
|
||||
pos = 0.0;
|
||||
} else if (pos > 1.0) {
|
||||
pos = 1.0;
|
||||
}
|
||||
|
||||
// note, need to perform the multiplication below as floating point before
|
||||
// converting to int
|
||||
int32_t rawValue = static_cast<int32_t>(
|
||||
(pos * static_cast<double>(GetFullRangeScaleFactor(dPort))) +
|
||||
GetMinNegativePwm(dPort));
|
||||
|
||||
if (rawValue == kPwmDisabled) {
|
||||
*status = HAL_PWM_SCALE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, rawValue, status);
|
||||
}
|
||||
|
||||
void HAL_SetPWMDisabled(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, kPwmDisabled, status);
|
||||
}
|
||||
|
||||
int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
@@ -310,79 +139,15 @@ int32_t HAL_GetPWMPulseTimeMicroseconds(HAL_DigitalHandle pwmPortHandle,
|
||||
return microseconds;
|
||||
}
|
||||
|
||||
double HAL_GetPWMSpeed(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
if (!port->configSet) {
|
||||
*status = INCOMPATIBLE_STATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t value = HAL_GetPWMPulseTimeMicroseconds(pwmPortHandle, status);
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
}
|
||||
SmartIo* dPort = port.get();
|
||||
if (value == kPwmDisabled) {
|
||||
return 0.0;
|
||||
} else if (value > GetMaxPositivePwm(dPort)) {
|
||||
return 1.0;
|
||||
} else if (value < GetMinNegativePwm(dPort)) {
|
||||
return -1.0;
|
||||
} else if (value > GetMinPositivePwm(dPort)) {
|
||||
return static_cast<double>(value - GetMinPositivePwm(dPort)) /
|
||||
static_cast<double>(GetPositiveScaleFactor(dPort));
|
||||
} else if (value < GetMaxNegativePwm(dPort)) {
|
||||
return static_cast<double>(value - GetMaxNegativePwm(dPort)) /
|
||||
static_cast<double>(GetNegativeScaleFactor(dPort));
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
double HAL_GetPWMPosition(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return 0;
|
||||
}
|
||||
if (!port->configSet) {
|
||||
*status = INCOMPATIBLE_STATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t value = HAL_GetPWMPulseTimeMicroseconds(pwmPortHandle, status);
|
||||
if (*status != 0) {
|
||||
return 0;
|
||||
}
|
||||
SmartIo* dPort = port.get();
|
||||
|
||||
if (value < GetMinNegativePwm(dPort)) {
|
||||
return 0.0;
|
||||
} else if (value > GetMaxPositivePwm(dPort)) {
|
||||
return 1.0;
|
||||
} else {
|
||||
return static_cast<double>(value - GetMinNegativePwm(dPort)) /
|
||||
static_cast<double>(GetFullRangeScaleFactor(dPort));
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_LatchPWMZero(HAL_DigitalHandle pwmPortHandle, int32_t* status) {
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, 0, status);
|
||||
}
|
||||
|
||||
void HAL_SetPWMPeriodScale(HAL_DigitalHandle pwmPortHandle, int32_t squelchMask,
|
||||
int32_t* status) {
|
||||
void HAL_SetPWMOutputPeriod(HAL_DigitalHandle pwmPortHandle, int32_t period,
|
||||
int32_t* status) {
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (squelchMask) {
|
||||
switch (period) {
|
||||
case 0:
|
||||
*status = port->SetPwmOutputPeriod(hal::PwmOutputPeriod::k5ms);
|
||||
break;
|
||||
@@ -399,31 +164,4 @@ void HAL_SetPWMPeriodScale(HAL_DigitalHandle pwmPortHandle, int32_t squelchMask,
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_SetPWMAlwaysHighMode(HAL_DigitalHandle pwmPortHandle,
|
||||
int32_t* status) {
|
||||
// Always high is going to have to use a 2ms period
|
||||
auto port = smartIoHandles->Get(pwmPortHandle, HAL_HandleEnum::PWM);
|
||||
if (port == nullptr) {
|
||||
*status = HAL_HANDLE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
*status = port->SetPwmOutputPeriod(hal::PwmOutputPeriod::k2ms);
|
||||
if (*status != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmPortHandle, kPwmAlwaysHigh, status);
|
||||
}
|
||||
|
||||
int32_t HAL_GetPWMLoopTiming(int32_t* status) {
|
||||
// TODO(thad) not currently supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t HAL_GetPWMCycleStartTime(int32_t* status) {
|
||||
// TODO(thad) not currently supported
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -36,13 +36,6 @@ enum class PwmOutputPeriod {
|
||||
|
||||
struct SmartIo {
|
||||
uint8_t channel;
|
||||
bool configSet = false;
|
||||
bool eliminateDeadband = false;
|
||||
int32_t maxPwm = 0;
|
||||
int32_t deadbandMaxPwm = 0;
|
||||
int32_t centerPwm = 0;
|
||||
int32_t deadbandMinPwm = 0;
|
||||
int32_t minPwm = 0;
|
||||
std::string previousAllocation;
|
||||
SmartIoMode currentMode{SmartIoMode::DigitalInput};
|
||||
nt::IntegerPublisher modePublisher;
|
||||
|
||||
@@ -9,15 +9,16 @@
|
||||
extern "C" {
|
||||
void HALSIM_ResetPWMData(int32_t index) {}
|
||||
|
||||
HAL_SimDeviceHandle HALSIM_GetPWMSimDevice(int32_t index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DEFINE_CAPI(TYPE, CAPINAME, RETURN) \
|
||||
HAL_SIMDATAVALUE_STUB_CAPI(TYPE, HALSIM, PWM##CAPINAME, RETURN)
|
||||
|
||||
DEFINE_CAPI(HAL_Bool, Initialized, false)
|
||||
DEFINE_CAPI(int32_t, PulseMicrosecond, 0)
|
||||
DEFINE_CAPI(double, Speed, 0)
|
||||
DEFINE_CAPI(double, Position, 0)
|
||||
DEFINE_CAPI(int32_t, PeriodScale, 0)
|
||||
DEFINE_CAPI(HAL_Bool, ZeroLatch, false)
|
||||
DEFINE_CAPI(int32_t, OutputPeriod, 0)
|
||||
|
||||
void HALSIM_RegisterPWMAllCallbacks(int32_t index, HAL_NotifyCallback callback,
|
||||
void* param, HAL_Bool initialNotify) {}
|
||||
|
||||
@@ -15,9 +15,8 @@ import edu.wpi.first.wpilibj.motorcontrol.PWMMotorController;
|
||||
public class RomiMotor extends PWMMotorController {
|
||||
/** Common initialization code called by all constructors. */
|
||||
protected final void initRomiMotor() {
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
using namespace frc;
|
||||
|
||||
RomiMotor::RomiMotor(int channel) : PWMMotorController("Romi Motor", channel) {
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ nativeUtils {
|
||||
groupId = "edu.wpi.first.thirdparty.frc2024.ceres"
|
||||
artifactId = "ceres-cpp"
|
||||
headerClassifier = "headers"
|
||||
sourceClassifier = "sources"
|
||||
ext = "zip"
|
||||
version = '2.2-3'
|
||||
targetPlatforms.addAll(nativeUtils.wpi.platforms.desktopPlatforms)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
using namespace halsimgui;
|
||||
|
||||
namespace {
|
||||
HALSIMGUI_DATASOURCE_DOUBLE_INDEXED(PWMSpeed, "PWM");
|
||||
HALSIMGUI_DATASOURCE_DOUBLE_INDEXED(PWMPulseMicrosecond, "PWM");
|
||||
|
||||
class PWMSimModel : public glass::PWMModel {
|
||||
public:
|
||||
@@ -33,12 +33,14 @@ class PWMSimModel : public glass::PWMModel {
|
||||
|
||||
glass::DoubleSource* GetSpeedData() override { return &m_speed; }
|
||||
|
||||
void SetSpeed(double val) override { HALSIM_SetPWMSpeed(m_index, val); }
|
||||
void SetSpeed(double val) override {
|
||||
HALSIM_SetPWMPulseMicrosecond(m_index, val);
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t m_index;
|
||||
int m_led = -1;
|
||||
PWMSpeedSource m_speed;
|
||||
PWMPulseMicrosecondSource m_speed;
|
||||
};
|
||||
|
||||
class PWMsSimModel : public glass::PWMsModel {
|
||||
|
||||
@@ -265,11 +265,8 @@ PWMs may be used to control either motor controllers or servos. Typically only
|
||||
| Data Key | Type | Description |
|
||||
| ------------------- | ------- | ------------------------------------------ |
|
||||
| ``"<init"`` | Boolean | If PWM is initialized in the robot program |
|
||||
| ``"<speed"`` | Float | Speed, -1.0 to 1.0 range |
|
||||
| ``"<position"`` | Float | Servo position, 0.0 to 1.0 range |
|
||||
| ``"<raw"`` | Integer | The pulse time in microseconds |
|
||||
| ``"<period_scale"`` | Integer | Scales the PWM signal by squelching setting a 2-bit mask of outputs to squelch (ex. `1` -> squelch every other value; `3` -> squelch 3 of 4 values) |
|
||||
| ``"<zero_latch"`` | Boolean | Whether the PWM should be latched to 0 |
|
||||
| ``"<output_period"``| Integer | Scales the PWM signal by squelching setting a 2-bit mask of outputs to squelch (ex. `1` -> squelch every other value; `3` -> squelch 3 of 4 values) |
|
||||
|
||||
#### Solenoid Output ("Solenoid")
|
||||
|
||||
|
||||
@@ -505,25 +505,12 @@ components:
|
||||
<init:
|
||||
type: boolean
|
||||
description: "If PWM is initialized in the robot program"
|
||||
<speed:
|
||||
type: number
|
||||
description: "Speed"
|
||||
minimum: -1.0
|
||||
maximum: 1.0
|
||||
<position:
|
||||
type: number
|
||||
description: "Servo position"
|
||||
minimum: 0.0
|
||||
maximum: 1.0
|
||||
"<raw":
|
||||
type: integer
|
||||
description: "The pulse time in microseconds"
|
||||
"<period_scale":
|
||||
"<output_period":
|
||||
type: integer
|
||||
description: "Scales the PWM signal by squelching setting a 2-bit mask of outputs to squelch (ex. `1` -> squelch every other value; `3` -> squelch 3 of 4 values)"
|
||||
"<zero_latch":
|
||||
type: boolean
|
||||
description: "Whether the PWM should be latched to 0"
|
||||
|
||||
solenoidData:
|
||||
type: object
|
||||
|
||||
@@ -28,11 +28,8 @@ HALSimWSProviderPWM::~HALSimWSProviderPWM() {
|
||||
|
||||
void HALSimWSProviderPWM::RegisterCallbacks() {
|
||||
m_initCbKey = REGISTER(Initialized, "<init", bool, boolean);
|
||||
m_speedCbKey = REGISTER(Speed, "<speed", double, double);
|
||||
m_positionCbKey = REGISTER(Position, "<position", double, double);
|
||||
m_rawCbKey = REGISTER(PulseMicrosecond, "<raw", int32_t, int);
|
||||
m_periodScaleCbKey = REGISTER(PeriodScale, "<period_scale", int32_t, int);
|
||||
m_zeroLatchCbKey = REGISTER(ZeroLatch, "<zero_latch", bool, boolean);
|
||||
m_outputPeriodCbKey = REGISTER(OutputPeriod, "<output_period", int32_t, int);
|
||||
}
|
||||
|
||||
void HALSimWSProviderPWM::CancelCallbacks() {
|
||||
@@ -41,18 +38,12 @@ void HALSimWSProviderPWM::CancelCallbacks() {
|
||||
|
||||
void HALSimWSProviderPWM::DoCancelCallbacks() {
|
||||
HALSIM_CancelPWMInitializedCallback(m_channel, m_initCbKey);
|
||||
HALSIM_CancelPWMSpeedCallback(m_channel, m_speedCbKey);
|
||||
HALSIM_CancelPWMPositionCallback(m_channel, m_positionCbKey);
|
||||
HALSIM_CancelPWMPulseMicrosecondCallback(m_channel, m_rawCbKey);
|
||||
HALSIM_CancelPWMPeriodScaleCallback(m_channel, m_periodScaleCbKey);
|
||||
HALSIM_CancelPWMZeroLatchCallback(m_channel, m_zeroLatchCbKey);
|
||||
HALSIM_CancelPWMOutputPeriodCallback(m_channel, m_outputPeriodCbKey);
|
||||
|
||||
m_initCbKey = 0;
|
||||
m_speedCbKey = 0;
|
||||
m_positionCbKey = 0;
|
||||
m_rawCbKey = 0;
|
||||
m_periodScaleCbKey = 0;
|
||||
m_zeroLatchCbKey = 0;
|
||||
m_outputPeriodCbKey = 0;
|
||||
}
|
||||
|
||||
} // namespace wpilibws
|
||||
|
||||
@@ -24,11 +24,8 @@ class HALSimWSProviderPWM : public HALSimWSHalChanProvider {
|
||||
|
||||
private:
|
||||
int32_t m_initCbKey = 0;
|
||||
int32_t m_speedCbKey = 0;
|
||||
int32_t m_positionCbKey = 0;
|
||||
int32_t m_rawCbKey = 0;
|
||||
int32_t m_periodScaleCbKey = 0;
|
||||
int32_t m_zeroLatchCbKey = 0;
|
||||
int32_t m_outputPeriodCbKey = 0;
|
||||
};
|
||||
|
||||
} // namespace wpilibws
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
{{ name }}::{{ name }}(int channel) : PWMMotorController("{{ name }}", channel) {
|
||||
m_pwm.SetBounds({{ pulse_width_ms.max }}_ms, {{ pulse_width_ms.deadbandMax }}_ms, {{ pulse_width_ms.center }}_ms, {{ pulse_width_ms.deadbandMin }}_ms, {{ pulse_width_ms.min }}_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_{{ PeriodMultiplier | default("1", true)}}X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds({{ pulse_width_ms.max }}_ms, {{ pulse_width_ms.deadbandMax }}_ms, {{ pulse_width_ms.center }}_ms, {{ pulse_width_ms.deadbandMin }}_ms, {{ pulse_width_ms.min }}_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_{{ OutputPeriod | default("5", true)}}Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "{{ ResourceName }}");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
DMC60::DMC60(int channel) : PWMMotorController("DMC60", channel) {
|
||||
m_pwm.SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "DigilentDMC60");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
Jaguar::Jaguar(int channel) : PWMMotorController("Jaguar", channel) {
|
||||
m_pwm.SetBounds(2.31_ms, 1.55_ms, 1.507_ms, 1.454_ms, 0.697_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.31_ms, 1.55_ms, 1.507_ms, 1.454_ms, 0.697_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "Jaguar");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
Koors40::Koors40(int channel) : PWMMotorController("Koors40", channel) {
|
||||
m_pwm.SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_4X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_20Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "Koors40");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
PWMSparkFlex::PWMSparkFlex(int channel) : PWMMotorController("PWMSparkFlex", channel) {
|
||||
m_pwm.SetBounds(2.003_ms, 1.55_ms, 1.5_ms, 1.46_ms, 0.999_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.003_ms, 1.55_ms, 1.5_ms, 1.46_ms, 0.999_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "RevSparkFlexPWM");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
PWMSparkMax::PWMSparkMax(int channel) : PWMMotorController("PWMSparkMax", channel) {
|
||||
m_pwm.SetBounds(2.003_ms, 1.55_ms, 1.5_ms, 1.46_ms, 0.999_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.003_ms, 1.55_ms, 1.5_ms, 1.46_ms, 0.999_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "RevSparkMaxPWM");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
PWMTalonFX::PWMTalonFX(int channel) : PWMMotorController("PWMTalonFX", channel) {
|
||||
m_pwm.SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "TalonFX");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
PWMTalonSRX::PWMTalonSRX(int channel) : PWMMotorController("PWMTalonSRX", channel) {
|
||||
m_pwm.SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "PWMTalonSRX");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
PWMVenom::PWMVenom(int channel) : PWMMotorController("PWMVenom", channel) {
|
||||
m_pwm.SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "FusionVenom");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
PWMVictorSPX::PWMVictorSPX(int channel) : PWMMotorController("PWMVictorSPX", channel) {
|
||||
m_pwm.SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "PWMVictorSPX");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
SD540::SD540(int channel) : PWMMotorController("SD540", channel) {
|
||||
m_pwm.SetBounds(2.05_ms, 1.55_ms, 1.5_ms, 1.44_ms, 0.94_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.05_ms, 1.55_ms, 1.5_ms, 1.44_ms, 0.94_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "MindsensorsSD540");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
Spark::Spark(int channel) : PWMMotorController("Spark", channel) {
|
||||
m_pwm.SetBounds(2.003_ms, 1.55_ms, 1.5_ms, 1.46_ms, 0.999_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.003_ms, 1.55_ms, 1.5_ms, 1.46_ms, 0.999_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "RevSPARK");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
SparkMini::SparkMini(int channel) : PWMMotorController("SparkMini", channel) {
|
||||
m_pwm.SetBounds(2.5_ms, 1.51_ms, 1.5_ms, 1.49_ms, 0.5_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.5_ms, 1.51_ms, 1.5_ms, 1.49_ms, 0.5_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "RevSPARK");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
Talon::Talon(int channel) : PWMMotorController("Talon", channel) {
|
||||
m_pwm.SetBounds(2.037_ms, 1.539_ms, 1.513_ms, 1.487_ms, 0.989_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.037_ms, 1.539_ms, 1.513_ms, 1.487_ms, 0.989_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "Talon");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
Victor::Victor(int channel) : PWMMotorController("Victor", channel) {
|
||||
m_pwm.SetBounds(2.027_ms, 1.525_ms, 1.507_ms, 1.49_ms, 1.026_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_2X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.027_ms, 1.525_ms, 1.507_ms, 1.49_ms, 1.026_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_10Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "Victor");
|
||||
}
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
using namespace frc;
|
||||
|
||||
VictorSP::VictorSP(int channel) : PWMMotorController("VictorSP", channel) {
|
||||
m_pwm.SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetPeriodMultiplier(PWM::kPeriodMultiplier_1X);
|
||||
m_pwm.SetSpeed(0.0);
|
||||
m_pwm.SetZeroLatch();
|
||||
SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
|
||||
SetSpeed(0.0);
|
||||
|
||||
HAL_ReportUsage("IO", GetChannel(), "VictorSP");
|
||||
}
|
||||
|
||||
@@ -31,11 +31,7 @@ PWM::PWM(int channel, bool registerSendable) {
|
||||
|
||||
m_channel = channel;
|
||||
|
||||
HAL_SetPWMDisabled(m_handle, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", channel);
|
||||
status = 0;
|
||||
HAL_SetPWMEliminateDeadband(m_handle, false, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", channel);
|
||||
SetDisabled();
|
||||
|
||||
HAL_ReportUsage("IO", channel, "PWM");
|
||||
if (registerSendable) {
|
||||
@@ -45,9 +41,7 @@ PWM::PWM(int channel, bool registerSendable) {
|
||||
|
||||
PWM::~PWM() {
|
||||
if (m_handle != HAL_kInvalidHandle) {
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMDisabled(m_handle, &status);
|
||||
FRC_ReportError(status, "Channel {}", m_channel);
|
||||
SetDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,121 +59,48 @@ units::microsecond_t PWM::GetPulseTime() const {
|
||||
return units::microsecond_t{value};
|
||||
}
|
||||
|
||||
void PWM::SetPosition(double pos) {
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMPosition(m_handle, pos, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
}
|
||||
|
||||
double PWM::GetPosition() const {
|
||||
int32_t status = 0;
|
||||
double position = HAL_GetPWMPosition(m_handle, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
return position;
|
||||
}
|
||||
|
||||
void PWM::SetSpeed(double speed) {
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMSpeed(m_handle, speed, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
}
|
||||
|
||||
double PWM::GetSpeed() const {
|
||||
int32_t status = 0;
|
||||
double speed = HAL_GetPWMSpeed(m_handle, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
return speed;
|
||||
}
|
||||
|
||||
void PWM::SetDisabled() {
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMDisabled(m_handle, &status);
|
||||
HAL_SetPWMPulseTimeMicroseconds(m_handle, 0, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
}
|
||||
|
||||
void PWM::SetPeriodMultiplier(PeriodMultiplier mult) {
|
||||
void PWM::SetOutputPeriod(OutputPeriod mult) {
|
||||
int32_t status = 0;
|
||||
|
||||
switch (mult) {
|
||||
case kPeriodMultiplier_4X:
|
||||
HAL_SetPWMPeriodScale(m_handle, 3,
|
||||
&status); // Squelch 3 out of 4 outputs
|
||||
case kOutputPeriod_20Ms:
|
||||
HAL_SetPWMOutputPeriod(m_handle, 3,
|
||||
&status); // Squelch 3 out of 4 outputs
|
||||
break;
|
||||
case kPeriodMultiplier_2X:
|
||||
HAL_SetPWMPeriodScale(m_handle, 1,
|
||||
&status); // Squelch 1 out of 2 outputs
|
||||
case kOutputPeriod_10Ms:
|
||||
HAL_SetPWMOutputPeriod(m_handle, 1,
|
||||
&status); // Squelch 1 out of 2 outputs
|
||||
break;
|
||||
case kPeriodMultiplier_1X:
|
||||
HAL_SetPWMPeriodScale(m_handle, 0, &status); // Don't squelch any outputs
|
||||
case kOutputPeriod_5Ms:
|
||||
HAL_SetPWMOutputPeriod(m_handle, 0,
|
||||
&status); // Don't squelch any outputs
|
||||
break;
|
||||
default:
|
||||
throw FRC_MakeError(err::InvalidParameter, "PeriodMultiplier value {}",
|
||||
throw FRC_MakeError(err::InvalidParameter, "OutputPeriod value {}",
|
||||
static_cast<int>(mult));
|
||||
}
|
||||
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
}
|
||||
|
||||
void PWM::SetZeroLatch() {
|
||||
int32_t status = 0;
|
||||
HAL_LatchPWMZero(m_handle, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
}
|
||||
|
||||
void PWM::EnableDeadbandElimination(bool eliminateDeadband) {
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMEliminateDeadband(m_handle, eliminateDeadband, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
}
|
||||
|
||||
void PWM::SetBounds(units::microsecond_t max, units::microsecond_t deadbandMax,
|
||||
units::microsecond_t center,
|
||||
units::microsecond_t deadbandMin,
|
||||
units::microsecond_t min) {
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMConfigMicroseconds(m_handle, max.value(), deadbandMax.value(),
|
||||
center.value(), deadbandMin.value(), min.value(),
|
||||
&status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
}
|
||||
|
||||
void PWM::GetBounds(units::microsecond_t* max,
|
||||
units::microsecond_t* deadbandMax,
|
||||
units::microsecond_t* center,
|
||||
units::microsecond_t* deadbandMin,
|
||||
units::microsecond_t* min) {
|
||||
int32_t status = 0;
|
||||
int32_t rawMax, rawDeadbandMax, rawCenter, rawDeadbandMin, rawMin;
|
||||
HAL_GetPWMConfigMicroseconds(m_handle, &rawMax, &rawDeadbandMax, &rawCenter,
|
||||
&rawDeadbandMin, &rawMin, &status);
|
||||
*max = units::microsecond_t{static_cast<double>(rawMax)};
|
||||
*deadbandMax = units::microsecond_t{static_cast<double>(rawDeadbandMax)};
|
||||
*center = units::microsecond_t{static_cast<double>(rawCenter)};
|
||||
*deadbandMin = units::microsecond_t{static_cast<double>(rawDeadbandMin)};
|
||||
*min = units::microsecond_t{static_cast<double>(rawMin)};
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
}
|
||||
|
||||
void PWM::SetAlwaysHighMode() {
|
||||
int32_t status = 0;
|
||||
HAL_SetPWMAlwaysHighMode(m_handle, &status);
|
||||
FRC_CheckErrorStatus(status, "Channel {}", m_channel);
|
||||
}
|
||||
|
||||
int PWM::GetChannel() const {
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
void PWM::SetSimDevice(HAL_SimDeviceHandle device) {
|
||||
HAL_SetPWMSimDevice(m_handle, device);
|
||||
}
|
||||
|
||||
void PWM::InitSendable(wpi::SendableBuilder& builder) {
|
||||
builder.SetSmartDashboardType("PWM");
|
||||
builder.SetActuator(true);
|
||||
builder.AddDoubleProperty(
|
||||
"Value", [=, this] { return GetPulseTime().value(); },
|
||||
[=, this](double value) { SetPulseTime(units::millisecond_t{value}); });
|
||||
builder.AddDoubleProperty(
|
||||
"Speed", [=, this] { return GetSpeed(); },
|
||||
[=, this](double value) { SetSpeed(value); });
|
||||
builder.AddDoubleProperty(
|
||||
"Position", [=, this] { return GetPosition(); },
|
||||
[=, this](double value) { SetPosition(value); });
|
||||
}
|
||||
|
||||
@@ -10,33 +10,44 @@
|
||||
|
||||
using namespace frc;
|
||||
|
||||
constexpr double Servo::kMaxServoAngle;
|
||||
constexpr double Servo::kMinServoAngle;
|
||||
|
||||
constexpr units::millisecond_t Servo::kDefaultMaxServoPWM;
|
||||
constexpr units::millisecond_t Servo::kDefaultMinServoPWM;
|
||||
|
||||
Servo::Servo(int channel) : PWM(channel) {
|
||||
// Set minimum and maximum PWM values supported by the servo
|
||||
SetBounds(kDefaultMaxServoPWM, 0.0_ms, 0.0_ms, 0.0_ms, kDefaultMinServoPWM);
|
||||
Servo::Servo(int channel) : m_pwm(channel, false) {
|
||||
wpi::SendableRegistry::Add(this, "Servo", channel);
|
||||
|
||||
// Assign defaults for period multiplier for the servo PWM control signal
|
||||
SetPeriodMultiplier(kPeriodMultiplier_4X);
|
||||
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_20Ms);
|
||||
|
||||
HAL_ReportUsage("IO", channel, "Servo");
|
||||
wpi::SendableRegistry::SetName(this, "Servo", channel);
|
||||
|
||||
m_simDevice = hal::SimDevice{"Servo", channel};
|
||||
if (m_simDevice) {
|
||||
m_simPosition = m_simDevice.CreateDouble("Position", true, 0.0);
|
||||
m_pwm.SetSimDevice(m_simDevice);
|
||||
}
|
||||
}
|
||||
|
||||
void Servo::Set(double value) {
|
||||
SetPosition(value);
|
||||
}
|
||||
value = std::clamp(value, 0.0, 1.0);
|
||||
if (m_simPosition) {
|
||||
m_simPosition.Set(value);
|
||||
}
|
||||
|
||||
void Servo::SetOffline() {
|
||||
SetDisabled();
|
||||
units::microsecond_t rawValue =
|
||||
(value * GetFullRangeScaleFactor()) + m_minPwm;
|
||||
|
||||
m_pwm.SetPulseTime(rawValue);
|
||||
}
|
||||
|
||||
double Servo::Get() const {
|
||||
return GetPosition();
|
||||
units::microsecond_t rawValue = m_pwm.GetPulseTime();
|
||||
|
||||
if (rawValue < m_minPwm) {
|
||||
return 0.0;
|
||||
} else if (rawValue > m_maxPwm) {
|
||||
return 1.0;
|
||||
}
|
||||
return (rawValue - m_minPwm).to<double>() /
|
||||
GetFullRangeScaleFactor().to<double>();
|
||||
}
|
||||
|
||||
void Servo::SetAngle(double degrees) {
|
||||
@@ -46,19 +57,11 @@ void Servo::SetAngle(double degrees) {
|
||||
degrees = kMaxServoAngle;
|
||||
}
|
||||
|
||||
SetPosition((degrees - kMinServoAngle) / GetServoAngleRange());
|
||||
Set((degrees - kMinServoAngle) / GetServoAngleRange());
|
||||
}
|
||||
|
||||
double Servo::GetAngle() const {
|
||||
return GetPosition() * GetServoAngleRange() + kMinServoAngle;
|
||||
}
|
||||
|
||||
double Servo::GetMaxAngle() const {
|
||||
return kMaxServoAngle;
|
||||
}
|
||||
|
||||
double Servo::GetMinAngle() const {
|
||||
return kMinServoAngle;
|
||||
return Get() * GetServoAngleRange() + kMinServoAngle;
|
||||
}
|
||||
|
||||
void Servo::InitSendable(wpi::SendableBuilder& builder) {
|
||||
@@ -68,6 +71,14 @@ void Servo::InitSendable(wpi::SendableBuilder& builder) {
|
||||
[=, this](double value) { Set(value); });
|
||||
}
|
||||
|
||||
double Servo::GetServoAngleRange() const {
|
||||
double Servo::GetServoAngleRange() {
|
||||
return kMaxServoAngle - kMinServoAngle;
|
||||
}
|
||||
|
||||
units::microsecond_t Servo::GetFullRangeScaleFactor() const {
|
||||
return m_maxPwm - m_minPwm;
|
||||
}
|
||||
|
||||
int Servo::GetChannel() const {
|
||||
return m_pwm.GetChannel();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ void PWMMotorController::Set(double speed) {
|
||||
if (m_isInverted) {
|
||||
speed = -speed;
|
||||
}
|
||||
m_pwm.SetSpeed(speed);
|
||||
SetSpeed(speed);
|
||||
|
||||
for (auto& follower : m_nonowningFollowers) {
|
||||
follower->Set(speed);
|
||||
@@ -36,7 +36,7 @@ void PWMMotorController::SetVoltage(units::volt_t output) {
|
||||
}
|
||||
|
||||
double PWMMotorController::Get() const {
|
||||
return m_pwm.GetSpeed() * (m_isInverted ? -1.0 : 1.0);
|
||||
return GetSpeed() * (m_isInverted ? -1.0 : 1.0);
|
||||
}
|
||||
|
||||
units::volt_t PWMMotorController::GetVoltage() const {
|
||||
@@ -64,7 +64,11 @@ void PWMMotorController::Disable() {
|
||||
|
||||
void PWMMotorController::StopMotor() {
|
||||
// Don't use Set(0) as that will feed the watch kitty
|
||||
m_pwm.SetSpeed(0);
|
||||
m_pwm.SetPulseTime(0_us);
|
||||
|
||||
if (m_simSpeed) {
|
||||
m_simSpeed.Set(0.0);
|
||||
}
|
||||
|
||||
for (auto& follower : m_nonowningFollowers) {
|
||||
follower->StopMotor();
|
||||
@@ -83,7 +87,7 @@ int PWMMotorController::GetChannel() const {
|
||||
}
|
||||
|
||||
void PWMMotorController::EnableDeadbandElimination(bool eliminateDeadband) {
|
||||
m_pwm.EnableDeadbandElimination(eliminateDeadband);
|
||||
m_eliminateDeadband = eliminateDeadband;
|
||||
}
|
||||
|
||||
void PWMMotorController::AddFollower(PWMMotorController& follower) {
|
||||
@@ -95,6 +99,12 @@ WPI_IGNORE_DEPRECATED
|
||||
PWMMotorController::PWMMotorController(std::string_view name, int channel)
|
||||
: m_pwm(channel, false) {
|
||||
wpi::SendableRegistry::Add(this, name, channel);
|
||||
|
||||
m_simDevice = hal::SimDevice{"PWMMotorController", channel};
|
||||
if (m_simDevice) {
|
||||
m_simSpeed = m_simDevice.CreateDouble("Speed", true, 0.0);
|
||||
m_pwm.SetSimDevice(m_simDevice);
|
||||
}
|
||||
}
|
||||
|
||||
WPI_UNIGNORE_DEPRECATED
|
||||
@@ -106,3 +116,86 @@ void PWMMotorController::InitSendable(wpi::SendableBuilder& builder) {
|
||||
"Value", [=, this] { return Get(); },
|
||||
[=, this](double value) { Set(value); });
|
||||
}
|
||||
|
||||
units::microsecond_t PWMMotorController::GetMinPositivePwm() const {
|
||||
if (m_eliminateDeadband) {
|
||||
return m_deadbandMaxPwm;
|
||||
} else {
|
||||
return m_centerPwm + 1_us;
|
||||
}
|
||||
}
|
||||
|
||||
units::microsecond_t PWMMotorController::GetMaxNegativePwm() const {
|
||||
if (m_eliminateDeadband) {
|
||||
return m_deadbandMinPwm;
|
||||
} else {
|
||||
return m_centerPwm - 1_us;
|
||||
}
|
||||
}
|
||||
|
||||
units::microsecond_t PWMMotorController::GetPositiveScaleFactor() const {
|
||||
return m_maxPwm - GetMinPositivePwm();
|
||||
}
|
||||
|
||||
units::microsecond_t PWMMotorController::GetNegativeScaleFactor() const {
|
||||
return GetMaxNegativePwm() - m_minPwm;
|
||||
}
|
||||
|
||||
void PWMMotorController::SetSpeed(double speed) {
|
||||
if (std::isfinite(speed)) {
|
||||
speed = std::clamp(speed, -1.0, 1.0);
|
||||
} else {
|
||||
speed = 0.0;
|
||||
}
|
||||
|
||||
if (m_simSpeed) {
|
||||
m_simSpeed.Set(speed);
|
||||
}
|
||||
|
||||
units::microsecond_t rawValue;
|
||||
if (speed == 0.0) {
|
||||
rawValue = m_centerPwm;
|
||||
} else if (speed > 0.0) {
|
||||
rawValue = units::microsecond_t{static_cast<double>(std::lround(
|
||||
(speed * GetPositiveScaleFactor()).to<double>()))} +
|
||||
GetMinPositivePwm();
|
||||
} else {
|
||||
rawValue = units::microsecond_t{static_cast<double>(std::lround(
|
||||
(speed * GetNegativeScaleFactor()).to<double>()))} +
|
||||
GetMaxNegativePwm();
|
||||
}
|
||||
|
||||
m_pwm.SetPulseTime(rawValue);
|
||||
}
|
||||
|
||||
double PWMMotorController::GetSpeed() const {
|
||||
units::microsecond_t rawValue = m_pwm.GetPulseTime();
|
||||
|
||||
if (rawValue == 0_us) {
|
||||
return 0.0;
|
||||
} else if (rawValue > m_maxPwm) {
|
||||
return 1.0;
|
||||
} else if (rawValue < m_minPwm) {
|
||||
return -1.0;
|
||||
} else if (rawValue > GetMinPositivePwm()) {
|
||||
return ((rawValue - GetMinPositivePwm()) / GetPositiveScaleFactor())
|
||||
.to<double>();
|
||||
} else if (rawValue < GetMaxNegativePwm()) {
|
||||
return ((rawValue - GetMaxNegativePwm()) / GetNegativeScaleFactor())
|
||||
.to<double>();
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void PWMMotorController::SetBounds(units::microsecond_t maxPwm,
|
||||
units::microsecond_t deadbandMaxPwm,
|
||||
units::microsecond_t centerPwm,
|
||||
units::microsecond_t deadbandMinPwm,
|
||||
units::microsecond_t minPwm) {
|
||||
m_maxPwm = maxPwm;
|
||||
m_deadbandMaxPwm = deadbandMaxPwm;
|
||||
m_centerPwm = centerPwm;
|
||||
m_deadbandMinPwm = deadbandMinPwm;
|
||||
m_minPwm = minPwm;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// 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.
|
||||
|
||||
#include "frc/simulation/PWMMotorControllerSim.h"
|
||||
|
||||
#include <hal/SimDevice.h>
|
||||
#include <units/length.h>
|
||||
|
||||
#include "frc/simulation/SimDeviceSim.h"
|
||||
|
||||
using namespace frc;
|
||||
using namespace frc::sim;
|
||||
|
||||
PWMMotorControllerSim::PWMMotorControllerSim(
|
||||
const PWMMotorController& motorctrl)
|
||||
: PWMMotorControllerSim(motorctrl.GetChannel()) {}
|
||||
|
||||
PWMMotorControllerSim::PWMMotorControllerSim(int channel) {
|
||||
frc::sim::SimDeviceSim deviceSim{"PWMMotorController", channel};
|
||||
m_simSpeed = deviceSim.GetDouble("Speed");
|
||||
}
|
||||
|
||||
double PWMMotorControllerSim::GetSpeed() const {
|
||||
return m_simSpeed.Get();
|
||||
}
|
||||
@@ -16,9 +16,6 @@ using namespace frc::sim;
|
||||
|
||||
PWMSim::PWMSim(const PWM& pwm) : m_index{pwm.GetChannel()} {}
|
||||
|
||||
PWMSim::PWMSim(const PWMMotorController& motorctrl)
|
||||
: m_index{motorctrl.GetChannel()} {}
|
||||
|
||||
PWMSim::PWMSim(int channel) : m_index{channel} {}
|
||||
|
||||
std::unique_ptr<CallbackStore> PWMSim::RegisterInitializedCallback(
|
||||
@@ -55,72 +52,21 @@ void PWMSim::SetPulseMicrosecond(int32_t microsecondPulseTime) {
|
||||
HALSIM_SetPWMPulseMicrosecond(m_index, microsecondPulseTime);
|
||||
}
|
||||
|
||||
std::unique_ptr<CallbackStore> PWMSim::RegisterSpeedCallback(
|
||||
NotifyCallback callback, bool initialNotify) {
|
||||
auto store = std::make_unique<CallbackStore>(m_index, -1, callback,
|
||||
&HALSIM_CancelPWMSpeedCallback);
|
||||
store->SetUid(HALSIM_RegisterPWMSpeedCallback(m_index, &CallbackStoreThunk,
|
||||
store.get(), initialNotify));
|
||||
return store;
|
||||
}
|
||||
|
||||
double PWMSim::GetSpeed() const {
|
||||
return HALSIM_GetPWMSpeed(m_index);
|
||||
}
|
||||
|
||||
void PWMSim::SetSpeed(double speed) {
|
||||
HALSIM_SetPWMSpeed(m_index, speed);
|
||||
}
|
||||
|
||||
std::unique_ptr<CallbackStore> PWMSim::RegisterPositionCallback(
|
||||
std::unique_ptr<CallbackStore> PWMSim::RegisterOutputPeriodCallback(
|
||||
NotifyCallback callback, bool initialNotify) {
|
||||
auto store = std::make_unique<CallbackStore>(
|
||||
m_index, -1, callback, &HALSIM_CancelPWMPositionCallback);
|
||||
store->SetUid(HALSIM_RegisterPWMPositionCallback(m_index, &CallbackStoreThunk,
|
||||
store.get(), initialNotify));
|
||||
return store;
|
||||
}
|
||||
|
||||
double PWMSim::GetPosition() const {
|
||||
return HALSIM_GetPWMPosition(m_index);
|
||||
}
|
||||
|
||||
void PWMSim::SetPosition(double position) {
|
||||
HALSIM_SetPWMPosition(m_index, position);
|
||||
}
|
||||
|
||||
std::unique_ptr<CallbackStore> PWMSim::RegisterPeriodScaleCallback(
|
||||
NotifyCallback callback, bool initialNotify) {
|
||||
auto store = std::make_unique<CallbackStore>(
|
||||
m_index, -1, callback, &HALSIM_CancelPWMPeriodScaleCallback);
|
||||
store->SetUid(HALSIM_RegisterPWMPeriodScaleCallback(
|
||||
m_index, -1, callback, &HALSIM_CancelPWMOutputPeriodCallback);
|
||||
store->SetUid(HALSIM_RegisterPWMOutputPeriodCallback(
|
||||
m_index, &CallbackStoreThunk, store.get(), initialNotify));
|
||||
return store;
|
||||
}
|
||||
|
||||
int PWMSim::GetPeriodScale() const {
|
||||
return HALSIM_GetPWMPeriodScale(m_index);
|
||||
int PWMSim::GetOutputPeriod() const {
|
||||
return HALSIM_GetPWMOutputPeriod(m_index);
|
||||
}
|
||||
|
||||
void PWMSim::SetPeriodScale(int periodScale) {
|
||||
HALSIM_SetPWMPeriodScale(m_index, periodScale);
|
||||
}
|
||||
|
||||
std::unique_ptr<CallbackStore> PWMSim::RegisterZeroLatchCallback(
|
||||
NotifyCallback callback, bool initialNotify) {
|
||||
auto store = std::make_unique<CallbackStore>(
|
||||
m_index, -1, callback, &HALSIM_CancelPWMZeroLatchCallback);
|
||||
store->SetUid(HALSIM_RegisterPWMZeroLatchCallback(
|
||||
m_index, &CallbackStoreThunk, store.get(), initialNotify));
|
||||
return store;
|
||||
}
|
||||
|
||||
bool PWMSim::GetZeroLatch() const {
|
||||
return HALSIM_GetPWMZeroLatch(m_index);
|
||||
}
|
||||
|
||||
void PWMSim::SetZeroLatch(bool zeroLatch) {
|
||||
HALSIM_SetPWMZeroLatch(m_index, zeroLatch);
|
||||
void PWMSim::SetOutputPeriod(int period) {
|
||||
HALSIM_SetPWMOutputPeriod(m_index, period);
|
||||
}
|
||||
|
||||
void PWMSim::ResetData() {
|
||||
|
||||
28
wpilibc/src/main/native/cpp/simulation/ServoSim.cpp
Normal file
28
wpilibc/src/main/native/cpp/simulation/ServoSim.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
#include "frc/simulation/ServoSim.h"
|
||||
|
||||
#include <hal/SimDevice.h>
|
||||
#include <units/length.h>
|
||||
|
||||
#include "frc/simulation/SimDeviceSim.h"
|
||||
|
||||
using namespace frc;
|
||||
using namespace frc::sim;
|
||||
|
||||
ServoSim::ServoSim(const Servo& servo) : ServoSim(servo.GetChannel()) {}
|
||||
|
||||
ServoSim::ServoSim(int channel) {
|
||||
frc::sim::SimDeviceSim deviceSim{"Servo", channel};
|
||||
m_simPosition = deviceSim.GetDouble("Position");
|
||||
}
|
||||
|
||||
double ServoSim::GetPosition() const {
|
||||
return m_simPosition.Get();
|
||||
}
|
||||
|
||||
double ServoSim::GetAngle() const {
|
||||
return GetPosition() * Servo::GetServoAngleRange() + Servo::kMinServoAngle;
|
||||
}
|
||||
@@ -27,21 +27,21 @@ class PWM : public wpi::Sendable, public wpi::SendableHelper<PWM> {
|
||||
public:
|
||||
friend class AddressableLED;
|
||||
/**
|
||||
* Represents the amount to multiply the minimum servo-pulse pwm period by.
|
||||
* Represents the output period in microseconds.
|
||||
*/
|
||||
enum PeriodMultiplier {
|
||||
enum OutputPeriod {
|
||||
/**
|
||||
* Don't skip pulses. PWM pulses occur every 5.05 ms
|
||||
* PWM pulses occur every 5 ms
|
||||
*/
|
||||
kPeriodMultiplier_1X = 1,
|
||||
kOutputPeriod_5Ms = 1,
|
||||
/**
|
||||
* Skip every other pulse. PWM pulses occur every 10.10 ms
|
||||
* PWM pulses occur every 10 ms
|
||||
*/
|
||||
kPeriodMultiplier_2X = 2,
|
||||
kOutputPeriod_10Ms = 2,
|
||||
/**
|
||||
* Skip three out of four pulses. PWM pulses occur every 20.20 ms
|
||||
* PWM pulses occur every 20 ms
|
||||
*/
|
||||
kPeriodMultiplier_4X = 4
|
||||
kOutputPeriod_20Ms = 4
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -74,7 +74,7 @@ class PWM : public wpi::Sendable, public wpi::SendableHelper<PWM> {
|
||||
*
|
||||
* @param time Microsecond PWM value.
|
||||
*/
|
||||
virtual void SetPulseTime(units::microsecond_t time);
|
||||
void SetPulseTime(units::microsecond_t time);
|
||||
|
||||
/**
|
||||
* Get the PWM pulse time directly from the hardware.
|
||||
@@ -83,122 +83,30 @@ class PWM : public wpi::Sendable, public wpi::SendableHelper<PWM> {
|
||||
*
|
||||
* @return Microsecond PWM control value.
|
||||
*/
|
||||
virtual units::microsecond_t GetPulseTime() const;
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a position.
|
||||
*
|
||||
* This is intended to be used by servos.
|
||||
*
|
||||
* @pre SetBounds() called.
|
||||
*
|
||||
* @param pos The position to set the servo between 0.0 and 1.0.
|
||||
*/
|
||||
virtual void SetPosition(double pos);
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of a position.
|
||||
*
|
||||
* This is intended to be used by servos.
|
||||
*
|
||||
* @pre SetBounds() called.
|
||||
*
|
||||
* @return The position the servo is set to between 0.0 and 1.0.
|
||||
*/
|
||||
virtual double GetPosition() const;
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a speed.
|
||||
*
|
||||
* This is intended to be used by motor controllers.
|
||||
*
|
||||
* @pre SetBounds() called.
|
||||
*
|
||||
* @param speed The speed to set the motor controller between -1.0 and 1.0.
|
||||
*/
|
||||
virtual void SetSpeed(double speed);
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of speed.
|
||||
*
|
||||
* This is intended to be used by motor controllers.
|
||||
*
|
||||
* @pre SetBounds() called.
|
||||
*
|
||||
* @return The most recently set speed between -1.0 and 1.0.
|
||||
*/
|
||||
virtual double GetSpeed() const;
|
||||
units::microsecond_t GetPulseTime() const;
|
||||
|
||||
/**
|
||||
* Temporarily disables the PWM output. The next set call will re-enable
|
||||
* the output.
|
||||
*/
|
||||
virtual void SetDisabled();
|
||||
void SetDisabled();
|
||||
|
||||
/**
|
||||
* Slow down the PWM signal for old devices.
|
||||
* Sets the PWM output period.
|
||||
*
|
||||
* @param mult The period multiplier to apply to this channel
|
||||
* @param mult The output period to apply to this channel
|
||||
*/
|
||||
void SetPeriodMultiplier(PeriodMultiplier mult);
|
||||
|
||||
/**
|
||||
* Latches PWM to zero.
|
||||
*/
|
||||
void SetZeroLatch();
|
||||
|
||||
/**
|
||||
* Optionally eliminate the deadband from a motor controller.
|
||||
*
|
||||
* @param eliminateDeadband If true, set the motor curve on the motor
|
||||
* controller to eliminate the deadband in the middle
|
||||
* of the range. Otherwise, keep the full range
|
||||
* without modifying any values.
|
||||
*/
|
||||
void EnableDeadbandElimination(bool eliminateDeadband);
|
||||
|
||||
/**
|
||||
* Set the bounds on the PWM pulse widths.
|
||||
*
|
||||
* This sets the bounds on the PWM values for a particular type of controller.
|
||||
* The values determine the upper and lower speeds as well as the deadband
|
||||
* bracket.
|
||||
*
|
||||
* @param max The max PWM pulse width in us
|
||||
* @param deadbandMax The high end of the deadband range pulse width in us
|
||||
* @param center The center (off) pulse width in us
|
||||
* @param deadbandMin The low end of the deadband pulse width in us
|
||||
* @param min The minimum pulse width in us
|
||||
*/
|
||||
void SetBounds(units::microsecond_t max, units::microsecond_t deadbandMax,
|
||||
units::microsecond_t center, units::microsecond_t deadbandMin,
|
||||
units::microsecond_t min);
|
||||
|
||||
/**
|
||||
* Get the bounds on the PWM values.
|
||||
*
|
||||
* This gets the bounds on the PWM values for a particular each type of
|
||||
* controller. The values determine the upper and lower speeds as well as the
|
||||
* deadband bracket.
|
||||
*
|
||||
* @param max The maximum pwm value
|
||||
* @param deadbandMax The high end of the deadband range
|
||||
* @param center The center speed (off)
|
||||
* @param deadbandMin The low end of the deadband range
|
||||
* @param min The minimum pwm value
|
||||
*/
|
||||
void GetBounds(units::microsecond_t* max, units::microsecond_t* deadbandMax,
|
||||
units::microsecond_t* center,
|
||||
units::microsecond_t* deadbandMin, units::microsecond_t* min);
|
||||
|
||||
/**
|
||||
* Sets the PWM output to be a continuous high signal while enabled.
|
||||
*
|
||||
*/
|
||||
void SetAlwaysHighMode();
|
||||
void SetOutputPeriod(OutputPeriod mult);
|
||||
|
||||
int GetChannel() const;
|
||||
|
||||
/**
|
||||
* Indicates this input is used by a simulated device.
|
||||
*
|
||||
* @param device simulated device handle
|
||||
*/
|
||||
void SetSimDevice(HAL_SimDeviceHandle device);
|
||||
|
||||
protected:
|
||||
void InitSendable(wpi::SendableBuilder& builder) override;
|
||||
|
||||
|
||||
@@ -4,20 +4,27 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hal/SimDevice.h>
|
||||
#include <units/angle.h>
|
||||
|
||||
#include "frc/PWM.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
namespace sim {
|
||||
class ServoSim;
|
||||
} // namespace sim
|
||||
|
||||
/**
|
||||
* Standard hobby style servo.
|
||||
*
|
||||
* The range parameters default to the appropriate values for the Hitec HS-322HD
|
||||
* servo provided in the FIRST Kit of Parts in 2008.
|
||||
*/
|
||||
class Servo : public PWM {
|
||||
class Servo : public wpi::Sendable, public wpi::SendableHelper<Servo> {
|
||||
public:
|
||||
friend class frc::sim::ServoSim;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -42,13 +49,6 @@ class Servo : public PWM {
|
||||
*/
|
||||
void Set(double value);
|
||||
|
||||
/**
|
||||
* Set the servo to offline.
|
||||
*
|
||||
* Set the servo raw value to 0 (undriven)
|
||||
*/
|
||||
void SetOffline();
|
||||
|
||||
/**
|
||||
* Get the servo position.
|
||||
*
|
||||
@@ -86,30 +86,27 @@ class Servo : public PWM {
|
||||
*/
|
||||
double GetAngle() const;
|
||||
|
||||
/**
|
||||
* Get the maximum angle of the servo.
|
||||
*
|
||||
* @return The maximum angle of the servo in degrees.
|
||||
*/
|
||||
double GetMaxAngle() const;
|
||||
|
||||
/**
|
||||
* Get the minimum angle of the servo.
|
||||
*
|
||||
* @return The minimum angle of the servo in degrees.
|
||||
*/
|
||||
double GetMinAngle() const;
|
||||
int GetChannel() const;
|
||||
|
||||
void InitSendable(wpi::SendableBuilder& builder) override;
|
||||
|
||||
private:
|
||||
double GetServoAngleRange() const;
|
||||
static double GetServoAngleRange();
|
||||
units::microsecond_t GetFullRangeScaleFactor() const;
|
||||
|
||||
static constexpr double kMaxServoAngle = 180.;
|
||||
static constexpr double kMaxServoAngle = 180.0;
|
||||
static constexpr double kMinServoAngle = 0.0;
|
||||
|
||||
static constexpr units::millisecond_t kDefaultMaxServoPWM = 2.4_ms;
|
||||
static constexpr units::millisecond_t kDefaultMinServoPWM = 0.6_ms;
|
||||
|
||||
units::millisecond_t m_maxPwm = kDefaultMaxServoPWM;
|
||||
units::millisecond_t m_minPwm = kDefaultMinServoPWM;
|
||||
|
||||
hal::SimDevice m_simDevice;
|
||||
hal::SimDouble m_simPosition;
|
||||
|
||||
PWM m_pwm;
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <hal/SimDevice.h>
|
||||
#include <units/voltage.h>
|
||||
#include <wpi/deprecated.h>
|
||||
#include <wpi/sendable/Sendable.h>
|
||||
@@ -133,11 +134,35 @@ class PWMMotorController : public MotorController,
|
||||
/// PWM instances for motor controller.
|
||||
PWM m_pwm;
|
||||
|
||||
void SetSpeed(double speed);
|
||||
double GetSpeed() const;
|
||||
|
||||
void SetBounds(units::microsecond_t maxPwm,
|
||||
units::microsecond_t deadbandMaxPwm,
|
||||
units::microsecond_t centerPwm,
|
||||
units::microsecond_t deadbandMinPwm,
|
||||
units::microsecond_t minPwm);
|
||||
|
||||
private:
|
||||
bool m_isInverted = false;
|
||||
std::vector<PWMMotorController*> m_nonowningFollowers;
|
||||
std::vector<std::unique_ptr<PWMMotorController>> m_owningFollowers;
|
||||
|
||||
hal::SimDevice m_simDevice;
|
||||
hal::SimDouble m_simSpeed;
|
||||
|
||||
bool m_eliminateDeadband{0};
|
||||
units::microsecond_t m_minPwm{0};
|
||||
units::microsecond_t m_deadbandMinPwm{0};
|
||||
units::microsecond_t m_centerPwm{0};
|
||||
units::microsecond_t m_deadbandMaxPwm{0};
|
||||
units::microsecond_t m_maxPwm{0};
|
||||
|
||||
units::microsecond_t GetMinPositivePwm() const;
|
||||
units::microsecond_t GetMaxNegativePwm() const;
|
||||
units::microsecond_t GetPositiveScaleFactor() const;
|
||||
units::microsecond_t GetNegativeScaleFactor() const;
|
||||
|
||||
PWM* GetPwm() { return &m_pwm; }
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hal/SimDevice.h>
|
||||
#include <units/length.h>
|
||||
|
||||
#include "frc/motorcontrol/PWMMotorController.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
class PWMMotorController;
|
||||
|
||||
namespace sim {
|
||||
|
||||
class PWMMotorControllerSim {
|
||||
public:
|
||||
explicit PWMMotorControllerSim(const PWMMotorController& motorctrl);
|
||||
|
||||
explicit PWMMotorControllerSim(int channel);
|
||||
|
||||
double GetSpeed() const;
|
||||
|
||||
private:
|
||||
hal::SimDouble m_simSpeed;
|
||||
};
|
||||
} // namespace sim
|
||||
} // namespace frc
|
||||
@@ -27,13 +27,6 @@ class PWMSim {
|
||||
*/
|
||||
explicit PWMSim(const PWM& pwm);
|
||||
|
||||
/**
|
||||
* Constructs from a PWMMotorController object.
|
||||
*
|
||||
* @param motorctrl PWMMotorController to simulate
|
||||
*/
|
||||
explicit PWMSim(const PWMMotorController& motorctrl);
|
||||
|
||||
/**
|
||||
* Constructs from a PWM channel number.
|
||||
*
|
||||
@@ -91,56 +84,6 @@ class PWMSim {
|
||||
*/
|
||||
void SetPulseMicrosecond(int32_t microsecondPulseTime);
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the PWM speed changes.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether to run the callback with the initial value
|
||||
* @return the CallbackStore object associated with this callback
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::unique_ptr<CallbackStore> RegisterSpeedCallback(NotifyCallback callback,
|
||||
bool initialNotify);
|
||||
|
||||
/**
|
||||
* Get the PWM speed.
|
||||
*
|
||||
* @return the PWM speed (-1.0 to 1.0)
|
||||
*/
|
||||
double GetSpeed() const;
|
||||
|
||||
/**
|
||||
* Set the PWM speed.
|
||||
*
|
||||
* @param speed the PWM speed (-1.0 to 1.0)
|
||||
*/
|
||||
void SetSpeed(double speed);
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the PWM position changes.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether to run the callback with the initial value
|
||||
* @return the CallbackStore object associated with this callback
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::unique_ptr<CallbackStore> RegisterPositionCallback(
|
||||
NotifyCallback callback, bool initialNotify);
|
||||
|
||||
/**
|
||||
* Get the PWM position.
|
||||
*
|
||||
* @return the PWM position (0.0 to 1.0)
|
||||
*/
|
||||
double GetPosition() const;
|
||||
|
||||
/**
|
||||
* Set the PWM position.
|
||||
*
|
||||
* @param position the PWM position (0.0 to 1.0)
|
||||
*/
|
||||
void SetPosition(double position);
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the PWM period scale changes.
|
||||
*
|
||||
@@ -149,7 +92,7 @@ class PWMSim {
|
||||
* @return the CallbackStore object associated with this callback
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::unique_ptr<CallbackStore> RegisterPeriodScaleCallback(
|
||||
std::unique_ptr<CallbackStore> RegisterOutputPeriodCallback(
|
||||
NotifyCallback callback, bool initialNotify);
|
||||
|
||||
/**
|
||||
@@ -157,39 +100,14 @@ class PWMSim {
|
||||
*
|
||||
* @return the PWM period scale
|
||||
*/
|
||||
int GetPeriodScale() const;
|
||||
int GetOutputPeriod() const;
|
||||
|
||||
/**
|
||||
* Set the PWM period scale.
|
||||
*
|
||||
* @param periodScale the PWM period scale
|
||||
* @param period the PWM period scale
|
||||
*/
|
||||
void SetPeriodScale(int periodScale);
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the PWM zero latch state changes.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether to run the callback with the initial state
|
||||
* @return the CallbackStore object associated with this callback
|
||||
*/
|
||||
[[nodiscard]]
|
||||
std::unique_ptr<CallbackStore> RegisterZeroLatchCallback(
|
||||
NotifyCallback callback, bool initialNotify);
|
||||
|
||||
/**
|
||||
* Check whether the PWM is zero latched.
|
||||
*
|
||||
* @return true if zero latched
|
||||
*/
|
||||
bool GetZeroLatch() const;
|
||||
|
||||
/**
|
||||
* Define whether the PWM has been zero latched.
|
||||
*
|
||||
* @param zeroLatch true to indicate zero latched
|
||||
*/
|
||||
void SetZeroLatch(bool zeroLatch);
|
||||
void SetOutputPeriod(int period);
|
||||
|
||||
/**
|
||||
* Reset all simulation data.
|
||||
|
||||
31
wpilibc/src/main/native/include/frc/simulation/ServoSim.h
Normal file
31
wpilibc/src/main/native/include/frc/simulation/ServoSim.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hal/SimDevice.h>
|
||||
#include <units/length.h>
|
||||
|
||||
#include "frc/Servo.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
class Servo;
|
||||
|
||||
namespace sim {
|
||||
class ServoSim {
|
||||
public:
|
||||
explicit ServoSim(const Servo& servo);
|
||||
|
||||
explicit ServoSim(int channel);
|
||||
|
||||
double GetPosition() const;
|
||||
|
||||
double GetAngle() const;
|
||||
|
||||
private:
|
||||
hal::SimDouble m_simPosition;
|
||||
};
|
||||
} // namespace sim
|
||||
} // namespace frc
|
||||
@@ -0,0 +1,26 @@
|
||||
// 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.
|
||||
|
||||
#include "frc/simulation/PWMMotorControllerSim.h" // NOLINT(build/include_order)
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/HAL.h>
|
||||
|
||||
#include "frc/motorcontrol/Spark.h"
|
||||
|
||||
namespace frc::sim {
|
||||
TEST(PWMMotorControllerSimTest, TestMotor) {
|
||||
frc::Spark spark{0};
|
||||
frc::sim::PWMMotorControllerSim sim{spark};
|
||||
|
||||
spark.Set(0);
|
||||
EXPECT_EQ(0, sim.GetSpeed());
|
||||
|
||||
spark.Set(0.354);
|
||||
EXPECT_EQ(0.354, sim.GetSpeed());
|
||||
|
||||
spark.Set(-0.785);
|
||||
EXPECT_EQ(-0.785, sim.GetSpeed());
|
||||
}
|
||||
} // namespace frc::sim
|
||||
@@ -12,8 +12,6 @@
|
||||
|
||||
namespace frc::sim {
|
||||
|
||||
constexpr double kPWMStepSize = 1.0 / 2000.0;
|
||||
|
||||
TEST(PWMSimTest, Initialize) {
|
||||
HAL_Initialize(500, 0);
|
||||
|
||||
@@ -46,115 +44,7 @@ TEST(PWMSimTest, SetPulseTime) {
|
||||
EXPECT_EQ(2290, callback.GetLastValue());
|
||||
}
|
||||
|
||||
TEST(PWMSimTest, SetSpeed) {
|
||||
HAL_Initialize(500, 0);
|
||||
|
||||
PWMSim sim{0};
|
||||
sim.ResetData();
|
||||
EXPECT_FALSE(sim.GetInitialized());
|
||||
|
||||
DoubleCallback callback;
|
||||
|
||||
auto cb = sim.RegisterSpeedCallback(callback.GetCallback(), false);
|
||||
PWM pwm{0};
|
||||
double kTestValue = 0.3504;
|
||||
pwm.SetSpeed(kTestValue);
|
||||
|
||||
EXPECT_NEAR(kTestValue, sim.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_TRUE(callback.WasTriggered());
|
||||
EXPECT_NEAR(kTestValue, callback.GetLastValue(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue / 2 + 0.5, sim.GetPosition(), kPWMStepSize * 2);
|
||||
EXPECT_NEAR(kTestValue / 2 + 0.5, pwm.GetPosition(), kPWMStepSize * 2);
|
||||
|
||||
kTestValue = -1.0;
|
||||
pwm.SetSpeed(kTestValue);
|
||||
|
||||
EXPECT_NEAR(kTestValue, sim.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(0.0, sim.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(0.0, pwm.GetPosition(), kPWMStepSize);
|
||||
|
||||
kTestValue = 0.0;
|
||||
pwm.SetSpeed(kTestValue);
|
||||
|
||||
EXPECT_NEAR(kTestValue, sim.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(0.5, sim.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(0.5, pwm.GetPosition(), kPWMStepSize);
|
||||
|
||||
kTestValue = 1.0;
|
||||
pwm.SetSpeed(kTestValue);
|
||||
|
||||
EXPECT_NEAR(kTestValue, sim.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, sim.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetPosition(), kPWMStepSize);
|
||||
|
||||
kTestValue = 1.1;
|
||||
pwm.SetSpeed(kTestValue);
|
||||
|
||||
EXPECT_NEAR(1.0, sim.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(1.0, pwm.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(1.0, sim.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(1.0, pwm.GetPosition(), kPWMStepSize);
|
||||
}
|
||||
|
||||
TEST(PWMSimTest, SetPosition) {
|
||||
HAL_Initialize(500, 0);
|
||||
|
||||
PWMSim sim{0};
|
||||
sim.ResetData();
|
||||
EXPECT_FALSE(sim.GetInitialized());
|
||||
|
||||
DoubleCallback callback;
|
||||
|
||||
auto cb = sim.RegisterPositionCallback(callback.GetCallback(), false);
|
||||
PWM pwm{0};
|
||||
double kTestValue = 0.3504;
|
||||
pwm.SetPosition(kTestValue);
|
||||
|
||||
EXPECT_NEAR(kTestValue, sim.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetPosition(), kPWMStepSize);
|
||||
EXPECT_TRUE(callback.WasTriggered());
|
||||
EXPECT_NEAR(kTestValue, callback.GetLastValue(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue * 2 - 1.0, sim.GetSpeed(), kPWMStepSize * 2);
|
||||
EXPECT_NEAR(kTestValue * 2 - 1.0, pwm.GetSpeed(), kPWMStepSize * 2);
|
||||
|
||||
kTestValue = -1.0;
|
||||
pwm.SetPosition(kTestValue);
|
||||
|
||||
EXPECT_NEAR(0.0, sim.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(0.0, pwm.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, sim.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetSpeed(), kPWMStepSize);
|
||||
|
||||
kTestValue = 0.0;
|
||||
pwm.SetPosition(kTestValue);
|
||||
|
||||
EXPECT_NEAR(kTestValue, sim.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(-1.0, sim.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(-1.0, pwm.GetSpeed(), kPWMStepSize);
|
||||
|
||||
kTestValue = 1.0;
|
||||
pwm.SetPosition(kTestValue);
|
||||
|
||||
EXPECT_NEAR(kTestValue, sim.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, sim.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(kTestValue, pwm.GetSpeed(), kPWMStepSize);
|
||||
|
||||
kTestValue = 1.1;
|
||||
pwm.SetPosition(kTestValue);
|
||||
|
||||
EXPECT_NEAR(1.0, sim.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(1.0, pwm.GetPosition(), kPWMStepSize);
|
||||
EXPECT_NEAR(1.0, sim.GetSpeed(), kPWMStepSize);
|
||||
EXPECT_NEAR(1.0, pwm.GetSpeed(), kPWMStepSize);
|
||||
}
|
||||
|
||||
TEST(PWMSimTest, SetPeriodScale) {
|
||||
TEST(PWMSimTest, SetOutputPeriod) {
|
||||
HAL_Initialize(500, 0);
|
||||
|
||||
PWMSim sim{0};
|
||||
@@ -163,28 +53,12 @@ TEST(PWMSimTest, SetPeriodScale) {
|
||||
|
||||
IntCallback callback;
|
||||
|
||||
auto cb = sim.RegisterPeriodScaleCallback(callback.GetCallback(), false);
|
||||
auto cb = sim.RegisterOutputPeriodCallback(callback.GetCallback(), false);
|
||||
PWM pwm{0};
|
||||
sim.SetPeriodScale(3504);
|
||||
EXPECT_EQ(3504, sim.GetPeriodScale());
|
||||
sim.SetOutputPeriod(3504);
|
||||
EXPECT_EQ(3504, sim.GetOutputPeriod());
|
||||
EXPECT_TRUE(callback.WasTriggered());
|
||||
EXPECT_EQ(3504, callback.GetLastValue());
|
||||
}
|
||||
|
||||
TEST(PWMSimTest, SetZeroLatch) {
|
||||
HAL_Initialize(500, 0);
|
||||
|
||||
PWMSim sim{0};
|
||||
sim.ResetData();
|
||||
EXPECT_FALSE(sim.GetInitialized());
|
||||
|
||||
BooleanCallback callback;
|
||||
|
||||
auto cb = sim.RegisterZeroLatchCallback(callback.GetCallback(), false);
|
||||
PWM pwm{0};
|
||||
pwm.SetZeroLatch();
|
||||
|
||||
EXPECT_TRUE(callback.WasTriggered());
|
||||
}
|
||||
|
||||
} // namespace frc::sim
|
||||
|
||||
32
wpilibc/src/test/native/cpp/simulation/ServoSimTest.cpp
Normal file
32
wpilibc/src/test/native/cpp/simulation/ServoSimTest.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// 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.
|
||||
|
||||
#include "frc/simulation/ServoSim.h" // NOLINT(build/include_order)
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/HAL.h>
|
||||
|
||||
#include "frc/Servo.h"
|
||||
|
||||
namespace frc::sim {
|
||||
TEST(ServoSimTest, TestServo) {
|
||||
frc::Servo servo{0};
|
||||
frc::sim::ServoSim sim{servo};
|
||||
|
||||
servo.Set(0);
|
||||
EXPECT_EQ(0, sim.GetPosition());
|
||||
|
||||
servo.Set(0.354);
|
||||
EXPECT_EQ(0.354, sim.GetPosition());
|
||||
|
||||
servo.SetAngle(10);
|
||||
EXPECT_EQ(10, sim.GetAngle());
|
||||
|
||||
servo.SetAngle(90);
|
||||
EXPECT_EQ(90, sim.GetAngle());
|
||||
|
||||
servo.SetAngle(170);
|
||||
EXPECT_EQ(170, sim.GetAngle());
|
||||
}
|
||||
} // namespace frc::sim
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <frc/simulation/BatterySim.h>
|
||||
#include <frc/simulation/ElevatorSim.h>
|
||||
#include <frc/simulation/EncoderSim.h>
|
||||
#include <frc/simulation/PWMSim.h>
|
||||
#include <frc/simulation/PWMMotorControllerSim.h>
|
||||
#include <frc/simulation/RoboRioSim.h>
|
||||
#include <frc/smartdashboard/Mechanism2d.h>
|
||||
#include <frc/smartdashboard/MechanismLigament2d.h>
|
||||
@@ -50,7 +50,7 @@ class Elevator {
|
||||
frc::Encoder m_encoder{Constants::kEncoderAChannel,
|
||||
Constants::kEncoderBChannel};
|
||||
frc::PWMSparkMax m_motor{Constants::kMotorPort};
|
||||
frc::sim::PWMSim m_motorSim{m_motor};
|
||||
frc::sim::PWMMotorControllerSim m_motorSim{m_motor};
|
||||
|
||||
// Simulation classes help us simulate what's going on, including gravity.
|
||||
frc::sim::ElevatorSim m_elevatorSim{m_elevatorGearbox,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <frc/simulation/BatterySim.h>
|
||||
#include <frc/simulation/ElevatorSim.h>
|
||||
#include <frc/simulation/EncoderSim.h>
|
||||
#include <frc/simulation/PWMSim.h>
|
||||
#include <frc/simulation/PWMMotorControllerSim.h>
|
||||
#include <frc/simulation/RoboRioSim.h>
|
||||
#include <frc/smartdashboard/Mechanism2d.h>
|
||||
#include <frc/smartdashboard/MechanismLigament2d.h>
|
||||
@@ -46,7 +46,7 @@ class Elevator {
|
||||
frc::Encoder m_encoder{Constants::kEncoderAChannel,
|
||||
Constants::kEncoderBChannel};
|
||||
frc::PWMSparkMax m_motor{Constants::kMotorPort};
|
||||
frc::sim::PWMSim m_motorSim{m_motor};
|
||||
frc::sim::PWMMotorControllerSim m_motorSim{m_motor};
|
||||
|
||||
// Simulation classes help us simulate what's going on, including gravity.
|
||||
frc::sim::ElevatorSim m_elevatorSim{m_elevatorGearbox,
|
||||
|
||||
@@ -70,9 +70,6 @@ int main(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set PWM config to standard servo speeds
|
||||
HAL_SetPWMConfigMicroseconds(pwmPort, 2000, 1501, 1500, 1499, 1000, &status);
|
||||
|
||||
// Create an Input
|
||||
status = 0;
|
||||
HAL_DigitalHandle dio = HAL_InitializeDIOPort(2, 1, NULL, &status);
|
||||
@@ -105,9 +102,9 @@ int main(void) {
|
||||
case TeleopMode:
|
||||
status = 0;
|
||||
if (HAL_GetDIO(dio, &status)) {
|
||||
HAL_SetPWMSpeed(pwmPort, 1.0, &status);
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmPort, 2000, &status);
|
||||
} else {
|
||||
HAL_SetPWMSpeed(pwmPort, 0, &status);
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmPort, 1500, &status);
|
||||
}
|
||||
break;
|
||||
case AutoMode:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <frc/Preferences.h>
|
||||
#include <frc/simulation/DriverStationSim.h>
|
||||
#include <frc/simulation/JoystickSim.h>
|
||||
#include <frc/simulation/PWMSim.h>
|
||||
#include <frc/simulation/PWMMotorControllerSim.h>
|
||||
#include <frc/simulation/SimHooks.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/simulation/MockHooks.h>
|
||||
@@ -23,7 +23,7 @@ class ArmSimulationTest : public testing::TestWithParam<units::degree_t> {
|
||||
std::optional<std::thread> m_thread;
|
||||
|
||||
protected:
|
||||
frc::sim::PWMSim m_motorSim{kMotorPort};
|
||||
frc::sim::PWMMotorControllerSim m_motorSim{kMotorPort};
|
||||
frc::sim::EncoderSim m_encoderSim =
|
||||
frc::sim::EncoderSim::CreateForChannel(kEncoderAChannel);
|
||||
frc::sim::JoystickSim m_joystickSim{kJoystickPort};
|
||||
@@ -41,7 +41,6 @@ class ArmSimulationTest : public testing::TestWithParam<units::degree_t> {
|
||||
m_thread->join();
|
||||
|
||||
m_encoderSim.ResetData();
|
||||
m_motorSim.ResetData();
|
||||
frc::sim::DriverStationSim::ResetData();
|
||||
frc::Preferences::RemoveAll();
|
||||
}
|
||||
@@ -61,7 +60,6 @@ TEST_P(ArmSimulationTest, Teleop) {
|
||||
frc::sim::DriverStationSim::SetEnabled(true);
|
||||
frc::sim::DriverStationSim::NotifyNewData();
|
||||
|
||||
EXPECT_TRUE(m_motorSim.GetInitialized());
|
||||
EXPECT_TRUE(m_encoderSim.GetInitialized());
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include <frc/simulation/DriverStationSim.h>
|
||||
#include <frc/simulation/JoystickSim.h>
|
||||
#include <frc/simulation/PWMSim.h>
|
||||
#include <frc/simulation/PWMMotorControllerSim.h>
|
||||
#include <frc/simulation/SimHooks.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/simulation/MockHooks.h>
|
||||
@@ -25,7 +25,7 @@ class ElevatorSimulationTest : public testing::Test {
|
||||
std::optional<std::thread> m_thread;
|
||||
|
||||
protected:
|
||||
frc::sim::PWMSim m_motorSim{Constants::kMotorPort};
|
||||
frc::sim::PWMMotorControllerSim m_motorSim{Constants::kMotorPort};
|
||||
frc::sim::EncoderSim m_encoderSim =
|
||||
frc::sim::EncoderSim::CreateForChannel(Constants::kEncoderAChannel);
|
||||
frc::sim::JoystickSim m_joystickSim{Constants::kJoystickPort};
|
||||
@@ -43,7 +43,6 @@ class ElevatorSimulationTest : public testing::Test {
|
||||
m_thread->join();
|
||||
|
||||
m_encoderSim.ResetData();
|
||||
m_motorSim.ResetData();
|
||||
frc::sim::DriverStationSim::ResetData();
|
||||
}
|
||||
};
|
||||
@@ -55,7 +54,6 @@ TEST_F(ElevatorSimulationTest, Teleop) {
|
||||
frc::sim::DriverStationSim::SetEnabled(true);
|
||||
frc::sim::DriverStationSim::NotifyNewData();
|
||||
|
||||
EXPECT_TRUE(m_motorSim.GetInitialized());
|
||||
EXPECT_TRUE(m_encoderSim.GetInitialized());
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <frc/simulation/DriverStationSim.h>
|
||||
#include <frc/simulation/ElevatorSim.h>
|
||||
#include <frc/simulation/JoystickSim.h>
|
||||
#include <frc/simulation/PWMSim.h>
|
||||
#include <frc/simulation/PWMMotorControllerSim.h>
|
||||
#include <frc/simulation/SimHooks.h>
|
||||
#include <frc/system/plant/DCMotor.h>
|
||||
#include <gtest/gtest.h>
|
||||
@@ -39,7 +39,7 @@ class PotentiometerPIDTest : public testing::Test {
|
||||
Robot::kFullHeight,
|
||||
true,
|
||||
0.0_m};
|
||||
frc::sim::PWMSim m_motorSim{Robot::kMotorChannel};
|
||||
frc::sim::PWMMotorControllerSim m_motorSim{Robot::kMotorChannel};
|
||||
frc::sim::AnalogInputSim m_analogSim{Robot::kPotChannel};
|
||||
frc::sim::JoystickSim m_joystickSim{Robot::kJoystickChannel};
|
||||
int32_t m_callback;
|
||||
@@ -85,7 +85,6 @@ class PotentiometerPIDTest : public testing::Test {
|
||||
|
||||
HALSIM_CancelSimPeriodicBeforeCallback(m_callback);
|
||||
m_analogSim.ResetData();
|
||||
m_motorSim.ResetData();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -96,7 +95,6 @@ TEST_F(PotentiometerPIDTest, Teleop) {
|
||||
frc::sim::DriverStationSim::SetEnabled(true);
|
||||
frc::sim::DriverStationSim::NotifyNewData();
|
||||
|
||||
EXPECT_TRUE(m_motorSim.GetInitialized());
|
||||
EXPECT_TRUE(m_analogSim.GetInitialized());
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <frc/DoubleSolenoid.h>
|
||||
#include <frc/simulation/DoubleSolenoidSim.h>
|
||||
#include <frc/simulation/PWMSim.h>
|
||||
#include <frc/simulation/PWMMotorControllerSim.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "Constants.h"
|
||||
@@ -13,7 +13,7 @@
|
||||
class IntakeTest : public testing::Test {
|
||||
protected:
|
||||
Intake intake; // create our intake
|
||||
frc::sim::PWMSim simMotor{
|
||||
frc::sim::PWMMotorControllerSim simMotor{
|
||||
IntakeConstants::kMotorPort}; // create our simulation PWM
|
||||
frc::sim::DoubleSolenoidSim simPiston{
|
||||
frc::PneumaticsModuleType::CTREPCM, IntakeConstants::kPistonFwdChannel,
|
||||
|
||||
@@ -37,10 +37,9 @@ public class {{ name }} extends PWMMotorController {
|
||||
public {{ name }}(final int channel) {
|
||||
super("{{ name }}", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds({{ (pulse_width_ms.max * 1000) | int }}, {{ (pulse_width_ms.deadbandMax * 1000) | int }}, {{ (pulse_width_ms.center * 1000) | int }}, {{ (pulse_width_ms.deadbandMin * 1000) | int }}, {{ (pulse_width_ms.min * 1000) | int }});
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k{{ PeriodMultiplier | default("1", true)}}X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds({{ (pulse_width_ms.max * 1000) | int }}, {{ (pulse_width_ms.deadbandMax * 1000) | int }}, {{ (pulse_width_ms.center * 1000) | int }}, {{ (pulse_width_ms.deadbandMin * 1000) | int }}, {{ (pulse_width_ms.min * 1000) | int }});
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k{{ OutputPeriod | default("5", true)}}Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "{{ ResourceName }}");
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
"Manufacturer": "Vex Robotics",
|
||||
"DisplayName": "Victor 888",
|
||||
"ResourceName": "Victor",
|
||||
"PeriodMultiplier": 2,
|
||||
"OutputPeriod": 10,
|
||||
"pulse_width_ms": {
|
||||
"max": 2.027,
|
||||
"deadbandMax": 1.525,
|
||||
@@ -174,7 +174,7 @@
|
||||
"Manufacturer": "AndyMark",
|
||||
"DisplayName": "Koors40",
|
||||
"ResourceName": "Koors40",
|
||||
"PeriodMultiplier": 4,
|
||||
"OutputPeriod": 20,
|
||||
"pulse_width_ms": {
|
||||
"max": 2.004,
|
||||
"deadbandMax": 1.520,
|
||||
|
||||
@@ -37,10 +37,9 @@ public class DMC60 extends PWMMotorController {
|
||||
public DMC60(final int channel) {
|
||||
super("DMC60", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "DigilentDMC60");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class Jaguar extends PWMMotorController {
|
||||
public Jaguar(final int channel) {
|
||||
super("Jaguar", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2310, 1550, 1507, 1454, 697);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2310, 1550, 1507, 1454, 697);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "Jaguar");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class Koors40 extends PWMMotorController {
|
||||
public Koors40(final int channel) {
|
||||
super("Koors40", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k4X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k20Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "Koors40");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class PWMSparkFlex extends PWMMotorController {
|
||||
public PWMSparkFlex(final int channel) {
|
||||
super("PWMSparkFlex", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2003, 1550, 1500, 1460, 999);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2003, 1550, 1500, 1460, 999);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "RevSparkFlexPWM");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class PWMSparkMax extends PWMMotorController {
|
||||
public PWMSparkMax(final int channel) {
|
||||
super("PWMSparkMax", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2003, 1550, 1500, 1460, 999);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2003, 1550, 1500, 1460, 999);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "RevSparkMaxPWM");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class PWMTalonFX extends PWMMotorController {
|
||||
public PWMTalonFX(final int channel) {
|
||||
super("PWMTalonFX", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "TalonFX");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class PWMTalonSRX extends PWMMotorController {
|
||||
public PWMTalonSRX(final int channel) {
|
||||
super("PWMTalonSRX", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "PWMTalonSRX");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class PWMVenom extends PWMMotorController {
|
||||
public PWMVenom(final int channel) {
|
||||
super("PWMVenom", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "FusionVenom");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class PWMVictorSPX extends PWMMotorController {
|
||||
public PWMVictorSPX(final int channel) {
|
||||
super("PWMVictorSPX", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "PWMVictorSPX");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class SD540 extends PWMMotorController {
|
||||
public SD540(final int channel) {
|
||||
super("SD540", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2050, 1550, 1500, 1440, 940);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2050, 1550, 1500, 1440, 940);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "MindsensorsSD540");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class Spark extends PWMMotorController {
|
||||
public Spark(final int channel) {
|
||||
super("Spark", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2003, 1550, 1500, 1460, 999);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2003, 1550, 1500, 1460, 999);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "RevSPARK");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class SparkMini extends PWMMotorController {
|
||||
public SparkMini(final int channel) {
|
||||
super("SparkMini", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2500, 1510, 1500, 1490, 500);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2500, 1510, 1500, 1490, 500);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "RevSPARK");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class Talon extends PWMMotorController {
|
||||
public Talon(final int channel) {
|
||||
super("Talon", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2037, 1539, 1513, 1487, 989);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2037, 1539, 1513, 1487, 989);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "Talon");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class Victor extends PWMMotorController {
|
||||
public Victor(final int channel) {
|
||||
super("Victor", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2027, 1525, 1507, 1490, 1026);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k2X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2027, 1525, 1507, 1490, 1026);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k10Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "Victor");
|
||||
}
|
||||
|
||||
@@ -37,10 +37,9 @@ public class VictorSP extends PWMMotorController {
|
||||
public VictorSP(final int channel) {
|
||||
super("VictorSP", channel);
|
||||
|
||||
m_pwm.setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setPeriodMultiplier(PWM.PeriodMultiplier.k1X);
|
||||
m_pwm.setSpeed(0.0);
|
||||
m_pwm.setZeroLatch();
|
||||
setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
|
||||
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
|
||||
setSpeed(0.0);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "VictorSP");
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.hal.PWMConfigDataResult;
|
||||
import edu.wpi.first.hal.PWMJNI;
|
||||
import edu.wpi.first.hal.SimDevice;
|
||||
import edu.wpi.first.util.sendable.Sendable;
|
||||
import edu.wpi.first.util.sendable.SendableBuilder;
|
||||
import edu.wpi.first.util.sendable.SendableRegistry;
|
||||
@@ -19,14 +19,14 @@ import edu.wpi.first.util.sendable.SendableRegistry;
|
||||
* sent to the FPGA, and the update occurs at the next FPGA cycle (5.05ms). There is no delay.
|
||||
*/
|
||||
public class PWM implements Sendable, AutoCloseable {
|
||||
/** Represents the amount to multiply the minimum servo-pulse pwm period by. */
|
||||
public enum PeriodMultiplier {
|
||||
/** Period Multiplier: don't skip pulses. PWM pulses occur every 5.05 ms */
|
||||
k1X,
|
||||
/** Period Multiplier: skip every other pulse. PWM pulses occur every 10.10 ms */
|
||||
k2X,
|
||||
/** Period Multiplier: skip three out of four pulses. PWM pulses occur every 20.20 ms */
|
||||
k4X
|
||||
/** Represents the output period in microseconds. */
|
||||
public enum OutputPeriod {
|
||||
/** Pulse every 5ms. */
|
||||
k5Ms,
|
||||
/** Pulse every 10ms. */
|
||||
k10Ms,
|
||||
/** Pulse every 20ms. */
|
||||
k20Ms
|
||||
}
|
||||
|
||||
private final int m_channel;
|
||||
@@ -62,8 +62,6 @@ public class PWM implements Sendable, AutoCloseable {
|
||||
|
||||
setDisabled();
|
||||
|
||||
PWMJNI.setPWMEliminateDeadband(m_handle, false);
|
||||
|
||||
HAL.reportUsage("IO", channel, "PWM");
|
||||
if (registerSendable) {
|
||||
SendableRegistry.add(this, "PWM", channel);
|
||||
@@ -82,44 +80,6 @@ public class PWM implements Sendable, AutoCloseable {
|
||||
m_handle = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally eliminate the deadband from a motor controller.
|
||||
*
|
||||
* @param eliminateDeadband If true, set the motor curve for the motor controller to eliminate the
|
||||
* deadband in the middle of the range. Otherwise, keep the full range without modifying any
|
||||
* values.
|
||||
*/
|
||||
public void enableDeadbandElimination(boolean eliminateDeadband) {
|
||||
PWMJNI.setPWMEliminateDeadband(m_handle, eliminateDeadband);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bounds on the PWM pulse widths. This sets the bounds on the PWM values for a particular
|
||||
* type of controller. The values determine the upper and lower speeds as well as the deadband
|
||||
* bracket.
|
||||
*
|
||||
* @param max The max PWM pulse width in us
|
||||
* @param deadbandMax The high end of the deadband range pulse width in us
|
||||
* @param center The center (off) pulse width in us
|
||||
* @param deadbandMin The low end of the deadband pulse width in us
|
||||
* @param min The minimum pulse width in us
|
||||
*/
|
||||
public void setBoundsMicroseconds(
|
||||
int max, int deadbandMax, int center, int deadbandMin, int min) {
|
||||
PWMJNI.setPWMConfigMicroseconds(m_handle, max, deadbandMax, center, deadbandMin, min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bounds on the PWM pulse widths. This gets the bounds on the PWM values for a
|
||||
* particular type of controller. The values determine the upper and lower speeds as well as the
|
||||
* deadband bracket.
|
||||
*
|
||||
* @return The bounds on the PWM pulse widths.
|
||||
*/
|
||||
public PWMConfigDataResult getBoundsMicroseconds() {
|
||||
return PWMJNI.getPWMConfigMicroseconds(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the channel number associated with the PWM Object.
|
||||
*
|
||||
@@ -129,54 +89,6 @@ public class PWM implements Sendable, AutoCloseable {
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a position.
|
||||
*
|
||||
* <p>This is intended to be used by servos.
|
||||
*
|
||||
* @param pos The position to set the servo between 0.0 and 1.0.
|
||||
* @pre setBoundsMicroseconds() called.
|
||||
*/
|
||||
public void setPosition(double pos) {
|
||||
PWMJNI.setPWMPosition(m_handle, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of a position.
|
||||
*
|
||||
* <p>This is intended to be used by servos.
|
||||
*
|
||||
* @return The position the servo is set to between 0.0 and 1.0.
|
||||
* @pre setBoundsMicroseconds() called.
|
||||
*/
|
||||
public double getPosition() {
|
||||
return PWMJNI.getPWMPosition(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value based on a speed.
|
||||
*
|
||||
* <p>This is intended to be used by motor controllers.
|
||||
*
|
||||
* @param speed The speed to set the motor controller between -1.0 and 1.0.
|
||||
* @pre setBoundsMicroseconds() called.
|
||||
*/
|
||||
public void setSpeed(double speed) {
|
||||
PWMJNI.setPWMSpeed(m_handle, speed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM value in terms of speed.
|
||||
*
|
||||
* <p>This is intended to be used by motor controllers.
|
||||
*
|
||||
* @return The most recently set speed between -1.0 and 1.0.
|
||||
* @pre setBoundsMicroseconds() called.
|
||||
*/
|
||||
public double getSpeed() {
|
||||
return PWMJNI.getPWMSpeed(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM value directly to the hardware.
|
||||
*
|
||||
@@ -201,33 +113,23 @@ public class PWM implements Sendable, AutoCloseable {
|
||||
|
||||
/** Temporarily disables the PWM output. The next set call will re-enable the output. */
|
||||
public final void setDisabled() {
|
||||
PWMJNI.setPWMDisabled(m_handle);
|
||||
setPulseTimeMicroseconds(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Slow down the PWM signal for old devices.
|
||||
* Sets the PWM output period.
|
||||
*
|
||||
* @param mult The period multiplier to apply to this channel
|
||||
* @param mult The output period to apply to this channel
|
||||
*/
|
||||
public void setPeriodMultiplier(PeriodMultiplier mult) {
|
||||
public void setOutputPeriod(OutputPeriod mult) {
|
||||
int scale =
|
||||
switch (mult) {
|
||||
case k4X -> 3; // Squelch 3 out of 4 outputs
|
||||
case k2X -> 1; // Squelch 1 out of 2 outputs
|
||||
case k1X -> 0; // Don't squelch any outputs
|
||||
case k20Ms -> 3;
|
||||
case k10Ms -> 1;
|
||||
case k5Ms -> 0;
|
||||
};
|
||||
|
||||
PWMJNI.setPWMPeriodScale(m_handle, scale);
|
||||
}
|
||||
|
||||
/** Latches PWM to zero. */
|
||||
public void setZeroLatch() {
|
||||
PWMJNI.latchPWMZero(m_handle);
|
||||
}
|
||||
|
||||
/** Sets the PWM output to be a continuous high signal while enabled. */
|
||||
public void setAlwaysHighMode() {
|
||||
PWMJNI.setAlwaysHighMode(m_handle);
|
||||
PWMJNI.setPWMOutputPeriod(m_handle, scale);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,13 +141,20 @@ public class PWM implements Sendable, AutoCloseable {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates this input is used by a simulated device.
|
||||
*
|
||||
* @param device simulated device handle
|
||||
*/
|
||||
public void setSimDevice(SimDevice device) {
|
||||
PWMJNI.setPWMSimDevice(m_handle, device.getNativeHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initSendable(SendableBuilder builder) {
|
||||
builder.setSmartDashboardType("PWM");
|
||||
builder.setActuator(true);
|
||||
builder.addDoubleProperty(
|
||||
"Value", this::getPulseTimeMicroseconds, value -> setPulseTimeMicroseconds((int) value));
|
||||
builder.addDoubleProperty("Speed", this::getSpeed, this::setSpeed);
|
||||
builder.addDoubleProperty("Position", this::getPosition, this::setPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,14 @@
|
||||
package edu.wpi.first.wpilibj;
|
||||
|
||||
import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.hal.SimDevice;
|
||||
import edu.wpi.first.hal.SimDevice.Direction;
|
||||
import edu.wpi.first.hal.SimDouble;
|
||||
import edu.wpi.first.math.MathUtil;
|
||||
import edu.wpi.first.util.sendable.Sendable;
|
||||
import edu.wpi.first.util.sendable.SendableBuilder;
|
||||
import edu.wpi.first.util.sendable.SendableRegistry;
|
||||
import edu.wpi.first.wpilibj.PWM.OutputPeriod;
|
||||
|
||||
/**
|
||||
* Standard hobby style servo.
|
||||
@@ -14,13 +20,21 @@ import edu.wpi.first.util.sendable.SendableRegistry;
|
||||
* <p>The range parameters default to the appropriate values for the Hitec HS-322HD servo provided
|
||||
* in the FIRST Kit of Parts in 2008.
|
||||
*/
|
||||
public class Servo extends PWM {
|
||||
public class Servo implements Sendable, AutoCloseable {
|
||||
private static final double kMaxServoAngle = 180.0;
|
||||
private static final double kMinServoAngle = 0.0;
|
||||
|
||||
private static final int kDefaultMaxServoPWM = 2400;
|
||||
private static final int kDefaultMinServoPWM = 600;
|
||||
|
||||
private final PWM m_pwm;
|
||||
|
||||
private SimDevice m_simDevice;
|
||||
private SimDouble m_simPosition;
|
||||
|
||||
private static final int m_minPwm = kDefaultMinServoPWM;
|
||||
private static final int m_maxPwm = kDefaultMaxServoPWM;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -32,12 +46,31 @@ public class Servo extends PWM {
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public Servo(final int channel) {
|
||||
super(channel);
|
||||
setBoundsMicroseconds(kDefaultMaxServoPWM, 0, 0, 0, kDefaultMinServoPWM);
|
||||
setPeriodMultiplier(PeriodMultiplier.k4X);
|
||||
m_pwm = new PWM(channel, false);
|
||||
SendableRegistry.add(this, "Servo", channel);
|
||||
|
||||
HAL.reportUsage("IO", getChannel(), "Servo");
|
||||
SendableRegistry.setName(this, "Servo", getChannel());
|
||||
m_pwm.setOutputPeriod(OutputPeriod.k20Ms);
|
||||
|
||||
HAL.reportUsage("IO", channel, "Servo");
|
||||
|
||||
m_simDevice = SimDevice.create("Servo", channel);
|
||||
if (m_simDevice != null) {
|
||||
m_simPosition = m_simDevice.createDouble("Position", Direction.kOutput, 0.0);
|
||||
m_pwm.setSimDevice(m_simDevice);
|
||||
}
|
||||
}
|
||||
|
||||
/** Free the resource associated with the PWM channel and set the value to 0. */
|
||||
@Override
|
||||
public void close() {
|
||||
SendableRegistry.remove(this);
|
||||
m_pwm.close();
|
||||
|
||||
if (m_simDevice != null) {
|
||||
m_simDevice.close();
|
||||
m_simDevice = null;
|
||||
m_simPosition = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,7 +81,15 @@ public class Servo extends PWM {
|
||||
* @param value Position from 0.0 to 1.0.
|
||||
*/
|
||||
public void set(double value) {
|
||||
setPosition(value);
|
||||
value = MathUtil.clamp(value, 0.0, 1.0);
|
||||
|
||||
if (m_simPosition != null) {
|
||||
m_simPosition.set(value);
|
||||
}
|
||||
|
||||
int rawValue = (int) ((value * getFullRangeScaleFactor()) + m_minPwm);
|
||||
|
||||
m_pwm.setPulseTimeMicroseconds(rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +102,14 @@ public class Servo extends PWM {
|
||||
* @return Position from 0.0 to 1.0.
|
||||
*/
|
||||
public double get() {
|
||||
return getPosition();
|
||||
int rawValue = m_pwm.getPulseTimeMicroseconds();
|
||||
|
||||
if (rawValue < m_minPwm) {
|
||||
return 0.0;
|
||||
} else if (rawValue > m_maxPwm) {
|
||||
return 1.0;
|
||||
}
|
||||
return (rawValue - m_minPwm) / getFullRangeScaleFactor();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +131,7 @@ public class Servo extends PWM {
|
||||
degrees = kMaxServoAngle;
|
||||
}
|
||||
|
||||
setPosition((degrees - kMinServoAngle) / getServoAngleRange());
|
||||
set((degrees - kMinServoAngle) / getServoAngleRange());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +143,29 @@ public class Servo extends PWM {
|
||||
* @return The angle in degrees to which the servo is set.
|
||||
*/
|
||||
public double getAngle() {
|
||||
return getPosition() * getServoAngleRange() + kMinServoAngle;
|
||||
return get() * getServoAngleRange() + kMinServoAngle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the backing PWM handle.
|
||||
*
|
||||
* @return The pwm handle.
|
||||
*/
|
||||
public int getPwmHandle() {
|
||||
return m_pwm.getHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the PWM channel number.
|
||||
*
|
||||
* @return The channel number.
|
||||
*/
|
||||
public int getChannel() {
|
||||
return m_pwm.getChannel();
|
||||
}
|
||||
|
||||
private double getFullRangeScaleFactor() {
|
||||
return m_maxPwm - m_minPwm;
|
||||
}
|
||||
|
||||
private double getServoAngleRange() {
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
package edu.wpi.first.wpilibj.motorcontrol;
|
||||
|
||||
import edu.wpi.first.hal.SimDevice;
|
||||
import edu.wpi.first.hal.SimDevice.Direction;
|
||||
import edu.wpi.first.hal.SimDouble;
|
||||
import edu.wpi.first.math.MathUtil;
|
||||
import edu.wpi.first.util.sendable.Sendable;
|
||||
import edu.wpi.first.util.sendable.SendableBuilder;
|
||||
import edu.wpi.first.util.sendable.SendableRegistry;
|
||||
@@ -22,6 +26,16 @@ public abstract class PWMMotorController extends MotorSafety
|
||||
/** PWM instances for motor controller. */
|
||||
protected PWM m_pwm;
|
||||
|
||||
private SimDevice m_simDevice;
|
||||
private SimDouble m_simSpeed;
|
||||
|
||||
private boolean m_eliminateDeadband;
|
||||
private int m_minPwm;
|
||||
private int m_deadbandMinPwm;
|
||||
private int m_centerPwm;
|
||||
private int m_deadbandMaxPwm;
|
||||
private int m_maxPwm;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -33,6 +47,12 @@ public abstract class PWMMotorController extends MotorSafety
|
||||
protected PWMMotorController(final String name, final int channel) {
|
||||
m_pwm = new PWM(channel, false);
|
||||
SendableRegistry.add(this, name, channel);
|
||||
|
||||
m_simDevice = SimDevice.create("PWMMotorController", channel);
|
||||
if (m_simDevice != null) {
|
||||
m_simSpeed = m_simDevice.createDouble("Speed", Direction.kOutput, 0.0);
|
||||
m_pwm.setSimDevice(m_simDevice);
|
||||
}
|
||||
}
|
||||
|
||||
/** Free the resource associated with the PWM channel and set the value to 0. */
|
||||
@@ -40,6 +60,105 @@ public abstract class PWMMotorController extends MotorSafety
|
||||
public void close() {
|
||||
SendableRegistry.remove(this);
|
||||
m_pwm.close();
|
||||
|
||||
if (m_simDevice != null) {
|
||||
m_simDevice.close();
|
||||
m_simDevice = null;
|
||||
m_simSpeed = null;
|
||||
}
|
||||
}
|
||||
|
||||
private int getMinPositivePwm() {
|
||||
if (m_eliminateDeadband) {
|
||||
return m_deadbandMaxPwm;
|
||||
} else {
|
||||
return m_centerPwm + 1;
|
||||
}
|
||||
}
|
||||
|
||||
private int getMaxNegativePwm() {
|
||||
if (m_eliminateDeadband) {
|
||||
return m_deadbandMinPwm;
|
||||
} else {
|
||||
return m_centerPwm - 1;
|
||||
}
|
||||
}
|
||||
|
||||
private int getPositiveScaleFactor() {
|
||||
return m_maxPwm - getMinPositivePwm();
|
||||
}
|
||||
|
||||
private int getNegativeScaleFactor() {
|
||||
return getMaxNegativePwm() - m_minPwm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a speed from -1 to 1, and outputs it in the microsecond format.
|
||||
*
|
||||
* @param speed the speed to output
|
||||
*/
|
||||
protected final void setSpeed(double speed) {
|
||||
if (Double.isFinite(speed)) {
|
||||
speed = MathUtil.clamp(speed, -1.0, 1.0);
|
||||
} else {
|
||||
speed = 0.0;
|
||||
}
|
||||
|
||||
if (m_simSpeed != null) {
|
||||
m_simSpeed.set(speed);
|
||||
}
|
||||
|
||||
int rawValue;
|
||||
if (speed == 0.0) {
|
||||
rawValue = m_centerPwm;
|
||||
} else if (speed > 0.0) {
|
||||
rawValue = (int) Math.round(speed * getPositiveScaleFactor()) + getMinPositivePwm();
|
||||
} else {
|
||||
rawValue = (int) Math.round(speed * getNegativeScaleFactor()) + getMaxNegativePwm();
|
||||
}
|
||||
|
||||
m_pwm.setPulseTimeMicroseconds(rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the speed from -1 to 1, from the currently set pulse time.
|
||||
*
|
||||
* @return motor controller speed
|
||||
*/
|
||||
protected final double getSpeed() {
|
||||
int rawValue = m_pwm.getPulseTimeMicroseconds();
|
||||
|
||||
if (rawValue == 0) {
|
||||
return 0.0;
|
||||
} else if (rawValue > m_maxPwm) {
|
||||
return 1.0;
|
||||
} else if (rawValue < m_minPwm) {
|
||||
return -1.0;
|
||||
} else if (rawValue > getMinPositivePwm()) {
|
||||
return (rawValue - getMinPositivePwm()) / (double) getPositiveScaleFactor();
|
||||
} else if (rawValue < getMaxNegativePwm()) {
|
||||
return (rawValue - getMaxNegativePwm()) / (double) getNegativeScaleFactor();
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bounds in microseconds for the controller.
|
||||
*
|
||||
* @param maxPwm maximum
|
||||
* @param deadbandMaxPwm deadband max
|
||||
* @param centerPwm center
|
||||
* @param deadbandMinPwm deadmand min
|
||||
* @param minPwm minimum
|
||||
*/
|
||||
protected final void setBoundsMicroseconds(
|
||||
int maxPwm, int deadbandMaxPwm, int centerPwm, int deadbandMinPwm, int minPwm) {
|
||||
m_maxPwm = maxPwm;
|
||||
m_deadbandMaxPwm = deadbandMaxPwm;
|
||||
m_centerPwm = centerPwm;
|
||||
m_deadbandMinPwm = deadbandMinPwm;
|
||||
m_minPwm = minPwm;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +174,7 @@ public abstract class PWMMotorController extends MotorSafety
|
||||
if (m_isInverted) {
|
||||
speed = -speed;
|
||||
}
|
||||
m_pwm.setSpeed(speed);
|
||||
setSpeed(speed);
|
||||
|
||||
for (var follower : m_followers) {
|
||||
follower.set(speed);
|
||||
@@ -65,15 +184,13 @@ public abstract class PWMMotorController extends MotorSafety
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the recently set value of the PWM. This value is affected by the inversion property. If you
|
||||
* want the value that is sent directly to the MotorController, use {@link
|
||||
* edu.wpi.first.wpilibj.PWM#getSpeed()} instead.
|
||||
* Get the recently set value of the PWM. This value is affected by the inversion property.
|
||||
*
|
||||
* @return The most recently set value for the PWM between -1.0 and 1.0.
|
||||
*/
|
||||
@Override
|
||||
public double get() {
|
||||
return m_pwm.getSpeed() * (m_isInverted ? -1.0 : 1.0);
|
||||
return getSpeed() * (m_isInverted ? -1.0 : 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,6 +216,10 @@ public abstract class PWMMotorController extends MotorSafety
|
||||
public void disable() {
|
||||
m_pwm.setDisabled();
|
||||
|
||||
if (m_simSpeed != null) {
|
||||
m_simSpeed.set(0.0);
|
||||
}
|
||||
|
||||
for (var follower : m_followers) {
|
||||
follower.disable();
|
||||
}
|
||||
@@ -107,7 +228,7 @@ public abstract class PWMMotorController extends MotorSafety
|
||||
@Override
|
||||
public void stopMotor() {
|
||||
// Don't use set(0) as that will feed the watch kitty
|
||||
m_pwm.setSpeed(0);
|
||||
m_pwm.setPulseTimeMicroseconds(0);
|
||||
|
||||
for (var follower : m_followers) {
|
||||
follower.stopMotor();
|
||||
@@ -145,7 +266,7 @@ public abstract class PWMMotorController extends MotorSafety
|
||||
* values.
|
||||
*/
|
||||
public void enableDeadbandElimination(boolean eliminateDeadband) {
|
||||
m_pwm.enableDeadbandElimination(eliminateDeadband);
|
||||
m_eliminateDeadband = eliminateDeadband;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// 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.SimDouble;
|
||||
import edu.wpi.first.wpilibj.motorcontrol.PWMMotorController;
|
||||
|
||||
/** Class to control a simulated PWM motor controller. */
|
||||
public class PWMMotorControllerSim {
|
||||
private final SimDouble m_simSpeed;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param motorctrl The device to simulate
|
||||
*/
|
||||
public PWMMotorControllerSim(PWMMotorController motorctrl) {
|
||||
this(motorctrl.getChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param channel The channel the motor controller is attached to.
|
||||
*/
|
||||
public PWMMotorControllerSim(int channel) {
|
||||
SimDeviceSim simDevice = new SimDeviceSim("PWMMotorController", channel);
|
||||
m_simSpeed = simDevice.getDouble("Speed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the motor speed set.
|
||||
*
|
||||
* @return Speed
|
||||
*/
|
||||
public double getSpeed() {
|
||||
return m_simSpeed.get();
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ package edu.wpi.first.wpilibj.simulation;
|
||||
import edu.wpi.first.hal.simulation.NotifyCallback;
|
||||
import edu.wpi.first.hal.simulation.PWMDataJNI;
|
||||
import edu.wpi.first.wpilibj.PWM;
|
||||
import edu.wpi.first.wpilibj.motorcontrol.PWMMotorController;
|
||||
|
||||
/** Class to control a simulated PWM output. */
|
||||
public class PWMSim {
|
||||
@@ -22,15 +21,6 @@ public class PWMSim {
|
||||
m_index = pwm.getChannel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs from a PWMMotorController object.
|
||||
*
|
||||
* @param motorctrl PWMMotorController to simulate
|
||||
*/
|
||||
public PWMSim(PWMMotorController motorctrl) {
|
||||
m_index = motorctrl.getChannel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs from a PWM channel number.
|
||||
*
|
||||
@@ -101,66 +91,6 @@ public class PWMSim {
|
||||
PWMDataJNI.setPulseMicrosecond(m_index, microsecondPulseTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the PWM speed changes.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether to run the callback with the initial value
|
||||
* @return the {@link CallbackStore} object associated with this callback.
|
||||
*/
|
||||
public CallbackStore registerSpeedCallback(NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = PWMDataJNI.registerSpeedCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, PWMDataJNI::cancelSpeedCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM speed.
|
||||
*
|
||||
* @return the PWM speed (-1.0 to 1.0)
|
||||
*/
|
||||
public double getSpeed() {
|
||||
return PWMDataJNI.getSpeed(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM speed.
|
||||
*
|
||||
* @param speed the PWM speed (-1.0 to 1.0)
|
||||
*/
|
||||
public void setSpeed(double speed) {
|
||||
PWMDataJNI.setSpeed(m_index, speed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the PWM position changes.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether to run the callback with the initial value
|
||||
* @return the {@link CallbackStore} object associated with this callback.
|
||||
*/
|
||||
public CallbackStore registerPositionCallback(NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = PWMDataJNI.registerPositionCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, PWMDataJNI::cancelPositionCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PWM position.
|
||||
*
|
||||
* @return the PWM position (0.0 to 1.0)
|
||||
*/
|
||||
public double getPosition() {
|
||||
return PWMDataJNI.getPosition(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM position.
|
||||
*
|
||||
* @param position the PWM position (0.0 to 1.0)
|
||||
*/
|
||||
public void setPosition(double position) {
|
||||
PWMDataJNI.setPosition(m_index, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the PWM period scale changes.
|
||||
*
|
||||
@@ -168,9 +98,10 @@ public class PWMSim {
|
||||
* @param initialNotify whether to run the callback with the initial value
|
||||
* @return the {@link CallbackStore} object associated with this callback.
|
||||
*/
|
||||
public CallbackStore registerPeriodScaleCallback(NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = PWMDataJNI.registerPeriodScaleCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, PWMDataJNI::cancelPeriodScaleCallback);
|
||||
public CallbackStore registerOutputPeriodCallback(
|
||||
NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = PWMDataJNI.registerOutputPeriodCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, PWMDataJNI::cancelOutputPeriodCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,47 +109,17 @@ public class PWMSim {
|
||||
*
|
||||
* @return the PWM period scale
|
||||
*/
|
||||
public int getPeriodScale() {
|
||||
return PWMDataJNI.getPeriodScale(m_index);
|
||||
public int getOutputPeriod() {
|
||||
return PWMDataJNI.getOutputPeriod(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PWM period scale.
|
||||
*
|
||||
* @param periodScale the PWM period scale
|
||||
* @param period the PWM period scale
|
||||
*/
|
||||
public void setPeriodScale(int periodScale) {
|
||||
PWMDataJNI.setPeriodScale(m_index, periodScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be run when the PWM zero latch state changes.
|
||||
*
|
||||
* @param callback the callback
|
||||
* @param initialNotify whether to run the callback with the initial state
|
||||
* @return the {@link CallbackStore} object associated with this callback.
|
||||
*/
|
||||
public CallbackStore registerZeroLatchCallback(NotifyCallback callback, boolean initialNotify) {
|
||||
int uid = PWMDataJNI.registerZeroLatchCallback(m_index, callback, initialNotify);
|
||||
return new CallbackStore(m_index, uid, PWMDataJNI::cancelZeroLatchCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the PWM is zero latched.
|
||||
*
|
||||
* @return true if zero latched
|
||||
*/
|
||||
public boolean getZeroLatch() {
|
||||
return PWMDataJNI.getZeroLatch(m_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define whether the PWM has been zero latched.
|
||||
*
|
||||
* @param zeroLatch true to indicate zero latched
|
||||
*/
|
||||
public void setZeroLatch(boolean zeroLatch) {
|
||||
PWMDataJNI.setZeroLatch(m_index, zeroLatch);
|
||||
public void setOutputPeriod(int period) {
|
||||
PWMDataJNI.setOutputPeriod(m_index, period);
|
||||
}
|
||||
|
||||
/** Reset all simulation data. */
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// 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.SimDouble;
|
||||
import edu.wpi.first.wpilibj.Servo;
|
||||
|
||||
/** Class to control a simulated Servo. */
|
||||
public class ServoSim {
|
||||
private final SimDouble m_simPosition;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param servo The device to simulate
|
||||
*/
|
||||
public ServoSim(Servo servo) {
|
||||
this(servo.getChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param channel The channel the servo is attached to.
|
||||
*/
|
||||
public ServoSim(int channel) {
|
||||
SimDeviceSim simDevice = new SimDeviceSim("Servo", channel);
|
||||
m_simPosition = simDevice.getDouble("Position");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position set.
|
||||
*
|
||||
* @return Position
|
||||
*/
|
||||
public double getPosition() {
|
||||
return m_simPosition.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the angle set.
|
||||
*
|
||||
* @return Angle
|
||||
*/
|
||||
public double getAngle() {
|
||||
return getPosition() * 180.0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// 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 static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.motorcontrol.Spark;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class PWMMotorControllerSimTest {
|
||||
@Test
|
||||
void testMotor() {
|
||||
HAL.initialize(500, 0);
|
||||
|
||||
try (Spark spark = new Spark(0)) {
|
||||
PWMMotorControllerSim sim = new PWMMotorControllerSim(spark);
|
||||
|
||||
spark.set(0);
|
||||
assertEquals(0, sim.getSpeed());
|
||||
|
||||
spark.set(0.354);
|
||||
assertEquals(0.354, sim.getSpeed());
|
||||
|
||||
spark.set(-0.785);
|
||||
assertEquals(-0.785, sim.getSpeed());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.PWM;
|
||||
import edu.wpi.first.wpilibj.simulation.testutils.BooleanCallback;
|
||||
import edu.wpi.first.wpilibj.simulation.testutils.DoubleCallback;
|
||||
import edu.wpi.first.wpilibj.simulation.testutils.IntCallback;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class PWMSimTest {
|
||||
private static final double PWM_STEP_SIZE = 1.0 / 2000.0;
|
||||
|
||||
@Test
|
||||
void testInitialize() {
|
||||
HAL.initialize(500, 0);
|
||||
@@ -55,119 +52,7 @@ class PWMSimTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetSpeed() {
|
||||
HAL.initialize(500, 0);
|
||||
|
||||
PWMSim sim = new PWMSim(0);
|
||||
sim.resetData();
|
||||
assertFalse(sim.getInitialized());
|
||||
|
||||
DoubleCallback callback = new DoubleCallback();
|
||||
|
||||
try (CallbackStore cb = sim.registerSpeedCallback(callback, false);
|
||||
PWM pwm = new PWM(0)) {
|
||||
double kTestValue = 0.3504;
|
||||
pwm.setSpeed(kTestValue);
|
||||
|
||||
assertEquals(kTestValue, sim.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getSpeed(), PWM_STEP_SIZE);
|
||||
assertTrue(callback.wasTriggered());
|
||||
assertEquals(kTestValue, callback.getSetValue(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue / 2 + 0.5, sim.getPosition(), PWM_STEP_SIZE * 2);
|
||||
assertEquals(kTestValue / 2 + 0.5, pwm.getPosition(), PWM_STEP_SIZE * 2);
|
||||
|
||||
kTestValue = -1.0;
|
||||
pwm.setSpeed(kTestValue);
|
||||
|
||||
assertEquals(kTestValue, sim.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(0.0, sim.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(0.0, pwm.getPosition(), PWM_STEP_SIZE);
|
||||
|
||||
kTestValue = 0.0;
|
||||
pwm.setSpeed(kTestValue);
|
||||
|
||||
assertEquals(kTestValue, sim.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(0.5, sim.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(0.5, pwm.getPosition(), PWM_STEP_SIZE);
|
||||
|
||||
kTestValue = 1.0;
|
||||
pwm.setSpeed(kTestValue);
|
||||
|
||||
assertEquals(kTestValue, sim.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, sim.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getPosition(), PWM_STEP_SIZE);
|
||||
|
||||
kTestValue = 1.1;
|
||||
pwm.setSpeed(kTestValue);
|
||||
|
||||
assertEquals(1.0, sim.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(1.0, pwm.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(1.0, sim.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(1.0, pwm.getPosition(), PWM_STEP_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetPosition() {
|
||||
HAL.initialize(500, 0);
|
||||
|
||||
PWMSim sim = new PWMSim(0);
|
||||
sim.resetData();
|
||||
assertFalse(sim.getInitialized());
|
||||
|
||||
DoubleCallback callback = new DoubleCallback();
|
||||
|
||||
try (CallbackStore cb = sim.registerPositionCallback(callback, false);
|
||||
PWM pwm = new PWM(0)) {
|
||||
double kTestValue = 0.3504;
|
||||
pwm.setPosition(kTestValue);
|
||||
|
||||
assertEquals(kTestValue, sim.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getPosition(), PWM_STEP_SIZE);
|
||||
assertTrue(callback.wasTriggered());
|
||||
assertEquals(kTestValue, callback.getSetValue(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue * 2 - 1.0, sim.getSpeed(), PWM_STEP_SIZE * 2);
|
||||
assertEquals(kTestValue * 2 - 1.0, pwm.getSpeed(), PWM_STEP_SIZE * 2);
|
||||
|
||||
kTestValue = -1.0;
|
||||
pwm.setPosition(kTestValue);
|
||||
|
||||
assertEquals(0.0, sim.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(0.0, pwm.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, sim.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getSpeed(), PWM_STEP_SIZE);
|
||||
|
||||
kTestValue = 0.0;
|
||||
pwm.setPosition(kTestValue);
|
||||
|
||||
assertEquals(kTestValue, sim.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(-1.0, sim.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(-1.0, pwm.getSpeed(), PWM_STEP_SIZE);
|
||||
|
||||
kTestValue = 1.0;
|
||||
pwm.setPosition(kTestValue);
|
||||
|
||||
assertEquals(kTestValue, sim.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, sim.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(kTestValue, pwm.getSpeed(), PWM_STEP_SIZE);
|
||||
|
||||
kTestValue = 1.1;
|
||||
pwm.setPosition(kTestValue);
|
||||
|
||||
assertEquals(1.0, sim.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(1.0, pwm.getPosition(), PWM_STEP_SIZE);
|
||||
assertEquals(1.0, sim.getSpeed(), PWM_STEP_SIZE);
|
||||
assertEquals(1.0, pwm.getSpeed(), PWM_STEP_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetPeriodScale() {
|
||||
void testSetOutputPeriod() {
|
||||
HAL.initialize(500, 0);
|
||||
|
||||
PWMSim sim = new PWMSim(0);
|
||||
@@ -176,30 +61,12 @@ class PWMSimTest {
|
||||
|
||||
IntCallback callback = new IntCallback();
|
||||
|
||||
try (CallbackStore cb = sim.registerPeriodScaleCallback(callback, false);
|
||||
try (CallbackStore cb = sim.registerOutputPeriodCallback(callback, false);
|
||||
PWM pwm = new PWM(0)) {
|
||||
sim.setPeriodScale(3504);
|
||||
assertEquals(3504, sim.getPeriodScale());
|
||||
sim.setOutputPeriod(3504);
|
||||
assertEquals(3504, sim.getOutputPeriod());
|
||||
assertTrue(callback.wasTriggered());
|
||||
assertEquals(3504, callback.getSetValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetZeroLatch() {
|
||||
HAL.initialize(500, 0);
|
||||
|
||||
PWMSim sim = new PWMSim(0);
|
||||
sim.resetData();
|
||||
assertFalse(sim.getInitialized());
|
||||
|
||||
BooleanCallback callback = new BooleanCallback();
|
||||
|
||||
try (CallbackStore cb = sim.registerZeroLatchCallback(callback, false);
|
||||
PWM pwm = new PWM(0)) {
|
||||
pwm.setZeroLatch();
|
||||
|
||||
assertTrue(callback.wasTriggered());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// 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 static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.Servo;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ServoSimTest {
|
||||
@Test
|
||||
void testServo() {
|
||||
HAL.initialize(500, 0);
|
||||
|
||||
try (Servo servo = new Servo(0)) {
|
||||
ServoSim sim = new ServoSim(servo);
|
||||
|
||||
servo.set(0);
|
||||
assertEquals(0, sim.getPosition());
|
||||
|
||||
servo.set(0.354);
|
||||
assertEquals(0.354, sim.getPosition());
|
||||
|
||||
servo.setAngle(10);
|
||||
assertEquals(10, sim.getAngle());
|
||||
|
||||
servo.setAngle(90);
|
||||
assertEquals(90, sim.getAngle());
|
||||
|
||||
servo.setAngle(170);
|
||||
assertEquals(170, sim.getAngle());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
|
||||
import edu.wpi.first.wpilibj.simulation.BatterySim;
|
||||
import edu.wpi.first.wpilibj.simulation.ElevatorSim;
|
||||
import edu.wpi.first.wpilibj.simulation.EncoderSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMMotorControllerSim;
|
||||
import edu.wpi.first.wpilibj.simulation.RoboRioSim;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.Mechanism2d;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.MechanismLigament2d;
|
||||
@@ -62,7 +62,7 @@ public class Elevator implements AutoCloseable {
|
||||
0.005,
|
||||
0.0);
|
||||
private final EncoderSim m_encoderSim = new EncoderSim(m_encoder);
|
||||
private final PWMSim m_motorSim = new PWMSim(m_motor);
|
||||
private final PWMMotorControllerSim m_motorSim = new PWMMotorControllerSim(m_motor);
|
||||
|
||||
// Create a Mechanism2d visualization of the elevator
|
||||
private final Mechanism2d m_mech2d =
|
||||
|
||||
@@ -15,7 +15,7 @@ import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
|
||||
import edu.wpi.first.wpilibj.simulation.BatterySim;
|
||||
import edu.wpi.first.wpilibj.simulation.ElevatorSim;
|
||||
import edu.wpi.first.wpilibj.simulation.EncoderSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMMotorControllerSim;
|
||||
import edu.wpi.first.wpilibj.simulation.RoboRioSim;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.Mechanism2d;
|
||||
import edu.wpi.first.wpilibj.smartdashboard.MechanismLigament2d;
|
||||
@@ -57,7 +57,7 @@ public class Elevator implements AutoCloseable {
|
||||
0.01,
|
||||
0.0);
|
||||
private final EncoderSim m_encoderSim = new EncoderSim(m_encoder);
|
||||
private final PWMSim m_motorSim = new PWMSim(m_motor);
|
||||
private final PWMMotorControllerSim m_motorSim = new PWMMotorControllerSim(m_motor);
|
||||
|
||||
// Create a Mechanism2d visualization of the elevator
|
||||
private final Mechanism2d m_mech2d = new Mechanism2d(20, 50);
|
||||
|
||||
@@ -13,7 +13,7 @@ import edu.wpi.first.wpilibj.Preferences;
|
||||
import edu.wpi.first.wpilibj.simulation.DriverStationSim;
|
||||
import edu.wpi.first.wpilibj.simulation.EncoderSim;
|
||||
import edu.wpi.first.wpilibj.simulation.JoystickSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMMotorControllerSim;
|
||||
import edu.wpi.first.wpilibj.simulation.RoboRioSim;
|
||||
import edu.wpi.first.wpilibj.simulation.SimHooks;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -27,7 +27,7 @@ class ArmSimulationTest {
|
||||
private Robot m_robot;
|
||||
private Thread m_thread;
|
||||
|
||||
private PWMSim m_motorSim;
|
||||
private PWMMotorControllerSim m_motorSim;
|
||||
private EncoderSim m_encoderSim;
|
||||
private JoystickSim m_joystickSim;
|
||||
|
||||
@@ -39,7 +39,7 @@ class ArmSimulationTest {
|
||||
m_robot = new Robot();
|
||||
m_thread = new Thread(m_robot::startCompetition);
|
||||
m_encoderSim = EncoderSim.createForChannel(Constants.kEncoderAChannel);
|
||||
m_motorSim = new PWMSim(Constants.kMotorPort);
|
||||
m_motorSim = new PWMMotorControllerSim(Constants.kMotorPort);
|
||||
m_joystickSim = new JoystickSim(Constants.kJoystickPort);
|
||||
|
||||
m_thread.start();
|
||||
@@ -57,7 +57,6 @@ class ArmSimulationTest {
|
||||
}
|
||||
m_robot.close();
|
||||
m_encoderSim.resetData();
|
||||
m_motorSim.resetData();
|
||||
Preferences.remove(Constants.kArmPKey);
|
||||
Preferences.remove(Constants.kArmPositionKey);
|
||||
Preferences.removeAll();
|
||||
@@ -79,7 +78,6 @@ class ArmSimulationTest {
|
||||
DriverStationSim.setEnabled(true);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_motorSim.getInitialized());
|
||||
assertTrue(m_encoderSim.getInitialized());
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.simulation.DriverStationSim;
|
||||
import edu.wpi.first.wpilibj.simulation.EncoderSim;
|
||||
import edu.wpi.first.wpilibj.simulation.JoystickSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMMotorControllerSim;
|
||||
import edu.wpi.first.wpilibj.simulation.RoboRioSim;
|
||||
import edu.wpi.first.wpilibj.simulation.SimHooks;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@@ -24,7 +24,7 @@ class ElevatorSimulationTest {
|
||||
private Robot m_robot;
|
||||
private Thread m_thread;
|
||||
|
||||
private PWMSim m_motorSim;
|
||||
private PWMMotorControllerSim m_motorSim;
|
||||
private EncoderSim m_encoderSim;
|
||||
private JoystickSim m_joystickSim;
|
||||
|
||||
@@ -36,7 +36,7 @@ class ElevatorSimulationTest {
|
||||
m_robot = new Robot();
|
||||
m_thread = new Thread(m_robot::startCompetition);
|
||||
m_encoderSim = EncoderSim.createForChannel(Constants.kEncoderAChannel);
|
||||
m_motorSim = new PWMSim(Constants.kMotorPort);
|
||||
m_motorSim = new PWMMotorControllerSim(Constants.kMotorPort);
|
||||
m_joystickSim = new JoystickSim(Constants.kJoystickPort);
|
||||
|
||||
m_thread.start();
|
||||
@@ -54,7 +54,6 @@ class ElevatorSimulationTest {
|
||||
}
|
||||
m_robot.close();
|
||||
m_encoderSim.resetData();
|
||||
m_motorSim.resetData();
|
||||
RoboRioSim.resetData();
|
||||
DriverStationSim.resetData();
|
||||
DriverStationSim.notifyNewData();
|
||||
@@ -68,7 +67,6 @@ class ElevatorSimulationTest {
|
||||
DriverStationSim.setEnabled(true);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_motorSim.getInitialized());
|
||||
assertTrue(m_encoderSim.getInitialized());
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import edu.wpi.first.wpilibj.simulation.AnalogInputSim;
|
||||
import edu.wpi.first.wpilibj.simulation.DriverStationSim;
|
||||
import edu.wpi.first.wpilibj.simulation.ElevatorSim;
|
||||
import edu.wpi.first.wpilibj.simulation.JoystickSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMMotorControllerSim;
|
||||
import edu.wpi.first.wpilibj.simulation.SimHooks;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -34,7 +34,7 @@ class PotentiometerPIDTest {
|
||||
private Thread m_thread;
|
||||
|
||||
private ElevatorSim m_elevatorSim;
|
||||
private PWMSim m_motorSim;
|
||||
private PWMMotorControllerSim m_motorSim;
|
||||
private AnalogInputSim m_analogSim;
|
||||
private SimPeriodicBeforeCallback m_callback;
|
||||
private JoystickSim m_joystickSim;
|
||||
@@ -57,7 +57,7 @@ class PotentiometerPIDTest {
|
||||
true,
|
||||
0);
|
||||
m_analogSim = new AnalogInputSim(Robot.kPotChannel);
|
||||
m_motorSim = new PWMSim(Robot.kMotorChannel);
|
||||
m_motorSim = new PWMMotorControllerSim(Robot.kMotorChannel);
|
||||
m_joystickSim = new JoystickSim(Robot.kJoystickChannel);
|
||||
|
||||
m_callback =
|
||||
@@ -93,7 +93,6 @@ class PotentiometerPIDTest {
|
||||
m_robot.close();
|
||||
m_callback.close();
|
||||
m_analogSim.resetData();
|
||||
m_motorSim.resetData();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -104,7 +103,6 @@ class PotentiometerPIDTest {
|
||||
DriverStationSim.setEnabled(true);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_motorSim.getInitialized());
|
||||
assertTrue(m_analogSim.getInitialized());
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import edu.wpi.first.wpilibj.DoubleSolenoid;
|
||||
import edu.wpi.first.wpilibj.PneumaticsModuleType;
|
||||
import edu.wpi.first.wpilibj.examples.unittest.Constants.IntakeConstants;
|
||||
import edu.wpi.first.wpilibj.simulation.DoubleSolenoidSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMSim;
|
||||
import edu.wpi.first.wpilibj.simulation.PWMMotorControllerSim;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -19,7 +19,7 @@ import org.junit.jupiter.api.Test;
|
||||
class IntakeTest {
|
||||
static final double DELTA = 1e-2; // acceptable deviation range
|
||||
Intake m_intake;
|
||||
PWMSim m_simMotor;
|
||||
PWMMotorControllerSim m_simMotor;
|
||||
DoubleSolenoidSim m_simPiston;
|
||||
|
||||
@BeforeEach // this method will run before each test
|
||||
@@ -27,7 +27,8 @@ class IntakeTest {
|
||||
assert HAL.initialize(500, 0); // initialize the HAL, crash if failed
|
||||
m_intake = new Intake(); // create our intake
|
||||
m_simMotor =
|
||||
new PWMSim(IntakeConstants.kMotorPort); // create our simulation PWM motor controller
|
||||
new PWMMotorControllerSim(
|
||||
IntakeConstants.kMotorPort); // create our simulation PWM motor controller
|
||||
m_simPiston =
|
||||
new DoubleSolenoidSim(
|
||||
PneumaticsModuleType.CTREPCM,
|
||||
|
||||
Reference in New Issue
Block a user