Format and style changes.

Rebuilt last SRX-related commit with latest checkout.

Change-Id: I9f10418580275dae5cd07d740d401d45ee44e276

C++: Added Magnetic Encoder sensor types
C++: API for changing status frame rates updated to use paramEnums.
C++: Added Setting nominal and peak outputs for closed loop modes.
C++: Added current-closed loop
C++: added vcomp mode
C++: Added unit scaling (rotations and rpm)
C++ Added allowableclosedlooperr
C++: Added auto zero position on index pin
C++: Added pulse width decoder API
C++: Added multiplicands in status frames, increasing the max reported pos and max rpm.
C++: Added SetClosedLoopOutputDirection() for reversing slave output and reversing single-direction closed loopoutput.
C++: Added generic ConfigSet and ConfigGet for future flexibility/features.
C++: Added IsSensorPresent
Java: Added Magnetic Encoder sensor types
Java: Added unit scaling (rotations and rpm)
Java: Added current-closed loop
Java: added vcomp mode
Java Added allowableclosedlooperr
Java: Added auto zero position on index pin
Java: Added pulse width decoder API
Java: setForwardSoftLimit and setReverseSoftLimit takes double instead of int so underneath we can support rotations instead of native units.
Java: Added generic SetParam and GetParam for future flexibility/features.
Java Added isSensorPresent

Change-Id: I800251510e411624dce5ee10272606c31764b8ab
This commit is contained in:
Omar Zrien
2015-10-11 14:49:39 -04:00
committed by Brad Miller (WPI)
parent a3b6535fe9
commit a0cc45a8f0
8 changed files with 1773 additions and 119 deletions

View File

@@ -91,9 +91,6 @@ private:
operator bool() const { return moved; }
} m_hasBeenMoved;
/** just in case user wants to modify periods of certain status frames.
* Default the vars to match the firmware default. */
uint32_t _statusRateMs[4];
//---------------------- Vars for opening a CAN stream if caller needs signals that require soliciting */
uint32_t _can_h; //!< Session handle for catching response params.
int32_t _can_stat; //!< Session handle status.
@@ -154,6 +151,7 @@ public:
static const int kStatusFrame_Feedback = 1;
static const int kStatusFrame_Encoder = 2;
static const int kStatusFrame_AnalogTempVbat = 3;
static const int kStatusFrame_PulseWidthMeas = 4;
/**
* Signal enumeration for generic signal access.
* Although every signal is enumerated, only use this for traffic that must be solicited.
@@ -225,6 +223,30 @@ public:
eSettingsChanged=90,
eQuadFilterEn=91,
ePidIaccum=93,
eStatus1FrameRate=94, // TALON_Status_1_General_10ms_t
eStatus2FrameRate=95, // TALON_Status_2_Feedback_20ms_t
eStatus3FrameRate=96, // TALON_Status_3_Enc_100ms_t
eStatus4FrameRate=97, // TALON_Status_4_AinTempVbat_100ms_t
eStatus6FrameRate=98, // TALON_Status_6_Eol_t
eStatus7FrameRate=99, // TALON_Status_7_Debug_200ms_t
eClearPositionOnIdx=100,
//reserved,
//reserved,
//reserved,
ePeakPosOutput=104,
eNominalPosOutput=105,
ePeakNegOutput=106,
eNominalNegOutput=107,
eQuadIdxPolarity=108,
eStatus8FrameRate=109, // TALON_Status_8_PulseWid_100ms_t
eAllowPosOverflow=110,
eProfileParamSlot0_AllowableClosedLoopErr=111,
eNumberPotTurns=112,
eNumberEncoderCPR=113,
ePwdPosition=114,
eAinPosition=115,
eProfileParamVcompRate=116,
eProfileParamSlot1_AllowableClosedLoopErr=117,
}param_t;
/*---------------------setters and getters that use the solicated param request/response-------------*//**
* Send a one shot frame to set an arbitrary signal.
@@ -253,6 +275,7 @@ public:
CTR_Code SetFgain(unsigned slotIdx,double gain);
CTR_Code SetIzone(unsigned slotIdx,int zone);
CTR_Code SetCloseLoopRampRate(unsigned slotIdx,int closeLoopRampRate);
CTR_Code SetVoltageCompensationRate(double voltagePerMs);
CTR_Code SetSensorPosition(int pos);
CTR_Code SetForwardSoftLimit(int forwardLimit);
CTR_Code SetReverseSoftLimit(int reverseLimit);
@@ -264,6 +287,7 @@ public:
CTR_Code GetFgain(unsigned slotIdx,double & gain);
CTR_Code GetIzone(unsigned slotIdx,int & zone);
CTR_Code GetCloseLoopRampRate(unsigned slotIdx,int & closeLoopRampRate);
CTR_Code GetVoltageCompensationRate(double & voltagePerMs);
CTR_Code GetForwardSoftLimit(int & forwardLimit);
CTR_Code GetReverseSoftLimit(int & reverseLimit);
CTR_Code GetForwardSoftEnable(int & enable);
@@ -325,6 +349,11 @@ public:
CTR_Code SetProfileSlotSelect(int param);
CTR_Code SetRampThrottle(int param);
CTR_Code SetRevFeedbackSensor(int param);
CTR_Code GetPulseWidthPosition(int &param);
CTR_Code GetPulseWidthVelocity(int &param);
CTR_Code GetPulseWidthRiseToFallUs(int &param);
CTR_Code GetPulseWidthRiseToRiseUs(int &param);
CTR_Code IsPulseWidthSensorPresent(int &param);
};
extern "C" {
void *c_TalonSRX_Create(int deviceNumber, int controlPeriodMs);

View File

@@ -20,6 +20,13 @@
* they will only need to set them in a periodic fashion as a function of what motion the application is attempting.
* If this API is used, be mindful of the CAN utilization reported in the driver station.
*
* If calling application has used the config routines to configure the selected feedback sensor, then all positions are measured in
* floating point precision rotations. All sensor velocities are specified in floating point precision RPM.
* @see ConfigPotentiometerTurns
* @see ConfigEncoderCodesPerRev
* HOWEVER, if calling application has not called the config routine for selected feedback sensor, then all getters/setters for
* position/velocity use the native engineering units of the Talon SRX firm (just like in 2015). Signals explained below.
*
* Encoder position is measured in encoder edges. Every edge is counted (similar to roboRIO 4X mode).
* Analog position is 10 bits, meaning 1024 ticks per rotation (0V => 3.3V).
* Use SetFeedbackDeviceSelect to select which sensor type you need. Once you do that you can use GetSensorPosition()
@@ -81,6 +88,7 @@
#define STATUS_5 0x02041500
#define STATUS_6 0x02041540
#define STATUS_7 0x02041580
#define STATUS_8 0x020415C0
#define CONTROL_1 0x02040000
#define CONTROL_2 0x02040040
@@ -94,6 +102,7 @@
#define GET_STATUS5() CtreCanNode::recMsg<TALON_Status_5_Startup_OneShot_t > rx = GetRx<TALON_Status_5_Startup_OneShot_t>(STATUS_5 | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS6() CtreCanNode::recMsg<TALON_Status_6_Eol_t > rx = GetRx<TALON_Status_6_Eol_t>(STATUS_6 | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS7() CtreCanNode::recMsg<TALON_Status_7_Debug_200ms_t > rx = GetRx<TALON_Status_7_Debug_200ms_t>(STATUS_7 | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS8() CtreCanNode::recMsg<TALON_Status_8_PulseWid_100ms_t > rx = GetRx<TALON_Status_8_PulseWid_100ms_t>(STATUS_8 | GetDeviceNumber(), EXPECTED_RESPONSE_TIMEOUT_MS)
#define PARAM_REQUEST 0x02041800
#define PARAM_RESPONSE 0x02041840
@@ -102,8 +111,11 @@
const int kParamArbIdValue = PARAM_RESPONSE;
const int kParamArbIdMask = 0xFFFFFFFF;
const double FLOAT_TO_FXP = (double)0x400000;
const double FXP_TO_FLOAT = 0.0000002384185791015625;
const double FLOAT_TO_FXP_10_22 = (double)0x400000;
const double FXP_TO_FLOAT_10_22 = 0.0000002384185791015625;
const double FLOAT_TO_FXP_0_8 = (double)0x100;
const double FXP_TO_FLOAT_0_8 = 0.00390625;
/* encoder/decoders */
/** control */
@@ -127,6 +139,7 @@ typedef struct _TALON_Control_2_Rates_OneShot_t {
unsigned Status2Ms:8;
unsigned Status3Ms:8;
unsigned Status4Ms:8;
unsigned StatusPulWidMs:8; // TALON_Status_8_PulseWid_100ms_t
} TALON_Control_2_Rates_OneShot_t ;
typedef struct _TALON_Control_3_ClearFlags_OneShot_t {
unsigned ZeroFeedbackSensor:1;
@@ -170,7 +183,9 @@ typedef struct _TALON_Status_2_Feedback_20ms_t {
unsigned StckyFault_UnderVoltage:1;
unsigned StckyFault_OverTemp:1;
unsigned Current_l2:2;
unsigned reserved:6;
unsigned reserved2:4;
unsigned VelDiv4:1;
unsigned PosDiv8:1;
unsigned ProfileSlotSelect:1;
unsigned BrakeIsEnabled:1;
} TALON_Status_2_Feedback_20ms_t ;
@@ -182,7 +197,9 @@ typedef struct _TALON_Status_3_Enc_100ms_t {
unsigned EncVelL:8;
unsigned EncIndexRiseEventsH:8;
unsigned EncIndexRiseEventsL:8;
unsigned reserved:5;
unsigned reserved:3;
unsigned VelDiv4:1;
unsigned PosDiv8:1;
unsigned QuadIdxpin:1;
unsigned QuadBpin:1;
unsigned QuadApin:1;
@@ -195,7 +212,9 @@ typedef struct _TALON_Status_4_AinTempVbat_100ms_t {
unsigned AnalogInVelL:8;
unsigned Temp:8;
unsigned BatteryV:8;
unsigned reserved:8;
unsigned reserved:6;
unsigned VelDiv4:1;
unsigned PosDiv8:1;
} TALON_Status_4_AinTempVbat_100ms_t ;
typedef struct _TALON_Status_5_Startup_OneShot_t {
unsigned ResetCountH:8;
@@ -228,6 +247,18 @@ typedef struct _TALON_Status_7_Debug_200ms_t {
unsigned TokenizationSucceses_h8:8;
unsigned TokenizationSucceses_l8:8;
} TALON_Status_7_Debug_200ms_t ;
typedef struct _TALON_Status_8_PulseWid_100ms_t {
unsigned PulseWidPositionH:8;
unsigned PulseWidPositionM:8;
unsigned PulseWidPositionL:8;
unsigned reserved:6;
unsigned VelDiv4:1;
unsigned PosDiv8:1;
unsigned PeriodUsM8:8;
unsigned PeriodUsL8:8;
unsigned PulseWidVelH:8;
unsigned PulseWidVelL:8;
} TALON_Status_8_PulseWid_100ms_t ;
typedef struct _TALON_Param_Request_t {
unsigned ParamEnum:8;
} TALON_Param_Request_t ;
@@ -239,7 +270,6 @@ typedef struct _TALON_Param_Response_t {
unsigned ParamValueH:8;
} TALON_Param_Response_t ;
CanTalonSRX::CanTalonSRX(int deviceNumber,int controlPeriodMs): CtreCanNode(deviceNumber), _can_h(0), _can_stat(0)
{
/* bound period to be within [1 ms,95 ms] */
@@ -255,11 +285,6 @@ CanTalonSRX::CanTalonSRX(int deviceNumber,int controlPeriodMs): CtreCanNode(devi
RegisterRx(STATUS_6 | (UINT8)deviceNumber );
RegisterRx(STATUS_7 | (UINT8)deviceNumber );
RegisterTx(CONTROL_1 | (UINT8)deviceNumber, (UINT8)controlPeriodMs);
/* default our frame rate table to what firmware defaults to. */
_statusRateMs[0] = 10; /* TALON_Status_1_General_10ms_t */
_statusRateMs[1] = 20; /* TALON_Status_2_Feedback_20ms_t */
_statusRateMs[2] = 100; /* TALON_Status_3_Enc_100ms_t */
_statusRateMs[3] = 100; /* TALON_Status_4_AinTempVbat_100ms_t */
/* the only default param that is nonzero is limit switch.
* Default to using the flash settings. */
SetOverrideLimitSwitchEn(kLimitSwitchOverride_UseDefaultsFromFlash);
@@ -268,8 +293,14 @@ CanTalonSRX::CanTalonSRX(int deviceNumber,int controlPeriodMs): CtreCanNode(devi
*/
CanTalonSRX::~CanTalonSRX()
{
if (m_hasBeenMoved) return;
RegisterTx(CONTROL_1 | (UINT8)GetDeviceNumber(), 0);
if (m_hasBeenMoved){
/* Another CANTalonSRX still exists, so
don't un-register the periodic control frame */
}else{
/* un-register the control frame so Talon is disabled */
RegisterTx(CONTROL_1 | (UINT8)GetDeviceNumber(), 0);
}
/* free the stream we used for SetParam/GetParamResponse */
if(_can_h){
FRC_NetworkCommunication_CANSessionMux_closeStreamSession(_can_h);
_can_h = 0;
@@ -408,14 +439,36 @@ CTR_Code CanTalonSRX::SetParam(param_t paramEnum, double value)
uint32_t urawbits;
value = std::min(value,1023.0); /* bounds check doubles that are outside u10.22 */
value = std::max(value,0.0);
urawbits = value * FLOAT_TO_FXP; /* perform unsign arithmetic */
urawbits = value * FLOAT_TO_FXP_10_22; /* perform unsign arithmetic */
rawbits = urawbits; /* copy bits over. SetParamRaw just stuffs into CAN frame with no sense of signedness */
} break;
case eProfileParamSlot1_F: /* signed 10.22 fixed pt value */
case eProfileParamSlot0_F:
value = std::min(value, 512.0); /* bounds check doubles that are outside s10.22 */
value = std::max(value,-512.0);
rawbits = value * FLOAT_TO_FXP;
rawbits = value * FLOAT_TO_FXP_10_22;
break;
case eProfileParamVcompRate: /* unsigned 0.8 fixed pt value volts per ms */
/* within [0,1) volts per ms.
Slowest ramp is 1/256 VperMilliSec or 3.072 seconds from 0-to-12V.
Fastest ramp is 255/256 VperMilliSec or 12.1ms from 0-to-12V.
*/
if(value <= 0){
/* negative or zero (disable), send raw value of zero */
rawbits = 0;
}else{
/* nonzero ramping */
rawbits = value * FLOAT_TO_FXP_0_8;
/* since whole part is cleared, cap to just under whole unit */
if(rawbits > (FLOAT_TO_FXP_0_8-1) )
rawbits = (FLOAT_TO_FXP_0_8-1);
/* since ramping is nonzero, cap to smallest ramp rate possible */
if(rawbits == 0){
/* caller is providing a nonzero ramp rate that's too small
to serialize, so cap to smallest possible */
rawbits = 1;
}
}
break;
default: /* everything else is integral */
rawbits = (int32_t)value;
@@ -439,7 +492,10 @@ CTR_Code CanTalonSRX::GetParamResponse(param_t paramEnum, double & value)
case eCurrent:
case eTemp:
case eBatteryV:
value = ((double)rawbits) * FXP_TO_FLOAT;
value = ((double)rawbits) * FXP_TO_FLOAT_10_22;
break;
case eProfileParamVcompRate:
value = ((double)rawbits) * FXP_TO_FLOAT_0_8;
break;
default: /* everything else is integral */
value = (double)rawbits;
@@ -494,6 +550,10 @@ CTR_Code CanTalonSRX::SetCloseLoopRampRate(unsigned slotIdx,int closeLoopRampRat
return SetParam(eProfileParamSlot0_CloseLoopRampRate, closeLoopRampRate);
return SetParam(eProfileParamSlot1_CloseLoopRampRate, closeLoopRampRate);
}
CTR_Code CanTalonSRX::SetVoltageCompensationRate(double voltagePerMs)
{
return SetParam(eProfileParamVcompRate, voltagePerMs);
}
CTR_Code CanTalonSRX::GetPgain(unsigned slotIdx,double & gain)
{
if(slotIdx == 0)
@@ -530,7 +590,10 @@ CTR_Code CanTalonSRX::GetCloseLoopRampRate(unsigned slotIdx,int & closeLoopRampR
return GetParamResponseInt32(eProfileParamSlot0_CloseLoopRampRate, closeLoopRampRate);
return GetParamResponseInt32(eProfileParamSlot1_CloseLoopRampRate, closeLoopRampRate);
}
CTR_Code CanTalonSRX::GetVoltageCompensationRate(double & voltagePerMs)
{
return GetParamResponse(eProfileParamVcompRate, voltagePerMs);
}
CTR_Code CanTalonSRX::SetSensorPosition(int pos)
{
return SetParam(eSensorPosition, pos);
@@ -572,39 +635,42 @@ CTR_Code CanTalonSRX::GetReverseSoftEnable(int & enable)
*/
CTR_Code CanTalonSRX::SetStatusFrameRate(unsigned frameEnum, unsigned periodMs)
{
int32_t status = 0;
CTR_Code retval = CTR_OKAY;
int32_t paramEnum = 0;
/* bounds check the period */
if(periodMs < 1)
periodMs = 1;
else if (periodMs > 255)
periodMs = 255;
uint8_t period = (uint8_t)periodMs;
/* tweak just the status messsage rate the caller cares about */
uint8_t period = (uint8_t)periodMs;
/* lookup the correct param enum based on what frame to rate-change */
switch(frameEnum){
case kStatusFrame_General:
_statusRateMs[0] = period;
paramEnum = eStatus1FrameRate;
break;
case kStatusFrame_Feedback:
_statusRateMs[1] = period;
paramEnum = eStatus2FrameRate;
break;
case kStatusFrame_Encoder:
_statusRateMs[2] = period;
paramEnum = eStatus3FrameRate;
break;
case kStatusFrame_AnalogTempVbat:
_statusRateMs[3] = period;
paramEnum = eStatus4FrameRate;
break;
case kStatusFrame_PulseWidthMeas:
paramEnum = eStatus8FrameRate;
break;
default:
/* caller's request is not support, return an error code */
retval = CTR_InvalidParamValue;
break;
}
/* build our request frame */
TALON_Control_2_Rates_OneShot_t frame;
memset(&frame,0,sizeof(frame));
frame.Status1Ms = _statusRateMs[0];
frame.Status2Ms = _statusRateMs[1];
frame.Status3Ms = _statusRateMs[2];
frame.Status4Ms = _statusRateMs[3];
FRC_NetworkCommunication_CANSessionMux_sendMessage(CONTROL_2 | GetDeviceNumber(), (const uint8_t*)&frame, sizeof(frame), 0, &status);
if(status)
return CTR_TxFailed;
return CTR_OKAY;
/* if lookup was succesful, send set-request out */
if(retval == CTR_OKAY){
/* paramEnum is updated, sent it out */
retval = SetParamRaw(paramEnum, period);
}
return retval;
}
/**
* Clear all sticky faults in TALON.
@@ -772,6 +838,8 @@ CTR_Code CanTalonSRX::GetSensorPosition(int &param)
raw |= rx->SensorPositionL;
raw <<= (32-24); /* sign extend */
raw >>= (32-24); /* sign extend */
if(rx->PosDiv8)
raw *= 8;
param = (int)raw;
return rx.err;
}
@@ -784,6 +852,8 @@ CTR_Code CanTalonSRX::GetSensorVelocity(int &param)
raw |= rx->SensorVelocityL;
raw <<= (32-16); /* sign extend */
raw >>= (32-16); /* sign extend */
if(rx->VelDiv4)
raw *= 4;
param = (int)raw;
return rx.err;
}
@@ -814,6 +884,8 @@ CTR_Code CanTalonSRX::GetEncPosition(int &param)
raw |= rx->EncPositionL;
raw <<= (32-24); /* sign extend */
raw >>= (32-24); /* sign extend */
if(rx->PosDiv8)
raw *= 8;
param = (int)raw;
return rx.err;
}
@@ -826,6 +898,8 @@ CTR_Code CanTalonSRX::GetEncVel(int &param)
raw |= rx->EncVelL;
raw <<= (32-16); /* sign extend */
raw >>= (32-16); /* sign extend */
if(rx->VelDiv4)
raw *= 4;
param = (int)raw;
return rx.err;
}
@@ -868,6 +942,8 @@ CTR_Code CanTalonSRX::GetAnalogInWithOv(int &param)
raw |= rx->AnalogInWithOvL;
raw <<= (32-24); /* sign extend */
raw >>= (32-24); /* sign extend */
if(rx->PosDiv8)
raw *= 8;
param = (int)raw;
return rx.err;
}
@@ -880,6 +956,8 @@ CTR_Code CanTalonSRX::GetAnalogInVel(int &param)
raw |= rx->AnalogInVelL;
raw <<= (32-16); /* sign extend */
raw >>= (32-16); /* sign extend */
if(rx->VelDiv4)
raw *= 4;
param = (int)raw;
return rx.err;
}
@@ -1018,6 +1096,82 @@ CTR_Code CanTalonSRX::SetRevFeedbackSensor(int param)
FlushTx(toFill);
return CTR_OKAY;
}
CTR_Code CanTalonSRX::GetPulseWidthPosition(int &param)
{
GET_STATUS8();
int32_t raw = 0;
raw |= rx->PulseWidPositionH;
raw <<= 8;
raw |= rx->PulseWidPositionM;
raw <<= 8;
raw |= rx->PulseWidPositionL;
raw <<= (32-24); /* sign extend */
raw >>= (32-24); /* sign extend */
if(rx->PosDiv8)
raw *= 8;
param = (int)raw;
return rx.err;
}
CTR_Code CanTalonSRX::GetPulseWidthVelocity(int &param)
{
GET_STATUS8();
int32_t raw = 0;
raw |= rx->PulseWidVelH;
raw <<= 8;
raw |= rx->PulseWidVelL;
raw <<= (32-16); /* sign extend */
raw >>= (32-16); /* sign extend */
if(rx->VelDiv4)
raw *= 4;
param = (int)raw;
return rx.err;
}
/**
* @param param [out] Rise to rise timeperiod in microseconds.
*/
CTR_Code CanTalonSRX::GetPulseWidthRiseToRiseUs(int &param)
{
GET_STATUS8();
uint32_t raw = 0;
raw |= rx->PeriodUsM8;
raw <<= 8;
raw |= rx->PeriodUsL8;
param = (int)raw;
return rx.err;
}
/**
* @param param [out] Rise to fall time period in microseconds.
*/
CTR_Code CanTalonSRX::GetPulseWidthRiseToFallUs(int &param)
{
int temp = 0;
int periodUs = 0;
/* first grab our 12.12 position */
CTR_Code retval1 = GetPulseWidthPosition(temp);
/* mask off number of turns */
temp &= 0xFFF;
/* next grab the waveform period. This value
* will be zero if we stop getting pulses **/
CTR_Code retval2 = GetPulseWidthRiseToRiseUs(periodUs);
/* now we have 0.12 position that is scaled to the waveform period.
Use fixed pt multiply to scale our 0.16 period into us.*/
param = (temp * periodUs) / BIT12;
/* pass the worst error code to caller.
Assume largest value is the most pressing error code.*/
return (CTR_Code)std::max((int)retval1, (int)retval2);
}
CTR_Code CanTalonSRX::IsPulseWidthSensorPresent(int &param)
{
int periodUs = 0;
CTR_Code retval = GetPulseWidthRiseToRiseUs(periodUs);
/* if a nonzero period is present, we are getting good pules.
Otherwise the sensor is not present. */
if(periodUs != 0)
param = 1;
else
param = 0;
return retval;
}
//------------------ C interface --------------------------------------------//
extern "C" {
void *c_TalonSRX_Create(int deviceNumber, int controlPeriodMs)

View File

@@ -33,13 +33,25 @@ class CANTalon : public MotorSafety,
AnalogPot = 2,
AnalogEncoder = 3,
EncRising = 4,
EncFalling = 5
EncFalling = 5,
CtreMagEncoder_Relative = 6, //!< Cross The Road Electronics Magnetic Encoder in Absolute/PulseWidth Mode
CtreMagEncoder_Absolute = 7, //!< Cross The Road Electronics Magnetic Encoder in Relative/Quadrature Mode
PulseWidth = 8,
};
/**
* Depending on the sensor type, Talon can determine if sensor is plugged in ot not.
*/
enum FeedbackDeviceStatus {
FeedbackStatusUnknown = 0, //!< Sensor status could not be determined. Not all sensors can do this.
FeedbackStatusPresent = 1, //!< Sensor is present and working okay.
FeedbackStatusNotPresent = 2, //!< Sensor is not present, not plugged in, not powered, etc...
};
enum StatusFrameRate {
StatusFrameRateGeneral = 0,
StatusFrameRateFeedback = 1,
StatusFrameRateQuadEncoder = 2,
StatusFrameRateAnalogTempVbat = 3,
StatusFrameRatePulseWidthMeas = 4,
};
explicit CANTalon(int deviceNumber);
explicit CANTalon(int deviceNumber, int controlPeriodMs);
@@ -89,10 +101,13 @@ class CANTalon : public MotorSafety,
virtual double GetPosition() const override;
virtual double GetSpeed() const override;
virtual int GetClosedLoopError() const;
virtual void SetAllowableClosedLoopErr(uint32_t allowableCloseLoopError);
virtual int GetAnalogIn() const;
virtual void SetAnalogPosition(int newPosition);
virtual int GetAnalogInRaw() const;
virtual int GetAnalogInVel() const;
virtual int GetEncPosition() const;
virtual void SetEncPosition(int);
virtual int GetEncVel() const;
int GetPinStateQuadA() const;
int GetPinStateQuadB() const;
@@ -101,12 +116,19 @@ class CANTalon : public MotorSafety,
int IsRevLimitSwitchClosed() const;
int GetNumberOfQuadIdxRises() const;
void SetNumberOfQuadIdxRises(int rises);
virtual int GetPulseWidthPosition() const;
virtual void SetPulseWidthPosition(int newpos);
virtual int GetPulseWidthVelocity() const;
virtual int GetPulseWidthRiseToFallUs() const;
virtual int GetPulseWidthRiseToRiseUs() const;
virtual FeedbackDeviceStatus IsSensorPresent(FeedbackDevice feedbackDevice)const;
virtual bool GetForwardLimitOK() const override;
virtual bool GetReverseLimitOK() const override;
virtual uint16_t GetFaults() const override;
uint16_t GetStickyFaults() const;
void ClearStickyFaults();
virtual void SetVoltageRampRate(double rampRate) override;
virtual void SetVoltageCompensationRampRate(double rampRate);
virtual uint32_t GetFirmwareVersion() const override;
virtual void ConfigNeutralMode(NeutralMode mode) override;
virtual void ConfigEncoderCodesPerRev(uint16_t codesPerRev) override;
@@ -140,12 +162,26 @@ class CANTalon : public MotorSafety,
*/
void ConfigRevLimitSwitchNormallyOpen(bool normallyOpen);
virtual void ConfigMaxOutputVoltage(double voltage) override;
void ConfigPeakOutputVoltage(double forwardVoltage,double reverseVoltage);
void ConfigNominalOutputVoltage(double forwardVoltage,double reverseVoltage);
/**
* Enables Talon SRX to automatically zero the Sensor Position whenever an
* edge is detected on the index signal.
* @param enable boolean input, pass true to enable feature or false to disable.
* @param risingEdge boolean input, pass true to clear the position on rising edge,
* pass false to clear the position on falling edge.
*/
void EnableZeroSensorPositionOnIndex(bool enable, bool risingEdge);
void ConfigSetParameter(uint32_t paramEnum, double value);
bool GetParameter(uint32_t paramEnum, double & dvalue) const;
virtual void ConfigFaultTime(float faultTime) override;
virtual void SetControlMode(ControlMode mode);
void SetFeedbackDevice(FeedbackDevice device);
void SetStatusFrameRateMs(StatusFrameRate stateFrame, int periodMs);
virtual ControlMode GetControlMode() const;
void SetSensorDirection(bool reverseSensor);
void SetClosedLoopOutputDirection(bool reverseOutput);
void SetCloseLoopRampRate(double rampRate);
void SelectProfileSlot(int slotIdx);
int GetIzone() const;
@@ -194,7 +230,39 @@ class CANTalon : public MotorSafety,
TalonControlMode m_sendMode;
double m_setPoint = 0;
/**
* Encoder CPR, counts per rotations, also called codes per revoluion.
* Default value of zero means the API behaves as it did during the 2015 season, each position
* unit is a single pulse and there are four pulses per count (4X).
* Caller can use ConfigEncoderCodesPerRev to set the quadrature encoder CPR.
*/
uint32_t m_codesPerRev = 0;
/**
* Number of turns per rotation. For example, a 10-turn pot spins ten full rotations from
* a wiper voltage of zero to 3.3 volts. Therefore knowing the
* number of turns a full voltage sweep represents is necessary for calculating rotations
* and velocity.
* A default value of zero means the API behaves as it did during the 2015 season, there are 1024
* position units from zero to 3.3V.
*/
uint32_t m_numPotTurns = 0;
/**
* Although the Talon handles feedback selection, caching the feedback selection is helpful at the API level
* for scaling into rotations and RPM.
*/
FeedbackDevice m_feedbackDevice = QuadEncoder;
static const unsigned int kDelayForSolicitedSignalsUs = 4000;
/**
* @param devToLookup FeedbackDevice to lookup the scalar for. Because Talon
* allows multiple sensors to be attached simultaneously, caller must
* specify which sensor to lookup.
* @return The number of native Talon units per rotation of the selected sensor.
* Zero if the necessary sensor information is not available.
* @see ConfigEncoderCodesPerRev
* @see ConfigPotentiometerTurns
*/
double GetNativeUnitsPerRotationScalar(FeedbackDevice devToLookup)const;
/**
* Fixup the sendMode so Set() serializes the correct demand value.
* Also fills the modeSelecet in the control frame to disabled.
@@ -202,6 +270,44 @@ class CANTalon : public MotorSafety,
* @see Set()
*/
void ApplyControlMode(CANSpeedController::ControlMode mode);
/**
* @param fullRotations double precision value representing number of rotations of selected feedback sensor.
* If user has never called the config routine for the selected sensor, then the caller
* is likely passing rotations in engineering units already, in which case it is returned
* as is.
* @see ConfigPotentiometerTurns
* @see ConfigEncoderCodesPerRev
* @return fullRotations in native engineering units of the Talon SRX firmware.
*/
int32_t ScaleRotationsToNativeUnits(FeedbackDevice devToLookup, double fullRotations) const;
/**
* @param rpm double precision value representing number of rotations per minute of selected feedback sensor.
* If user has never called the config routine for the selected sensor, then the caller
* is likely passing rotations in engineering units already, in which case it is returned
* as is.
* @see ConfigPotentiometerTurns
* @see ConfigEncoderCodesPerRev
* @return sensor velocity in native engineering units of the Talon SRX firmware.
*/
int32_t ScaleVelocityToNativeUnits(FeedbackDevice devToLookup, double rpm) const;
/**
* @param nativePos integral position of the feedback sensor in native Talon SRX units.
* If user has never called the config routine for the selected sensor, then the return
* will be in TALON SRX units as well to match the behavior in the 2015 season.
* @see ConfigPotentiometerTurns
* @see ConfigEncoderCodesPerRev
* @return double precision number of rotations, unless config was never performed.
*/
double ScaleNativeUnitsToRotations(FeedbackDevice devToLookup, int32_t nativePos) const;
/**
* @param nativeVel integral velocity of the feedback sensor in native Talon SRX units.
* If user has never called the config routine for the selected sensor, then the return
* will be in TALON SRX units as well to match the behavior in the 2015 season.
* @see ConfigPotentiometerTurns
* @see ConfigEncoderCodesPerRev
* @return double precision of sensor velocity in RPM, unless config was never performed.
*/
double ScaleNativeUnitsToRpm(FeedbackDevice devToLookup, int32_t nativeVel) const;
// LiveWindow stuff.
std::shared_ptr<ITable> m_table;

View File

@@ -8,6 +8,21 @@
#include "WPIErrors.h"
#include <unistd.h> // usleep
#include <sstream>
/**
* Number of adc engineering units per 0 to 3.3V sweep.
* This is necessary for scaling Analog Position in rotations/RPM.
*/
const double kNativeAdcUnitsPerRotation = 1024.0;
/**
* Number of pulse width engineering units per full rotation.
* This is necessary for scaling Pulse Width Decoded Position in rotations/RPM.
*/
const double kNativePwdUnitsPerRotation = 4096.0;
/**
* Number of minutes per 100ms unit. Useful for scaling velocities
* measured by Talon's 100ms timebase to rotations per minute.
*/
const double kMinutesPer100msUnit = 1.0/600.0;
/**
* Constructor for the CANTalon device.
@@ -25,20 +40,12 @@ CANTalon::CANTalon(int deviceNumber)
* Constructor for the CANTalon device.
* @param deviceNumber The CAN ID of the Talon SRX
* @param controlPeriodMs The period in ms to send the CAN control frame.
* Period is bounded to [1ms,
* 95ms].
* Period is bounded to [1ms,95ms].
*/
CANTalon::CANTalon(int deviceNumber, int controlPeriodMs)
: m_deviceNumber(deviceNumber),
m_impl(new CanTalonSRX(
deviceNumber,
controlPeriodMs)) /* bounded underneath to be within [1 ms,95 ms] */
,
m_safetyHelper(new MotorSafetyHelper(this)),
m_profile(0),
m_controlEnabled(true),
m_controlMode(kPercentVbus),
m_setPoint(0) {
m_impl(new CanTalonSRX(deviceNumber,controlPeriodMs)),
m_safetyHelper(new MotorSafetyHelper(this)) {
ApplyControlMode(m_controlMode);
m_impl->SetProfileSlotSelect(m_profile);
}
@@ -92,10 +99,10 @@ float CANTalon::Get() const {
return GetOutputCurrent();
case kSpeed:
m_impl->GetSensorVelocity(value);
return value;
return ScaleNativeUnitsToRpm(m_feedbackDevice, value);
case kPosition:
m_impl->GetSensorPosition(value);
return value;
return ScaleNativeUnitsToRotations(m_feedbackDevice, value);
case kPercentVbus:
case kFollower:
default:
@@ -123,7 +130,7 @@ void CANTalon::Set(float value, uint8_t syncGroup) {
/* feed safety helper since caller just updated our output */
m_safetyHelper->Feed();
if (m_controlEnabled) {
m_setPoint = value;
m_setPoint = value; /* cache set point for GetSetpoint() */
CTR_Code status = CTR_OKAY;
switch (m_controlMode) {
case CANSpeedController::kPercentVbus: {
@@ -135,20 +142,24 @@ void CANTalon::Set(float value, uint8_t syncGroup) {
} break;
case CANSpeedController::kVoltage: {
// Voltage is an 8.8 fixed point number.
int volts = int((m_isInverted ? value : -value) * 256);
int volts = int((m_isInverted ? -value : value) * 256);
status = m_impl->SetDemand(volts);
} break;
case CANSpeedController::kSpeed:
status = m_impl->SetDemand(m_isInverted ? -value : value);
/* if the caller has provided scaling info, apply it */
status = m_impl->SetDemand(ScaleVelocityToNativeUnits(m_feedbackDevice, m_isInverted ? -value : value));
break;
case CANSpeedController::kPosition:
status = m_impl->SetDemand(value);
status = m_impl->SetDemand(ScaleRotationsToNativeUnits(m_feedbackDevice, value));
break;
case CANSpeedController::kCurrent:
case CANSpeedController::kCurrent: {
double milliamperes = (m_isInverted ? -value : value) * 1000.0; /* mA*/
status = m_impl->SetDemand(milliamperes);
} break;
default:
wpi_setWPIErrorWithContext(
IncompatibleMode,
"The CAN Talon does not support Current Mode at this time.");
"The CAN Talon does not support this control mode.");
break;
}
if (status != CTR_OKAY) {
@@ -259,7 +270,7 @@ void CANTalon::SetF(double f) {
}
/**
* Set the Izone to a nonzero value to auto clear the integral accumulator
* when the absolute value of CloseLoopError exceeds Izone.
* when the absolute value of CloseLoopError exceeds Izone.
*
* @see SelectProfileSlot to choose between the two sets of gains.
*/
@@ -312,8 +323,11 @@ void CANTalon::SetPID(double p, double i, double d, double f) {
/**
* Select the feedback device to use in closed-loop
*/
void CANTalon::SetFeedbackDevice(FeedbackDevice device) {
CTR_Code status = m_impl->SetFeedbackDeviceSelect((int)device);
void CANTalon::SetFeedbackDevice(FeedbackDevice feedbackDevice) {
/* save the selection so that future setters/getters know which scalars to apply */
m_feedbackDevice = feedbackDevice;
/* pass feedback to actual CAN frame */
CTR_Code status = m_impl->SetFeedbackDeviceSelect((int)feedbackDevice);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
@@ -501,26 +515,31 @@ float CANTalon::GetTemperature() const {
* Continuous sensors (like analog encoderes) can also partially be set (the
* portion of the postion based on overflows).
*/
void CANTalon::SetPosition(double pos) { m_impl->SetSensorPosition(pos); }
void CANTalon::SetPosition(double pos) {
int32_t nativePos = ScaleRotationsToNativeUnits(m_feedbackDevice, pos);
CTR_Code status = m_impl->SetSensorPosition(nativePos);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* TODO documentation (see CANJaguar.cpp)
*
* @return The position of the sensor currently providing feedback.
* When using analog sensors, 0 units corresponds to 0V, 1023
* When using analog sensors, 0 units corresponds to 0V, 1023
* units corresponds to 3.3V
* When using an analog encoder (wrapping around 1023 => 0 is
* When using an analog encoder (wrapping around 1023 => 0 is
* possible) the units are still 3.3V per 1023 units.
* When using quadrature, each unit is a quadrature edge (4X)
* When using quadrature, each unit is a quadrature edge (4X)
* mode.
*/
double CANTalon::GetPosition() const {
int postition;
CTR_Code status = m_impl->GetSensorPosition(postition);
int32_t position;
CTR_Code status = m_impl->GetSensorPosition(position);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
return (double)postition;
return ScaleNativeUnitsToRotations(m_feedbackDevice, position);
}
/**
* If sensor and motor are out of phase, sensor can be inverted
@@ -533,7 +552,23 @@ void CANTalon::SetSensorDirection(bool reverseSensor) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* Flips the sign (multiplies by negative one) the throttle values going into
* the motor on the talon in closed loop modes. Typically the application
* should use SetSensorDirection to keep sensor and motor in phase.
* @see SetSensorDirection
* However this routine is helpful for reversing the motor direction
* when Talon is in slave mode, or when using a single-direction position
* sensor in a closed-loop mode.
*
* @param reverseOutput True if motor output should be flipped; False if not.
*/
void CANTalon::SetClosedLoopOutputDirection(bool reverseOutput) {
CTR_Code status = m_impl->SetRevMotDuringCloseLoopEn(reverseOutput ? 1 : 0);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* Returns the current error in the controller.
*
@@ -541,12 +576,31 @@ void CANTalon::SetSensorDirection(bool reverseSensor) {
*/
int CANTalon::GetClosedLoopError() const {
int error;
/* retrieve the closed loop error in native units */
CTR_Code status = m_impl->GetCloseLoopErr(error);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
return error;
}
/**
* Set the allowable closed loop error.
* @param allowableCloseLoopError allowable closed loop error for selected profile.
* mA for Curent closed loop.
* Talon Native Units for position and velocity.
*/
void CANTalon::SetAllowableClosedLoopErr(uint32_t allowableCloseLoopError)
{
/* grab param enum */
CanTalonSRX::param_t param;
if (m_profile == 1) {
param = CanTalonSRX::eProfileParamSlot1_AllowableClosedLoopErr;
} else {
param = CanTalonSRX::eProfileParamSlot0_AllowableClosedLoopErr;
}
/* send allowable close loop er in native units */
ConfigSetParameter(param, allowableCloseLoopError);
}
/**
* TODO documentation (see CANJaguar.cpp)
@@ -556,26 +610,24 @@ int CANTalon::GetClosedLoopError() const {
* The speed units will be in the sensor's native ticks per 100ms.
*
* For analog sensors, 3.3V corresponds to 1023 units.
* So a speed of 200 equates to ~0.645 dV per 100ms or 6.451 dV per
* So a speed of 200 equates to ~0.645 dV per 100ms or 6.451 dV per
* second.
* If this is an analog encoder, that likely means 1.9548 rotations
* If this is an analog encoder, that likely means 1.9548 rotations
* per sec.
* For quadrature encoders, each unit corresponds a quadrature edge (4X).
* So a 250 count encoder will produce 1000 edge events per
* So a 250 count encoder will produce 1000 edge events per
* rotation.
* An example speed of 200 would then equate to 20% of a rotation
* An example speed of 200 would then equate to 20% of a rotation
* per 100ms,
* or 10 rotations per second.
* or 10 rotations per second.
*/
double CANTalon::GetSpeed() const {
int speed;
// TODO convert from int to appropriate units (or at least document it).
int32_t speed;
CTR_Code status = m_impl->GetSensorVelocity(speed);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
return (double)speed;
return ScaleNativeUnitsToRpm(m_feedbackDevice, speed);
}
/**
@@ -583,10 +635,8 @@ double CANTalon::GetSpeed() const {
* whether it is actually being used for feedback.
*
* @returns The 24bit analog value. The bottom ten bits is the ADC (0 - 1023)
* on
* the analog pin of the Talon.
* The upper 14 bits
* tracks the overflows and
* on the analog pin of the Talon.
* The upper 14 bits tracks the overflows and
* underflows (continuous sensor).
*/
int CANTalon::GetAnalogIn() const {
@@ -597,6 +647,13 @@ int CANTalon::GetAnalogIn() const {
}
return position;
}
void CANTalon::SetAnalogPosition(int newPosition) {
CTR_Code status = m_impl->SetParam(CanTalonSRX::eAinPosition, newPosition);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* Get the position of whatever is in the analog pin of the Talon, regardless of
* whether it is actually being used for feedback.
@@ -633,6 +690,12 @@ int CANTalon::GetEncPosition() const {
}
return position;
}
void CANTalon::SetEncPosition(int newPosition) {
CTR_Code status = m_impl->SetParam(CanTalonSRX::eEncPosition, newPosition);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* Get the position of whatever is in the analog pin of the Talon, regardless of
@@ -648,6 +711,84 @@ int CANTalon::GetEncVel() const {
}
return vel;
}
int CANTalon::GetPulseWidthPosition() const {
int param;
CTR_Code status = m_impl->GetPulseWidthPosition(param);
if (status != CTR_OKAY)
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return param;
}
void CANTalon::SetPulseWidthPosition(int newPosition)
{
CTR_Code status = m_impl->SetParam(CanTalonSRX::ePwdPosition, newPosition);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
int CANTalon::GetPulseWidthVelocity()const
{
int param;
CTR_Code status = m_impl->GetPulseWidthVelocity(param);
if (status != CTR_OKAY)
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return param;
}
int CANTalon::GetPulseWidthRiseToFallUs()const
{
int param;
CTR_Code status = m_impl->GetPulseWidthRiseToFallUs(param);
if (status != CTR_OKAY)
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return param;
}
int CANTalon::GetPulseWidthRiseToRiseUs()const
{
int param;
CTR_Code status = m_impl->GetPulseWidthRiseToRiseUs(param);
if (status != CTR_OKAY)
wpi_setErrorWithContext(status, getHALErrorMessage(status));
return param;
}
/**
* @param which feedback sensor to check it if is connected.
* @return status of caller's specified sensor type.
*/
CANTalon::FeedbackDeviceStatus CANTalon::IsSensorPresent(FeedbackDevice feedbackDevice)const
{
FeedbackDeviceStatus retval = FeedbackStatusUnknown;
int param;
/* detecting sensor health depends on which sensor caller cares about */
switch (feedbackDevice) {
case QuadEncoder:
case AnalogPot:
case AnalogEncoder:
case EncRising:
case EncFalling:
/* no real good way to tell if these sensor
are actually present so return status unknown. */
break;
case PulseWidth:
case CtreMagEncoder_Relative:
case CtreMagEncoder_Absolute:
/* all of these require pulse width signal to be present. */
CTR_Code status = m_impl->IsPulseWidthSensorPresent(param);
if (status != CTR_OKAY) {
/* we're not getting status info, signal unknown status */
} else {
/* param is updated */
if (param) {
/* pulse signal is present, sensor must be working since it always
generates a pulse waveform.*/
retval = FeedbackStatusPresent;
} else {
/* no pulse present, sensor disconnected */
retval = FeedbackStatusNotPresent;
}
}
break;
}
return retval;
}
/**
* @return IO level of QUADA pin.
*/
@@ -899,6 +1040,15 @@ void CANTalon::SetVoltageRampRate(double rampRate) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
void CANTalon::SetVoltageCompensationRampRate(double rampRate) {
/* when in voltage compensation mode, the voltage compensation rate
directly caps the change in target voltage */
CTR_Code status = CTR_OKAY;
status = m_impl->SetVoltageCompensationRate(rampRate / 1000);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* Sets a voltage change rate that applies only when a close loop contorl mode
* is enabled.
@@ -933,8 +1083,8 @@ uint32_t CANTalon::GetFirmwareVersion() const {
/* only sent once on boot */
// CTR_Code status = m_impl->GetFirmVers(firmwareVersion);
// if(status != CTR_OKAY) {
// wpi_setErrorWithContext(status, getHALErrorMessage(status));
// if (status != CTR_OKAY) {
// wpi_setErrorWithContext(status, getHALErrorMessage(status));
//}
return firmwareVersion;
@@ -1003,19 +1153,31 @@ int CANTalon::GetBrakeEnableDuringNeutral() const {
return brakeEn;
}
/**
* @deprecated not implemented
* Configure how many codes per revolution are generated by your encoder.
*
* @param codesPerRev The number of counts per revolution.
*/
void CANTalon::ConfigEncoderCodesPerRev(uint16_t codesPerRev) {
/* TALON SRX does not scale units, they are raw from the sensor. Unit scaling
* can be done in API or by caller */
/* first save the scalar so that all getters/setter work as the user expects */
m_codesPerRev = codesPerRev;
/* next send the scalar to the Talon over CAN. This is so that the Talon can report
it to whoever needs it, like the webdash. Don't bother checking the return,
this is only for instrumentation and is not necessary for Talon functionality. */
(void)m_impl->SetParam(CanTalonSRX::eNumberEncoderCPR, m_codesPerRev);
}
/**
* @deprecated not implemented
* Configure the number of turns on the potentiometer.
*
* @param turns The number of turns of the potentiometer.
*/
void CANTalon::ConfigPotentiometerTurns(uint16_t turns) {
/* TALON SRX does not scale units, they are raw from the sensor. Unit scaling
* can be done in API or by caller */
/* first save the scalar so that all getters/setter work as the user expects */
m_numPotTurns = turns;
/* next send the scalar to the Talon over CAN. This is so that the Talon can report
it to whoever needs it, like the webdash. Don't bother checking the return,
this is only for instrumentation and is not necessary for Talon functionality. */
(void)m_impl->SetParam(CanTalonSRX::eNumberPotTurns, m_numPotTurns);
}
/**
@@ -1107,7 +1269,8 @@ void CANTalon::ConfigLimitMode(LimitMode mode) {
*/
void CANTalon::ConfigForwardLimit(double forwardLimitPosition) {
CTR_Code status = CTR_OKAY;
status = m_impl->SetForwardSoftLimit(forwardLimitPosition);
int32_t nativeLimitPos = ScaleRotationsToNativeUnits(m_feedbackDevice, forwardLimitPosition);
status = m_impl->SetForwardSoftLimit(nativeLimitPos);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
@@ -1153,19 +1316,80 @@ void CANTalon::ConfigRevLimitSwitchNormallyOpen(bool normallyOpen) {
*/
void CANTalon::ConfigReverseLimit(double reverseLimitPosition) {
CTR_Code status = CTR_OKAY;
status = m_impl->SetReverseSoftLimit(reverseLimitPosition);
int32_t nativeLimitPos = ScaleRotationsToNativeUnits(m_feedbackDevice, reverseLimitPosition);
status = m_impl->SetReverseSoftLimit(nativeLimitPos);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* TODO documentation (see CANJaguar.cpp)
*/
void CANTalon::ConfigMaxOutputVoltage(double voltage) {
/* SRX does not support max output */
wpi_setWPIErrorWithContext(IncompatibleMode,
"MaxOutputVoltage not supported.");
/* config peak throttle when in closed-loop mode in the fwd and rev direction. */
ConfigPeakOutputVoltage(voltage, -voltage);
}
void CANTalon::ConfigPeakOutputVoltage(double forwardVoltage,double reverseVoltage) {
/* bounds checking */
if (forwardVoltage > 12)
forwardVoltage = 12;
else if (forwardVoltage < 0)
forwardVoltage = 0;
if (reverseVoltage > 0)
reverseVoltage = 0;
else if (reverseVoltage < -12)
reverseVoltage = -12;
/* config calls */
ConfigSetParameter(CanTalonSRX::ePeakPosOutput, 1023 * forwardVoltage / 12.0);
ConfigSetParameter(CanTalonSRX::ePeakNegOutput, 1023 * reverseVoltage / 12.0);
}
void CANTalon::ConfigNominalOutputVoltage(double forwardVoltage,double reverseVoltage) {
/* bounds checking */
if (forwardVoltage > 12)
forwardVoltage = 12;
else if (forwardVoltage < 0)
forwardVoltage = 0;
if (reverseVoltage > 0)
reverseVoltage = 0;
else if (reverseVoltage < -12)
reverseVoltage = -12;
/* config calls */
ConfigSetParameter(CanTalonSRX::eNominalPosOutput,1023*forwardVoltage/12.0);
ConfigSetParameter(CanTalonSRX::eNominalNegOutput,1023*reverseVoltage/12.0);
}
/**
* General set frame. Since the parameter is a general integral type, this can
* be used for testing future features.
*/
void CANTalon::ConfigSetParameter(uint32_t paramEnum, double value) {
CTR_Code status;
/* config peak throttle when in closed-loop mode in the positive direction. */
status = m_impl->SetParam((CanTalonSRX::param_t)paramEnum,value);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* General get frame. Since the parameter is a general integral type, this can
* be used for testing future features.
*/
bool CANTalon::GetParameter(uint32_t paramEnum, double & dvalue) const {
bool retval = true;
/* send the request frame */
CTR_Code status = m_impl->RequestParam((CanTalonSRX::param_t)paramEnum);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
retval = false;
}
/* small yield for getting response */
usleep(kDelayForSolicitedSignalsUs);
/* get the last received update */
status = m_impl->GetParamResponse((CanTalonSRX::param_t)paramEnum, dvalue);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
retval = false;
}
return retval;
}
/**
@@ -1252,7 +1476,198 @@ void CANTalon::SetSafetyEnabled(bool enabled) {
void CANTalon::GetDescription(std::ostringstream& desc) const {
desc << "CANTalon ID " << m_deviceNumber;
}
/**
* @param devToLookup FeedbackDevice to lookup the scalar for. Because Talon
* allows multiple sensors to be attached simultaneously, caller must
* specify which sensor to lookup.
* @return The number of native Talon units per rotation of the selected sensor.
* Zero if the necessary sensor information is not available.
* @see ConfigEncoderCodesPerRev
* @see ConfigPotentiometerTurns
*/
double CANTalon::GetNativeUnitsPerRotationScalar(FeedbackDevice devToLookup)const
{
bool scalingAvail = false;
CTR_Code status = CTR_OKAY;
double retval = 0;
switch (devToLookup) {
case QuadEncoder:
{ /* When caller wants to lookup Quadrature, the QEI may be in 1x if the selected feedback is edge counter.
* Additionally if the quadrature source is the CTRE Mag encoder, then the CPR is known.
* This is nice in that the calling app does not require knowing the CPR at all.
* So do both checks here.
*/
int32_t qeiPulsePerCount = 4; /* default to 4x */
switch (m_feedbackDevice) {
case CtreMagEncoder_Relative:
case CtreMagEncoder_Absolute:
/* we assume the quadrature signal comes from the MagEnc,
of which we know the CPR already */
retval = kNativePwdUnitsPerRotation;
scalingAvail = true;
break;
case EncRising: /* Talon's QEI is setup for 1x, so perform 1x math */
case EncFalling:
qeiPulsePerCount = 1;
break;
case QuadEncoder: /* Talon's QEI is 4x */
default: /* pulse width and everything else, assume its regular quad use. */
break;
}
if (scalingAvail) {
/* already deduced the scalar above, we're done. */
} else {
/* we couldn't deduce the scalar just based on the selection */
if (0 == m_codesPerRev) {
/* caller has never set the CPR. Most likely caller
is just using engineering units so fall to the
bottom of this func.*/
} else {
/* Talon expects PPR units */
retval = qeiPulsePerCount * m_codesPerRev;
scalingAvail = true;
}
}
} break;
case EncRising:
case EncFalling:
if (0 == m_codesPerRev) {
/* caller has never set the CPR. Most likely caller
is just using engineering units so fall to the
bottom of this func.*/
} else {
/* Talon expects PPR units */
retval = 1 * m_codesPerRev;
scalingAvail = true;
}
break;
case AnalogPot:
case AnalogEncoder:
if (0 == m_numPotTurns) {
/* caller has never set the CPR. Most likely caller
is just using engineering units so fall to the
bottom of this func.*/
} else {
retval = (double)kNativeAdcUnitsPerRotation / m_numPotTurns;
scalingAvail = true;
}
break;
case CtreMagEncoder_Relative:
case CtreMagEncoder_Absolute:
case PulseWidth:
retval = kNativePwdUnitsPerRotation;
scalingAvail = true;
break;
}
/* handle any detected errors */
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
/* if scaling information is not possible, signal caller
by returning zero */
if (false == scalingAvail)
retval = 0;
return retval;
}
/**
* @param fullRotations double precision value representing number of rotations of selected feedback sensor.
* If user has never called the config routine for the selected sensor, then the caller
* is likely passing rotations in engineering units already, in which case it is returned
* as is.
* @see ConfigPotentiometerTurns
* @see ConfigEncoderCodesPerRev
* @return fullRotations in native engineering units of the Talon SRX firmware.
*/
int32_t CANTalon::ScaleRotationsToNativeUnits(FeedbackDevice devToLookup,double fullRotations)const
{
/* first assume we don't have config info, prep the default return */
int32_t retval = (int32_t)fullRotations;
/* retrieve scaling info */
double scalar = GetNativeUnitsPerRotationScalar(devToLookup);
/* apply scalar if its available */
if (scalar > 0)
retval = (int32_t)(fullRotations*scalar);
return retval;
}
/**
* @param rpm double precision value representing number of rotations per minute of selected feedback sensor.
* If user has never called the config routine for the selected sensor, then the caller
* is likely passing rotations in engineering units already, in which case it is returned
* as is.
* @see ConfigPotentiometerTurns
* @see ConfigEncoderCodesPerRev
* @return sensor velocity in native engineering units of the Talon SRX firmware.
*/
int32_t CANTalon::ScaleVelocityToNativeUnits(FeedbackDevice devToLookup,double rpm)const
{
/* first assume we don't have config info, prep the default return */
int32_t retval = (int32_t)rpm;
/* retrieve scaling info */
double scalar = GetNativeUnitsPerRotationScalar(devToLookup);
/* apply scalar if its available */
if (scalar > 0)
retval = (int32_t)(rpm * kMinutesPer100msUnit * scalar);
return retval;
}
/**
* @param nativePos integral position of the feedback sensor in native Talon SRX units.
* If user has never called the config routine for the selected sensor, then the return
* will be in TALON SRX units as well to match the behavior in the 2015 season.
* @see ConfigPotentiometerTurns
* @see ConfigEncoderCodesPerRev
* @return double precision number of rotations, unless config was never performed.
*/
double CANTalon::ScaleNativeUnitsToRotations(FeedbackDevice devToLookup,int32_t nativePos)const
{
/* first assume we don't have config info, prep the default return */
double retval = (double)nativePos;
/* retrieve scaling info */
double scalar = GetNativeUnitsPerRotationScalar(devToLookup);
/* apply scalar if its available */
if (scalar > 0)
retval = ((double)nativePos) / scalar;
return retval;
}
/**
* @param nativeVel integral velocity of the feedback sensor in native Talon SRX units.
* If user has never called the config routine for the selected sensor, then the return
* will be in TALON SRX units as well to match the behavior in the 2015 season.
* @see ConfigPotentiometerTurns
* @see ConfigEncoderCodesPerRev
* @return double precision of sensor velocity in RPM, unless config was never performed.
*/
double CANTalon::ScaleNativeUnitsToRpm(FeedbackDevice devToLookup, int32_t nativeVel)const
{
/* first assume we don't have config info, prep the default return */
double retval = (double)nativeVel;
/* retrieve scaling info */
double scalar = GetNativeUnitsPerRotationScalar(devToLookup);
/* apply scalar if its available */
if (scalar > 0)
retval = (double)(nativeVel) / (scalar*kMinutesPer100msUnit);
return retval;
}
/**
* Enables Talon SRX to automatically zero the Sensor Position whenever an
* edge is detected on the index signal.
* @param enable boolean input, pass true to enable feature or false to disable.
* @param risingEdge boolean input, pass true to clear the position on rising edge,
* pass false to clear the position on falling edge.
*/
void CANTalon::EnableZeroSensorPositionOnIndex(bool enable, bool risingEdge)
{
if (enable) {
/* enable the feature, update the edge polarity first to ensure
it is correct before the feature is enabled. */
ConfigSetParameter(CanTalonSRX::eQuadIdxPolarity,risingEdge ? 1 : 0);
ConfigSetParameter(CanTalonSRX::eClearPositionOnIdx,1);
} else {
/* disable the feature first, then update the edge polarity. */
ConfigSetParameter(CanTalonSRX::eClearPositionOnIdx,0);
ConfigSetParameter(CanTalonSRX::eQuadIdxPolarity,risingEdge ? 1 : 0);
}
}
/**
* Common interface for inverting direction of a speed controller.
* Only works in PercentVbus, speed, and Voltage modes.

View File

@@ -14,6 +14,21 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
private MotorSafetyHelper m_safetyHelper;
private boolean isInverted = false;
protected PIDSourceType m_pidSource = PIDSourceType.kDisplacement;
/**
* Number of adc engineering units per 0 to 3.3V sweep.
* This is necessary for scaling Analog Position in rotations/RPM.
*/
private final int kNativeAdcUnitsPerRotation = 1024;
/**
* Number of pulse width engineering units per full rotation.
* This is necessary for scaling Pulse Width Decoded Position in rotations/RPM.
*/
private final double kNativePwdUnitsPerRotation = 4096.0;
/**
* Number of minutes per 100ms unit. Useful for scaling velocities
* measured by Talon's 100ms timebase to rotations per minute.
*/
private final double kMinutesPer100msUnit = 1.0/600.0;
public enum TalonControlMode implements CANSpeedController.ControlMode {
PercentVbus(0), Position(1), Speed(2), Current(3), Voltage(4), Follower(5), Disabled(15);
@@ -44,9 +59,8 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
return value;
}
}
public enum FeedbackDevice {
QuadEncoder(0), AnalogPot(2), AnalogEncoder(3), EncRising(4), EncFalling(5);
QuadEncoder(0), AnalogPot(2), AnalogEncoder(3), EncRising(4), EncFalling(5), CtreMagEncoder_Relative(6), CtreMagEncoder_Absolute(7), PulseWidth(8);
public int value;
@@ -64,9 +78,27 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
this.value = value;
}
}
/**
* Depending on the sensor type, Talon can determine if sensor is plugged in ot not.
*/
public enum FeedbackDeviceStatus {
FeedbackStatusUnknown(0), FeedbackStatusPresent(1), FeedbackStatusNotPresent(2);
public int value;
public static FeedbackDeviceStatus valueOf(int value) {
for (FeedbackDeviceStatus mode : values()) {
if (mode.value == value) {
return mode;
}
}
return null;
}
private FeedbackDeviceStatus(int value) {
this.value = value;
}
}
/** enumerated types for frame rate ms */
public enum StatusFrameRate {
General(0), Feedback(1), QuadEncoder(2), AnalogTempVbat(3);
General(0), Feedback(1), QuadEncoder(2), AnalogTempVbat(3), PulseWidth(4);
public int value;
public static StatusFrameRate valueOf(int value) {
@@ -95,6 +127,27 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
int m_profile;
double m_setPoint;
/**
* Encoder CPR, counts per rotations, also called codes per revoluion.
* Default value of zero means the API behaves as it did during the 2015 season, each position
* unit is a single pulse and there are four pulses per count (4X).
* Caller can use configEncoderCodesPerRev to set the quadrature encoder CPR.
*/
int m_codesPerRev;
/**
* Number of turns per rotation. For example, a 10-turn pot spins ten full rotations from
* a wiper voltage of zero to 3.3 volts. Therefore knowing the
* number of turns a full voltage sweep represents is necessary for calculating rotations
* and velocity.
* A default value of zero means the API behaves as it did during the 2015 season, there are 1024
* position units from zero to 3.3V.
*/
int m_numPotTurns;
/**
* Although the Talon handles feedback selection, caching the feedback selection is helpful at the API level
* for scaling into rotations and RPM.
*/
FeedbackDevice m_feedbackDevice;
public CANTalon(int deviceNumber) {
m_deviceNumber = deviceNumber;
@@ -103,6 +156,9 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
m_controlEnabled = true;
m_profile = 0;
m_setPoint = 0;
m_codesPerRev = 0;
m_numPotTurns = 0;
m_feedbackDevice = FeedbackDevice.QuadEncoder;
setProfile(m_profile);
applyControlMode(TalonControlMode.PercentVbus);
}
@@ -118,6 +174,9 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
m_controlEnabled = true;
m_profile = 0;
m_setPoint = 0;
m_codesPerRev = 0;
m_numPotTurns = 0;
m_feedbackDevice = FeedbackDevice.QuadEncoder;
setProfile(m_profile);
applyControlMode(TalonControlMode.PercentVbus);
}
@@ -171,7 +230,7 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
/* feed safety helper since caller just updated our output */
m_safetyHelper.feed();
if (m_controlEnabled) {
m_setPoint = outputValue;
m_setPoint = outputValue; /* cache set point for getSetpoint() */
switch (m_controlMode) {
case PercentVbus:
m_impl.Set(isInverted ? -outputValue : outputValue);
@@ -185,10 +244,14 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
m_impl.SetDemand(volts);
break;
case Speed:
m_impl.SetDemand((int) (isInverted ? -outputValue : outputValue));
m_impl.SetDemand(ScaleVelocityToNativeUnits(m_feedbackDevice,(isInverted ? -outputValue : outputValue)));
break;
case Position:
m_impl.SetDemand((int) outputValue);
m_impl.SetDemand(ScaleRotationsToNativeUnits(m_feedbackDevice,outputValue));
break;
case Current:
double milliamperes = (isInverted ? -outputValue : outputValue) * 1000.0; /* mA*/
m_impl.SetDemand((int)milliamperes);
break;
default:
break;
@@ -303,24 +366,31 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
* @return The current sensor value of the Talon.
*/
public double get() {
double retval = 0;
long valuep = CanTalonJNI.new_intp();
SWIGTYPE_p_int swigp = new SWIGTYPE_p_int(valuep, true);
switch (m_controlMode) {
case Voltage:
return getOutputVoltage();
retval = getOutputVoltage();
break;
case Current:
return getOutputCurrent();
retval = getOutputCurrent();
break;
case Speed:
m_impl.GetSensorVelocity(swigp);
return (double) CanTalonJNI.intp_value(valuep);
retval = ScaleNativeUnitsToRpm(m_feedbackDevice,CanTalonJNI.intp_value(valuep));
break;
case Position:
m_impl.GetSensorPosition(swigp);
return (double) CanTalonJNI.intp_value(valuep);
retval = ScaleNativeUnitsToRotations(m_feedbackDevice,CanTalonJNI.intp_value(valuep));
break;
case PercentVbus:
default:
m_impl.GetAppliedThrottle(swigp);
return (double) CanTalonJNI.intp_value(valuep) / 1023.0;
retval = (double) CanTalonJNI.intp_value(valuep) / 1023.0;
break;
}
return retval;
}
/**
@@ -336,6 +406,10 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
return CanTalonJNI.intp_value(valuep);
}
public void setEncPosition(int newPosition) {
setParameter(CanTalonSRX.param_t.eEncPosition, newPosition);
}
/**
* Get the current encoder velocity, regardless of whether it is the current
* feedback device.
@@ -348,7 +422,68 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
m_impl.GetEncVel(swigp);
return CanTalonJNI.intp_value(valuep);
}
public int getPulseWidthPosition() {
long valuep = CanTalonJNI.new_intp();
SWIGTYPE_p_int swigp = new SWIGTYPE_p_int(valuep, true);
m_impl.GetPulseWidthPosition(swigp);
return CanTalonJNI.intp_value(valuep);
}
public void setPulseWidthPosition(int newPosition) {
setParameter(CanTalonSRX.param_t.ePwdPosition, newPosition);
}
public int getPulseWidthVelocity() {
long valuep = CanTalonJNI.new_intp();
SWIGTYPE_p_int swigp = new SWIGTYPE_p_int(valuep, true);
m_impl.GetPulseWidthVelocity(swigp);
return CanTalonJNI.intp_value(valuep);
}
public int getPulseWidthRiseToFallUs() {
long valuep = CanTalonJNI.new_intp();
SWIGTYPE_p_int swigp = new SWIGTYPE_p_int(valuep, true);
m_impl.GetPulseWidthRiseToFallUs(swigp);
return CanTalonJNI.intp_value(valuep);
}
public int getPulseWidthRiseToRiseUs() {
long valuep = CanTalonJNI.new_intp();
SWIGTYPE_p_int swigp = new SWIGTYPE_p_int(valuep, true);
m_impl.GetPulseWidthRiseToRiseUs(swigp);
return CanTalonJNI.intp_value(valuep);
}
/**
* @param which feedback sensor to check it if is connected.
* @return status of caller's specified sensor type.
*/
public FeedbackDeviceStatus isSensorPresent(FeedbackDevice feedbackDevice) {
FeedbackDeviceStatus retval = FeedbackDeviceStatus.FeedbackStatusUnknown;
/* detecting sensor health depends on which sensor caller cares about */
switch(feedbackDevice){
case QuadEncoder:
case AnalogPot:
case AnalogEncoder:
case EncRising:
case EncFalling:
/* no real good way to tell if these sensor
are actually present so return status unknown. */
break;
case PulseWidth:
case CtreMagEncoder_Relative:
case CtreMagEncoder_Absolute:
/* all of these require pulse width signal to be present. */
long valuep = CanTalonJNI.new_intp();
SWIGTYPE_p_int swigp = new SWIGTYPE_p_int(valuep, true);
SWIGTYPE_p_CTR_Code status = m_impl.IsPulseWidthSensorPresent(swigp);
/* TODO: add a check for CanTalonJNI.CTR_Codep_value(status) */
if( CanTalonJNI.intp_value(valuep) == 0 ){
/* Talon not getting a signal */
retval = FeedbackDeviceStatus.FeedbackStatusNotPresent;
}else{
/* getting good signal */
retval = FeedbackDeviceStatus.FeedbackStatusPresent;
}
break;
}
return retval;
}
/**
* Get the number of of rising edges seen on the index pin.
*
@@ -391,6 +526,9 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
return CanTalonJNI.intp_value(valuep);
}
public void setAnalogPosition(int newPosition){
setParameter(CanTalonSRX.param_t.eAinPosition, (double)newPosition);
}
/**
* Get the current analog in position, regardless of whether it is the current
* feedback device.
@@ -436,10 +574,25 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
*/
public int getClosedLoopError() {
long valuep = CanTalonJNI.new_intp();
/* retrieve the closed loop error in native units */
SWIGTYPE_p_int swigp = new SWIGTYPE_p_int(valuep, true);
m_impl.GetCloseLoopErr(swigp);
return CanTalonJNI.intp_value(valuep);
}
/**
* Set the allowable closed loop error.
* @param allowableCloseLoopError allowable closed loop error for selected profile.
* mA for Curent closed loop.
* Talon Native Units for position and velocity.
*/
public void setAllowableClosedLoopErr(int allowableCloseLoopError)
{
if(m_profile == 0){
setParameter(CanTalonSRX.param_t.eProfileParamSlot0_AllowableClosedLoopErr, (double)allowableCloseLoopError);
}else{
setParameter(CanTalonSRX.param_t.eProfileParamSlot1_AllowableClosedLoopErr, (double)allowableCloseLoopError);
}
}
// Returns true if limit switch is closed. false if open.
public boolean isFwdLimitSwitchClosed() {
@@ -465,6 +618,32 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
return (CanTalonJNI.intp_value(valuep) == 0) ? false : true;
}
/**
* Configure how many codes per revolution are generated by your encoder.
*
* @param codesPerRev The number of counts per revolution.
*/
public void configEncoderCodesPerRev(int codesPerRev) {
/* first save the scalar so that all getters/setter work as the user expects */
m_codesPerRev = codesPerRev;
/* next send the scalar to the Talon over CAN. This is so that the Talon can report
it to whoever needs it, like the webdash. Don't bother checking the return,
this is only for instrumentation and is not necessary for Talon functionality. */
setParameter(CanTalonSRX.param_t.eNumberEncoderCPR, m_codesPerRev);
}
/**
* Configure the number of turns on the potentiometer.
*
* @param turns The number of turns of the potentiometer.
*/
public void configPotentiometerTurns(int turns) {
/* first save the scalar so that all getters/setter work as the user expects */
m_numPotTurns = turns;
/* next send the scalar to the Talon over CAN. This is so that the Talon can report
it to whoever needs it, like the webdash. Don't bother checking the return,
this is only for instrumentation and is not necessary for Talon functionality. */
setParameter(CanTalonSRX.param_t.eNumberPotTurns, m_numPotTurns);
}
/**
* Returns temperature of Talon, in degrees Celsius.
*/
@@ -521,11 +700,12 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
public double getPosition() {
long positionp = CanTalonJNI.new_intp();
m_impl.GetSensorPosition(new SWIGTYPE_p_int(positionp, true));
return CanTalonJNI.intp_value(positionp);
return ScaleNativeUnitsToRotations(m_feedbackDevice,CanTalonJNI.intp_value(positionp));
}
public void setPosition(double pos) {
m_impl.SetSensorPosition((int) pos);
int nativePos = ScaleRotationsToNativeUnits(m_feedbackDevice,pos);
m_impl.SetSensorPosition(nativePos);
}
/**
@@ -546,7 +726,7 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
public double getSpeed() {
long speedp = CanTalonJNI.new_intp();
m_impl.GetSensorVelocity(new SWIGTYPE_p_int(speedp, true));
return CanTalonJNI.intp_value(speedp);
return ScaleNativeUnitsToRpm(m_feedbackDevice,CanTalonJNI.intp_value(speedp));
}
public TalonControlMode getControlMode() {
@@ -586,6 +766,9 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
}
public void setFeedbackDevice(FeedbackDevice device) {
/* save the selection so that future setters/getters know which scalars to apply */
m_feedbackDevice = device;
/* pass feedback to actual CAN frame */
m_impl.SetFeedbackDeviceSelect(device.value);
}
@@ -864,6 +1047,9 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
m_impl.SetRampThrottle(rate);
}
public void setVoltageCompensationRampRate(double rampRate) {
m_impl.SetVoltageCompensationRate(rampRate / 1000);
}
/**
* Clear the accumulator for I gain.
*/
@@ -948,8 +1134,9 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
SWIGTYPE_p_CTR_Code status = m_impl.SetParam(CanTalonSRX.param_t.ePidIaccum, 0);
}
public void setForwardSoftLimit(int forwardLimit) {
m_impl.SetForwardSoftLimit(forwardLimit);
public void setForwardSoftLimit(double forwardLimit) {
int nativeLimitPos = ScaleRotationsToNativeUnits(m_feedbackDevice,forwardLimit);
m_impl.SetForwardSoftLimit(nativeLimitPos);
}
public int getForwardSoftLimit() {
@@ -968,8 +1155,9 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
return (CanTalonJNI.intp_value(valuep) == 0) ? false : true;
}
public void setReverseSoftLimit(int reverseLimit) {
m_impl.SetReverseSoftLimit(reverseLimit);
public void setReverseSoftLimit(double reverseLimit) {
int nativeLimitPos = ScaleRotationsToNativeUnits(m_feedbackDevice,reverseLimit);
m_impl.SetReverseSoftLimit(nativeLimitPos);
}
public int getReverseSoftLimit() {
@@ -987,7 +1175,70 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
m_impl.GetReverseSoftEnable(new SWIGTYPE_p_int(valuep, true));
return (CanTalonJNI.intp_value(valuep) == 0) ? false : true;
}
/**
* Configure the maximum voltage that the Jaguar will ever output.
*
* This can be used to limit the maximum output voltage in all modes so that
* motors which cannot withstand full bus voltage can be used safely.
*
* @param voltage The maximum voltage output by the Jaguar.
*/
public void configMaxOutputVoltage(double voltage) {
/* config peak throttle when in closed-loop mode in the fwd and rev direction. */
configPeakOutputVoltage(voltage, -voltage);
}
public void configPeakOutputVoltage(double forwardVoltage,double reverseVoltage) {
/* bounds checking */
if(forwardVoltage > 12)
forwardVoltage = 12;
else if(forwardVoltage < 0)
forwardVoltage = 0;
if(reverseVoltage > 0)
reverseVoltage = 0;
else if(reverseVoltage < -12)
reverseVoltage = -12;
/* config calls */
setParameter(CanTalonSRX.param_t.ePeakPosOutput,1023*forwardVoltage/12.0);
setParameter(CanTalonSRX.param_t.ePeakNegOutput,1023*reverseVoltage/12.0);
}
public void configNominalOutputVoltage(double forwardVoltage,double reverseVoltage) {
/* bounds checking */
if(forwardVoltage > 12)
forwardVoltage = 12;
else if(forwardVoltage < 0)
forwardVoltage = 0;
if(reverseVoltage > 0)
reverseVoltage = 0;
else if(reverseVoltage < -12)
reverseVoltage = -12;
/* config calls */
setParameter(CanTalonSRX.param_t.eNominalPosOutput,1023*forwardVoltage/12.0);
setParameter(CanTalonSRX.param_t.eNominalNegOutput,1023*reverseVoltage/12.0);
}
/**
* General set frame. Since the parameter is a general integral type, this can
* be used for testing future features.
*/
public void setParameter(CanTalonSRX.param_t paramEnum, double value){
SWIGTYPE_p_CTR_Code status = m_impl.SetParam(paramEnum,value);
/* TODO: error report to driver station */
}
/**
* General get frame. Since the parameter is a general integral type, this can
* be used for testing future features.
*/
public double getParameter(CanTalonSRX.param_t paramEnum) {
/* transmit a request for this param */
m_impl.RequestParam(paramEnum);
/* Briefly wait for new values from the Talon. */
Timer.delay(kDelayForSolicitedSignals);
/* poll out latest response value */
long pp = CanTalonJNI.new_doublep();
SWIGTYPE_p_CTR_Code status = m_impl.GetParamResponse(paramEnum, new SWIGTYPE_p_double(pp, true));
/* pass latest value back to caller */
return CanTalonJNI.doublep_value(pp);
}
public void clearStickyFaults() {
m_impl.ClearStickyFaults();
}
@@ -1110,8 +1361,186 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
m_impl.GetStckyFault_RevSoftLim(new SWIGTYPE_p_int(valuep, true));
return CanTalonJNI.intp_value(valuep);
}
/**
* @return Number of native units per rotation if scaling info is available.
* Zero if scaling information is not available.
*/
double GetNativeUnitsPerRotationScalar(FeedbackDevice devToLookup)
{
double retval = 0;
boolean scalingAvail = false;
switch(devToLookup){
case QuadEncoder:
{ /* When caller wants to lookup Quadrature, the QEI may be in 1x if the selected feedback is edge counter.
* Additionally if the quadrature source is the CTRE Mag encoder, then the CPR is known.
* This is nice in that the calling app does not require knowing the CPR at all.
* So do both checks here.
*/
int qeiPulsePerCount = 4; /* default to 4x */
switch(m_feedbackDevice){
case CtreMagEncoder_Relative:
case CtreMagEncoder_Absolute:
/* we assume the quadrature signal comes from the MagEnc,
of which we know the CPR already */
retval = kNativePwdUnitsPerRotation;
scalingAvail = true;
break;
case EncRising: /* Talon's QEI is setup for 1x, so perform 1x math */
case EncFalling:
qeiPulsePerCount = 1;
break;
case QuadEncoder: /* Talon's QEI is 4x */
default: /* pulse width and everything else, assume its regular quad use. */
break;
}
if(scalingAvail){
/* already deduced the scalar above, we're done. */
}else{
/* we couldn't deduce the scalar just based on the selection */
if(0 == m_codesPerRev){
/* caller has never set the CPR. Most likely caller
is just using engineering units so fall to the
bottom of this func.*/
}else{
/* Talon expects PPR units */
retval = 4 * m_codesPerRev;
scalingAvail = true;
}
}
} break;
case EncRising:
case EncFalling:
if(0 == m_codesPerRev){
/* caller has never set the CPR. Most likely caller
is just using engineering units so fall to the
bottom of this func.*/
}else{
/* Talon expects PPR units */
retval = 1 * m_codesPerRev;
scalingAvail = true;
}
break;
case AnalogPot:
case AnalogEncoder:
if(0 == m_numPotTurns){
/* caller has never set the CPR. Most likely caller
is just using engineering units so fall to the
bottom of this func.*/
}else {
retval = (double)kNativeAdcUnitsPerRotation / m_numPotTurns;
scalingAvail = true;
}
break;
case CtreMagEncoder_Relative:
case CtreMagEncoder_Absolute:
case PulseWidth:
retval = kNativePwdUnitsPerRotation;
scalingAvail = true;
break;
}
/* if scaling info is not available give caller zero */
if(false == scalingAvail)
return 0;
return retval;
}
/**
* @param fullRotations double precision value representing number of rotations of selected feedback sensor.
* If user has never called the config routine for the selected sensor, then the caller
* is likely passing rotations in engineering units already, in which case it is returned
* as is.
* @see configPotentiometerTurns
* @see configEncoderCodesPerRev
* @return fullRotations in native engineering units of the Talon SRX firmware.
*/
int ScaleRotationsToNativeUnits(FeedbackDevice devToLookup, double fullRotations)
{
/* first assume we don't have config info, prep the default return */
int retval = (int)fullRotations;
/* retrieve scaling info */
double scalar = GetNativeUnitsPerRotationScalar(devToLookup);
/* apply scalar if its available */
if(scalar > 0)
retval = (int)(fullRotations*scalar);
return retval;
}
/**
* @param rpm double precision value representing number of rotations per minute of selected feedback sensor.
* If user has never called the config routine for the selected sensor, then the caller
* is likely passing rotations in engineering units already, in which case it is returned
* as is.
* @see configPotentiometerTurns
* @see configEncoderCodesPerRev
* @return sensor velocity in native engineering units of the Talon SRX firmware.
*/
int ScaleVelocityToNativeUnits(FeedbackDevice devToLookup, double rpm)
{
/* first assume we don't have config info, prep the default return */
int retval = (int)rpm;
/* retrieve scaling info */
double scalar = GetNativeUnitsPerRotationScalar(devToLookup);
/* apply scalar if its available */
if(scalar > 0)
retval = (int)(rpm * kMinutesPer100msUnit * scalar);
return retval;
}
/**
* @param nativePos integral position of the feedback sensor in native Talon SRX units.
* If user has never called the config routine for the selected sensor, then the return
* will be in TALON SRX units as well to match the behavior in the 2015 season.
* @see configPotentiometerTurns
* @see configEncoderCodesPerRev
* @return double precision number of rotations, unless config was never performed.
*/
double ScaleNativeUnitsToRotations(FeedbackDevice devToLookup, int nativePos)
{
/* first assume we don't have config info, prep the default return */
double retval = (double)nativePos;
/* retrieve scaling info */
double scalar = GetNativeUnitsPerRotationScalar(devToLookup);
/* apply scalar if its available */
if(scalar > 0)
retval = ((double)nativePos) / scalar;
return retval;
}
/**
* @param nativeVel integral velocity of the feedback sensor in native Talon SRX units.
* If user has never called the config routine for the selected sensor, then the return
* will be in TALON SRX units as well to match the behavior in the 2015 season.
* @see configPotentiometerTurns
* @see configEncoderCodesPerRev
* @return double precision of sensor velocity in RPM, unless config was never performed.
*/
double ScaleNativeUnitsToRpm(FeedbackDevice devToLookup, long nativeVel)
{
/* first assume we don't have config info, prep the default return */
double retval = (double)nativeVel;
/* retrieve scaling info */
double scalar = GetNativeUnitsPerRotationScalar(devToLookup);
/* apply scalar if its available */
if(scalar > 0)
retval = (double)(nativeVel) / (scalar*kMinutesPer100msUnit);
return retval;
}
/**
* Enables Talon SRX to automatically zero the Sensor Position whenever an
* edge is detected on the index signal.
* @param enable boolean input, pass true to enable feature or false to disable.
* @param risingEdge boolean input, pass true to clear the position on rising edge,
* pass false to clear the position on falling edge.
*/
public void enableZeroSensorPositionOnIndex(boolean enable, boolean risingEdge) {
if(enable){
/* enable the feature, update the edge polarity first to ensure
it is correct before the feature is enabled. */
setParameter(CanTalonSRX.param_t.eQuadIdxPolarity,risingEdge ? 1 : 0);
setParameter(CanTalonSRX.param_t.eClearPositionOnIdx,1);
}else{
/* disable the feature first, then update the edge polarity. */
setParameter(CanTalonSRX.param_t.eClearPositionOnIdx,0);
setParameter(CanTalonSRX.param_t.eQuadIdxPolarity,risingEdge ? 1 : 0);
}
}
@Override
public void setExpiration(double timeout) {
m_safetyHelper.setExpiration(timeout);

View File

@@ -104,9 +104,12 @@ public class CanTalonSRX extends CtreCanNode {
slotIdx, closeLoopRampRate), true);
}
public SWIGTYPE_p_CTR_Code SetVoltageCompensationRate(double vpers) {
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_SetVoltageCompensationRate(swigCPtr, this,vpers), true);
}
public SWIGTYPE_p_CTR_Code SetSensorPosition(int pos) {
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_SetSensorPosition(swigCPtr, this, pos),
true);
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_SetSensorPosition(swigCPtr, this, pos),true);
}
public SWIGTYPE_p_CTR_Code SetForwardSoftLimit(int forwardLimit) {
@@ -159,6 +162,11 @@ public class CanTalonSRX extends CtreCanNode {
slotIdx, SWIGTYPE_p_int.getCPtr(closeLoopRampRate)), true);
}
public SWIGTYPE_p_CTR_Code GetVoltageCompensationRate(SWIGTYPE_p_double vpers) {
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_GetVoltageCompensationRate(swigCPtr, this,
SWIGTYPE_p_double.getCPtr(vpers)), true);
}
public SWIGTYPE_p_CTR_Code GetForwardSoftLimit(SWIGTYPE_p_int forwardLimit) {
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_GetForwardSoftLimit(swigCPtr, this,
SWIGTYPE_p_int.getCPtr(forwardLimit)), true);
@@ -417,6 +425,27 @@ public class CanTalonSRX extends CtreCanNode {
param), true);
}
public SWIGTYPE_p_CTR_Code GetPulseWidthPosition(SWIGTYPE_p_int param) {
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_GetPulseWidthPosition(swigCPtr, this,
SWIGTYPE_p_int.getCPtr(param)), true);
}
public SWIGTYPE_p_CTR_Code GetPulseWidthVelocity(SWIGTYPE_p_int param) {
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_GetPulseWidthVelocity(swigCPtr, this,
SWIGTYPE_p_int.getCPtr(param)), true);
}
public SWIGTYPE_p_CTR_Code GetPulseWidthRiseToFallUs(SWIGTYPE_p_int param) {
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_GetPulseWidthRiseToFallUs(swigCPtr, this,
SWIGTYPE_p_int.getCPtr(param)), true);
}
public SWIGTYPE_p_CTR_Code GetPulseWidthRiseToRiseUs(SWIGTYPE_p_int param) {
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_GetPulseWidthRiseToRiseUs(swigCPtr, this,
SWIGTYPE_p_int.getCPtr(param)), true);
}
public SWIGTYPE_p_CTR_Code IsPulseWidthSensorPresent(SWIGTYPE_p_int param) {
return new SWIGTYPE_p_CTR_Code(CanTalonJNI.CanTalonSRX_IsPulseWidthSensorPresent(swigCPtr, this,
SWIGTYPE_p_int.getCPtr(param)), true);
}
public final static int kDefaultControlPeriodMs = CanTalonJNI
.CanTalonSRX_kDefaultControlPeriodMs_get();
public final static int kMode_DutyCycle = CanTalonJNI.CanTalonSRX_kMode_DutyCycle_get();
@@ -467,6 +496,8 @@ public class CanTalonSRX extends CtreCanNode {
public final static int kStatusFrame_Encoder = CanTalonJNI.CanTalonSRX_kStatusFrame_Encoder_get();
public final static int kStatusFrame_AnalogTempVbat = CanTalonJNI
.CanTalonSRX_kStatusFrame_AnalogTempVbat_get();
public final static int kStatusFrame_PulseWidthMeas = CanTalonJNI
.CanTalonSRX_kStatusFrame_PulseWidthMeas_get();
public final static class param_t {
public final static CanTalonSRX.param_t eProfileParamSlot0_P = new CanTalonSRX.param_t(
@@ -610,6 +641,49 @@ public class CanTalonSRX extends CtreCanNode {
public final static CanTalonSRX.param_t ePidIaccum = new CanTalonSRX.param_t("ePidIaccum",
CanTalonJNI.CanTalonSRX_ePidIaccum_get());
public final static CanTalonSRX.param_t eStatus1FrameRate = new CanTalonSRX.param_t("eStatus1FrameRate",
CanTalonJNI.CanTalonSRX_eStatus1FrameRate_get());
public final static CanTalonSRX.param_t eStatus2FrameRate = new CanTalonSRX.param_t("eStatus2FrameRate",
CanTalonJNI.CanTalonSRX_eStatus2FrameRate_get());
public final static CanTalonSRX.param_t eStatus3FrameRate = new CanTalonSRX.param_t("eStatus3FrameRate",
CanTalonJNI.CanTalonSRX_eStatus3FrameRate_get());
public final static CanTalonSRX.param_t eStatus4FrameRate = new CanTalonSRX.param_t("eStatus4FrameRate",
CanTalonJNI.CanTalonSRX_eStatus4FrameRate_get());
public final static CanTalonSRX.param_t eStatus6FrameRate = new CanTalonSRX.param_t("eStatus6FrameRate",
CanTalonJNI.CanTalonSRX_eStatus6FrameRate_get());
public final static CanTalonSRX.param_t eStatus7FrameRate = new CanTalonSRX.param_t("eStatus7FrameRate",
CanTalonJNI.CanTalonSRX_eStatus7FrameRate_get());
public final static CanTalonSRX.param_t eClearPositionOnIdx = new CanTalonSRX.param_t("eClearPositionOnIdx",
CanTalonJNI.CanTalonSRX_eClearPositionOnIdx_get());
public final static CanTalonSRX.param_t ePeakPosOutput = new CanTalonSRX.param_t("ePeakPosOutput",
CanTalonJNI.CanTalonSRX_ePeakPosOutput_get());
public final static CanTalonSRX.param_t eNominalPosOutput = new CanTalonSRX.param_t("eNominalPosOutput",
CanTalonJNI.CanTalonSRX_eNominalPosOutput_get());
public final static CanTalonSRX.param_t ePeakNegOutput = new CanTalonSRX.param_t("ePeakNegOutput",
CanTalonJNI.CanTalonSRX_ePeakNegOutput_get());
public final static CanTalonSRX.param_t eNominalNegOutput = new CanTalonSRX.param_t("eNominalNegOutput",
CanTalonJNI.CanTalonSRX_eNominalNegOutput_get());
public final static CanTalonSRX.param_t eQuadIdxPolarity = new CanTalonSRX.param_t("eQuadIdxPolarity",
CanTalonJNI.CanTalonSRX_eQuadIdxPolarity_get());
public final static CanTalonSRX.param_t eStatus8FrameRate = new CanTalonSRX.param_t("eStatus8FrameRate",
CanTalonJNI.CanTalonSRX_eStatus8FrameRate_get());
public final static CanTalonSRX.param_t eAllowPosOverflow = new CanTalonSRX.param_t("eAllowPosOverflow",
CanTalonJNI.CanTalonSRX_eAllowPosOverflow_get());
public final static CanTalonSRX.param_t eProfileParamSlot0_AllowableClosedLoopErr = new CanTalonSRX.param_t("eProfileParamSlot0_AllowableClosedLoopErr",
CanTalonJNI.CanTalonSRX_eProfileParamSlot0_AllowableClosedLoopErr_get());
public final static CanTalonSRX.param_t eNumberPotTurns = new CanTalonSRX.param_t("eNumberPotTurns",
CanTalonJNI.CanTalonSRX_eNumberPotTurns_get());
public final static CanTalonSRX.param_t eNumberEncoderCPR = new CanTalonSRX.param_t("eNumberEncoderCPR",
CanTalonJNI.CanTalonSRX_eNumberEncoderCPR_get());
public final static CanTalonSRX.param_t ePwdPosition = new CanTalonSRX.param_t("ePwdPosition",
CanTalonJNI.CanTalonSRX_ePwdPosition_get());
public final static CanTalonSRX.param_t eAinPosition = new CanTalonSRX.param_t("eAinPosition",
CanTalonJNI.CanTalonSRX_eAinPosition_get());
public final static CanTalonSRX.param_t eProfileParamVcompRate = new CanTalonSRX.param_t("eProfileParamVcompRate",
CanTalonJNI.CanTalonSRX_eProfileParamVcompRate_get());
public final static CanTalonSRX.param_t eProfileParamSlot1_AllowableClosedLoopErr = new CanTalonSRX.param_t("eProfileParamSlot1_AllowableClosedLoopErr",
CanTalonJNI.CanTalonSRX_eProfileParamSlot1_AllowableClosedLoopErr_get());
public final int swigValue() {
return swigValue;
}

View File

@@ -153,6 +153,8 @@ public class CanTalonJNI {
public final static native int CanTalonSRX_kStatusFrame_AnalogTempVbat_get();
public final static native int CanTalonSRX_kStatusFrame_PulseWidthMeas_get();
public final static native int CanTalonSRX_eProfileParamSlot0_P_get();
public final static native int CanTalonSRX_eProfileParamSlot0_I_get();
@@ -283,6 +285,48 @@ public class CanTalonJNI {
public final static native int CanTalonSRX_ePidIaccum_get();
public final static native int CanTalonSRX_eStatus1FrameRate_get();
public final static native int CanTalonSRX_eStatus2FrameRate_get();
public final static native int CanTalonSRX_eStatus3FrameRate_get();
public final static native int CanTalonSRX_eStatus4FrameRate_get();
public final static native int CanTalonSRX_eStatus6FrameRate_get();
public final static native int CanTalonSRX_eStatus7FrameRate_get();
public final static native int CanTalonSRX_eClearPositionOnIdx_get();
public final static native int CanTalonSRX_ePeakPosOutput_get();
public final static native int CanTalonSRX_eNominalPosOutput_get();
public final static native int CanTalonSRX_ePeakNegOutput_get();
public final static native int CanTalonSRX_eNominalNegOutput_get();
public final static native int CanTalonSRX_eQuadIdxPolarity_get();
public final static native int CanTalonSRX_eStatus8FrameRate_get();
public final static native int CanTalonSRX_eAllowPosOverflow_get();
public final static native int CanTalonSRX_eProfileParamSlot0_AllowableClosedLoopErr_get();
public final static native int CanTalonSRX_eNumberPotTurns_get();
public final static native int CanTalonSRX_eNumberEncoderCPR_get();
public final static native int CanTalonSRX_ePwdPosition_get();
public final static native int CanTalonSRX_eAinPosition_get();
public final static native int CanTalonSRX_eProfileParamVcompRate_get();
public final static native int CanTalonSRX_eProfileParamSlot1_AllowableClosedLoopErr_get();
public final static native long CanTalonSRX_SetParam(long jarg1, CanTalonSRX jarg1_, int jarg2,
double jarg3);
@@ -345,6 +389,9 @@ public class CanTalonJNI {
public final static native long CanTalonSRX_GetCloseLoopRampRate(long jarg1, CanTalonSRX jarg1_,
long jarg2, long jarg3);
public final static native long CanTalonSRX_GetVoltageCompensationRate(long jarg1,
CanTalonSRX jarg1_, long jarg2);
public final static native long CanTalonSRX_GetForwardSoftLimit(long jarg1, CanTalonSRX jarg1_,
long jarg2);
@@ -489,8 +536,21 @@ public class CanTalonJNI {
public final static native long CanTalonSRX_SetRampThrottle(long jarg1, CanTalonSRX jarg1_,
int jarg2);
public final static native long CanTalonSRX_SetVoltageCompensationRate(long jarg1, CanTalonSRX jarg1_,
double jarg2);
public final static native long CanTalonSRX_SetRevFeedbackSensor(long jarg1, CanTalonSRX jarg1_,
int jarg2);
public final static native long CanTalonSRX_GetPulseWidthPosition(long jarg1, CanTalonSRX jarg1_, long jarg2);
public final static native long CanTalonSRX_GetPulseWidthVelocity(long jarg1, CanTalonSRX jarg1_, long jarg2);
public final static native long CanTalonSRX_GetPulseWidthRiseToFallUs(long jarg1, CanTalonSRX jarg1_, long jarg2);
public final static native long CanTalonSRX_GetPulseWidthRiseToRiseUs(long jarg1, CanTalonSRX jarg1_, long jarg2);
public final static native long CanTalonSRX_IsPulseWidthSensorPresent(long jarg1, CanTalonSRX jarg1_, long jarg2);
public final static native long CanTalonSRX_SWIGUpcast(long jarg1);
}

View File

@@ -1293,6 +1293,18 @@ SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1kStatusFrame_1PulseWidthMeas_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
int result;
(void)jenv;
(void)jcls;
result = (int)CanTalonSRX::kStatusFrame_PulseWidthMeas;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eProfileParamSlot0_1P_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
@@ -2073,6 +2085,240 @@ SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eStatus1FrameRate_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eStatus1FrameRate;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eStatus2FrameRate_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eStatus2FrameRate;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eStatus3FrameRate_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eStatus3FrameRate;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eStatus4FrameRate_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eStatus4FrameRate;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eStatus6FrameRate_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eStatus6FrameRate;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eStatus7FrameRate_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eStatus7FrameRate;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eClearPositionOnIdx_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eClearPositionOnIdx;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1ePeakPosOutput_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::ePeakPosOutput;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eNominalPosOutput_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eNominalPosOutput;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1ePeakNegOutput_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::ePeakNegOutput;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eNominalNegOutput_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eNominalNegOutput;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eQuadIdxPolarity_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eQuadIdxPolarity;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eStatus8FrameRate_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eStatus8FrameRate;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eAllowPosOverflow_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eAllowPosOverflow;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eProfileParamSlot0_1AllowableClosedLoopErr_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eProfileParamSlot0_AllowableClosedLoopErr;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eNumberPotTurns_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eNumberPotTurns;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eNumberEncoderCPR_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eNumberEncoderCPR;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1ePwdPosition_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::ePwdPosition;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eAinPosition_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eAinPosition;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eProfileParamVcompRate_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eProfileParamVcompRate;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1eProfileParamSlot1_1AllowableClosedLoopErr_1get(JNIEnv *jenv, jclass jcls) {
jint jresult = 0 ;
CanTalonSRX::_param_t result;
(void)jenv;
(void)jcls;
result = (CanTalonSRX::_param_t)CanTalonSRX::eProfileParamSlot1_AllowableClosedLoopErr;
jresult = (jint)result;
return jresult;
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1SetParam(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2, jdouble jarg3) {
jlong jresult = 0 ;
CanTalonSRX *arg1 = (CanTalonSRX *) 0 ;
@@ -2491,6 +2737,25 @@ SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_
return jresult;
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1GetVoltageCompensationRate(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2) {
jlong jresult = 0 ;
CanTalonSRX *arg1 = (CanTalonSRX *) 0 ;
double *arg2 = 0 ;
CTR_Code result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CanTalonSRX **)&jarg1;
arg2 = *(double **)&jarg2;
if (!arg2) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "double & reference is null");
return 0;
}
result = (arg1)->GetVoltageCompensationRate(*arg2);
*(CTR_Code **)&jresult = new CTR_Code((const CTR_Code &)result);
return jresult;
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1GetForwardSoftLimit(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2) {
jlong jresult = 0 ;
@@ -3523,6 +3788,23 @@ SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1SetVoltageCompensationRate(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jdouble jarg2) {
jlong jresult = 0 ;
CanTalonSRX *arg1 = (CanTalonSRX *) 0 ;
double arg2 ;
CTR_Code result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CanTalonSRX **)&jarg1;
arg2 = (double)jarg2;
result = (arg1)->SetVoltageCompensationRate(arg2);
*(CTR_Code **)&jresult = new CTR_Code((const CTR_Code &)result);
return jresult;
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1SetRevFeedbackSensor(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) {
jlong jresult = 0 ;
CanTalonSRX *arg1 = (CanTalonSRX *) 0 ;
@@ -3540,6 +3822,111 @@ SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1GetPulseWidthPosition(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2) {
jlong jresult = 0 ;
CanTalonSRX *arg1 = (CanTalonSRX *) 0 ;
int *arg2 = 0 ;
CTR_Code result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CanTalonSRX **)&jarg1;
arg2 = *(int **)&jarg2;
if (!arg2) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "int & reference is null");
return 0;
}
result = (arg1)->GetPulseWidthPosition(*arg2);
*(CTR_Code **)&jresult = new CTR_Code((const CTR_Code &)result);
return jresult;
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1GetPulseWidthVelocity(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2) {
jlong jresult = 0 ;
CanTalonSRX *arg1 = (CanTalonSRX *) 0 ;
int *arg2 = 0 ;
CTR_Code result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CanTalonSRX **)&jarg1;
arg2 = *(int **)&jarg2;
if (!arg2) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "int & reference is null");
return 0;
}
result = (arg1)->GetPulseWidthVelocity(*arg2);
*(CTR_Code **)&jresult = new CTR_Code((const CTR_Code &)result);
return jresult;
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1GetPulseWidthRiseToFallUs(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2) {
jlong jresult = 0 ;
CanTalonSRX *arg1 = (CanTalonSRX *) 0 ;
int *arg2 = 0 ;
CTR_Code result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CanTalonSRX **)&jarg1;
arg2 = *(int **)&jarg2;
if (!arg2) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "int & reference is null");
return 0;
}
result = (arg1)->GetPulseWidthRiseToFallUs(*arg2);
*(CTR_Code **)&jresult = new CTR_Code((const CTR_Code &)result);
return jresult;
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1GetPulseWidthRiseToRiseUs(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2) {
jlong jresult = 0 ;
CanTalonSRX *arg1 = (CanTalonSRX *) 0 ;
int *arg2 = 0 ;
CTR_Code result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CanTalonSRX **)&jarg1;
arg2 = *(int **)&jarg2;
if (!arg2) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "int & reference is null");
return 0;
}
result = (arg1)->GetPulseWidthRiseToRiseUs(*arg2);
*(CTR_Code **)&jresult = new CTR_Code((const CTR_Code &)result);
return jresult;
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1IsPulseWidthSensorPresent(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2) {
jlong jresult = 0 ;
CanTalonSRX *arg1 = (CanTalonSRX *) 0 ;
int *arg2 = 0 ;
CTR_Code result;
(void)jenv;
(void)jcls;
(void)jarg1_;
arg1 = *(CanTalonSRX **)&jarg1;
arg2 = *(int **)&jarg2;
if (!arg2) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "int & reference is null");
return 0;
}
result = (arg1)->IsPulseWidthSensorPresent(*arg2);
*(CTR_Code **)&jresult = new CTR_Code((const CTR_Code &)result);
return jresult;
}
SWIGEXPORT jlong JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_CanTalonSRX_1SWIGUpcast(JNIEnv *jenv, jclass jcls, jlong jarg1) {
jlong baseptr = 0;
(void)jenv;