Compare commits

...

38 Commits

Author SHA1 Message Date
Fredric Silberberg
16343bbe71 Updated release to version 5. 2016-03-01 15:55:19 -05:00
Peter Johnson
623a5fcf8d Fix C++ CameraServer request handling.
The request is not guaranteed to be in a single packet, so it may be necessary
to perform multiple reads to get the complete request.  The previous code
could unpredictably fail as it only performed a single read.

Fixes artf4817.

Change-Id: I7734a12e1a2542f5d7ca0889453c387f0bb30538
2016-02-24 00:18:59 -08:00
Fredric Silberberg
6bd1654b80 Updated release number for the new release
Change-Id: Ib05f1db442cd1eacd77653c0e0984a5337609f7b
2016-02-11 16:12:35 -05:00
Fredric Silberberg
952ebb11ad This adds StopMotor() to the SpeedController interface for C++ and Java.
For Java, this is as simple as just adding it, as all motors already
have an implementation from MotorSafety that is correctly resolved. For
C++, I had to override StopMotor in the classes that descend from
SafePWM and explicitly call the SafePWM version. RobotDrive now calls
StopMotor on each of its SpeedControllers, instead of calling Disable or
setting the motor to 0.0 as it was doing previously.

Additional small formatting corrections to the previous commit starting
this were added.

Change-Id: Ie94565394927a910ce74bc628670ac3d658d8df9
2016-02-11 12:19:52 -08:00
Brad Miller (WPI)
91c5db06db Merge "More updates to the Gyro test fixing potential null pointer exception" 2016-02-11 11:17:06 -08:00
Omar Zrien
df33a78221 Added Config routine to allow enabling/disabling of limit switch and soft limits. This improves upon the ConfigLimitMode routine, which does not allow certain combinations of enable/disabled limit features.
Also keeps parity with LV and Java.

Change-Id: Id2f4c9f169effc6bc3ea48529e8f04f387609ddc
2016-02-11 09:11:30 -08:00
Brad Miller (WPI)
a33076ab9a Merge "Add an additional member variable for "stopped" which indicates the CAN motor controller has been explicitly stopped, but not disabled by the user (main use case is MotorSafety tripping). When Set() is called the next time the controller will be re-enabled automatically." 2016-02-10 08:33:39 -08:00
Kevin O'Connor
d567bd0bca Add an additional member variable for "stopped" which indicates the CAN motor controller has been explicitly stopped, but not disabled by the user (main use case is MotorSafety tripping). When Set() is called the next time the controller will be re-enabled automatically.
Change-Id: Ib1c0e5d0ddd55343d83039acbc46c0f9c4e451a1
2016-02-08 18:13:57 -05:00
Patrick
f436b33d79 More updates to the Gyro test fixing potential null pointer exception
also retuned the deviation over time test to make it pass more reliably.
Ran sucessfully 40/40 times run including several run with the entire wpilibj

Change-Id: I2e42c368fdb81f9206e15ce39878ea105da1e405
2016-02-08 15:03:51 -05:00
Peter Johnson
3c3b2c75c0 Rate-limit duplicate error messages to avoid flooding console.
Fixes artf4809.

In both C++ and Java, error messages are being sent to both the console
(via stdout/stderr) and being reported via the HAL.  We don't want to
remove the stdout/stderr reporting at present because users debugging only
via netconsole (e.g. using riolog) won't see the HAL-reported errors.  Until
there's an alternative means to getting the HAL-reported errors to those
users, instead store the previous 5 error messages and don't duplicate them
more often than once per second.

Changes the error reporting from setErrorData() to sendError(), which
improves driver station error reporting.  The "location" in C++ is given as
the immediate caller (e.g. the WPILib function).  The "location" in Java is
given as the first user function in the call stack.  Note the full call stack
is provided in both instances.

Change-Id: I590dd63dcb66825301ebb260aff00cd8d7d501ed
2016-02-08 01:14:56 -08:00
Brad Miller (WPI)
f17d27aacf Merge "artf4818: Fix CAN Talon JNI references with underscores." 2016-02-06 09:38:26 -08:00
Brad Miller (WPI)
94629bcb78 Merge "Updated PDP port of Talon and disabled PDP tests for Victor and Jaguar since the Victor and Jaguar don't draw enough current for the PDP to read above 0. PDP tests for both java and cpp only test the Talon now." 2016-02-06 08:45:44 -08:00
Patrick
4a6f55b61d Fixed the gyro deviation over time test
Also modified the testgyroCalibratedParameters to reduce code duplication.

Change-Id: I356562df4e9da1848d84e82ee82c5fbfc47d7d31
2016-02-02 13:38:51 -05:00
Joe Ross
fdfedd12fc artf4818: Fix CAN Talon JNI references with underscores.
Add test to verify bindings are correct

Change-Id: I766f2d7ff32a1bee2289974e331a4d8d5d563a35
2016-01-31 20:30:37 -08:00
Brad Miller (WPI)
ae1171d1be Merge "Fixed the motor tests by reducing speed to within the limits of the encoders we use. Also fixed java pid tolerances since getAvgError() was broken. It is now fixed and works properly. Added tests for both java and cpp that test if pid tolerances are working using fake input output pairs." 2016-01-31 09:48:51 -08:00
Patrick
6b356020f3 Updated PDP port of Talon and disabled PDP tests for Victor and Jaguar since the Victor and Jaguar don't draw enough current for the PDP to read above 0. PDP tests for both java and cpp only test the Talon now.
Change-Id: I84b2f168b27d07b444e223ae225013b6e97edde3
2016-01-29 14:49:58 -05:00
Patrick
7041cbc5eb Fixed the motor tests by reducing speed to within the limits of the encoders we use. Also fixed java pid tolerances since getAvgError() was broken. It is now fixed and works properly. Added tests for both java and cpp that test if pid tolerances are working using fake input output pairs.
Change-Id: I5bf23dbbdab996c582e1035fc2b2f36dd5f52417
2016-01-28 14:47:15 -05:00
Peter_Mitrano
f24c8b1b8d Fixed robot drive for C++ Simulation
initial values for m_invertedMotors is now 1
previously it was done in some of the constructors, but not all of them.

Change-Id: I2c1ce8d8a67f82d02c4c51f1c4d1aaad143f3112
2016-01-25 12:03:48 -05:00
Fred Silberberg (WPI)
d62256156e Merge "Update version number for Release 3 Print distinctive message on robot program startup Change-Id: Ic91b81bd298ee6730503933cf0e733702e4b4405" 2016-01-24 16:07:23 -08:00
Brad Miller
61dbd43664 Update version number for Release 3
Print distinctive message on robot program startup
Change-Id: Ic91b81bd298ee6730503933cf0e733702e4b4405
2016-01-24 18:31:23 -05:00
Brad Miller (WPI)
f913b5de8c Merge "Removed publishing of java sim jar" 2016-01-24 15:27:54 -08:00
Omar Zrien
bd3e068f3b PDP Classes should support any PDP address
Change-Id: I3a8586e099559ee51449185734b89aaa6cd075d6
2016-01-22 23:53:49 -05:00
Fred Silberberg (WPI)
c6ff69079a Merge "Remove maven local as a possible search location" 2016-01-21 15:40:44 -08:00
Omar Zrien
5d3ac3ea71 Another improvement to HAL-joy getting to ensure it works in future RIO image updates.
Change-Id: I1f396b151e42dfd2b31de1fabde24b2988e8b599
2016-01-21 14:52:51 -08:00
Peter_Mitrano
f9e87f0cce Removed publishing of java sim jar
This causes the name of the jar to change, and thus fail to be included
in the simulation zip. There is no need to publish java sim jar.
Also added dependency on jar being built before zipping it

Change-Id: I1fa3dcf405d7da78a8d112381ecc3bfb2d6d367b
2016-01-20 15:15:02 -05:00
Peter Johnson
8801568325 DriverStation::GetJoystickName(): Make work for stick>0.
Change-Id: I1c62742cf8b80c81d21c2198f966c8151a758a01
2016-01-15 10:45:20 -08:00
Peter_Mitrano
75a91e24ef Remove maven local as a possible search location
maven caches are not stored in maven local, and searching here can
cause problems for building simulation.

Change-Id: Id106e80cfb9129431fd43500b06f879e7c682115
2016-01-15 11:56:35 -05:00
Brad Miller (WPI)
6adf4c48cd Merge "Fix HALGetJoystickDescriptor()." 2016-01-15 08:44:03 -08:00
Brad Miller (WPI)
026c427a2b Merge "Fixed Simulation C++ API" 2016-01-15 08:43:31 -08:00
Peter_Mitrano
63878d8ab7 Fixed Simulation C++ API
Fixed API in the following classes:
 - RobotDrive
 - AnalogGyro

moved some files from Athena the shared that are independant of platform
Renamed Gyro to AnalogGyro
added smart pointer constructors to RobotDrive

Change-Id: If8a1bde5aed77fd60869d1993c302dd519bc8848
2016-01-15 11:26:16 -05:00
Peter Johnson
83f902f2f6 Fix HALGetJoystickDescriptor().
This reverts the previous commit instead fixing it at the root
HALGetJoystickDescriptor function, which also fixes use of that function
by the C++ DriverStation class.

Change-Id: I1f203a015d8f10d119c61635def2822bf124754c
2016-01-14 21:49:50 -08:00
Thad House
f79ed1ab44 Artf4800: Fixes HALGetJoystick*** Segfault
The HALGetJoystick*** methods were not initializing the descriptor
variable properly. This was causing a SegFault if joysticks were moved
around while one of these methods were running.

Change-Id: If804c7ea724b10381765068e4d6fad75fad69ecb
2016-01-14 11:19:51 -08:00
Brad Miller (WPI)
bf89762e82 Merge "fix sim_ds launch script" 2016-01-13 10:19:40 -08:00
Brad Miller (WPI)
bd1e091629 Merge "Added build dir specification for sim javadoc to not overwrite athena javadoc" 2016-01-13 10:17:15 -08:00
Fredric Silberberg
2662a7ab0d Initialized the m_sensors variable to fix artf4798.
Change-Id: Iab7b76c0e36b3a8e5ab764f7dcd6772a2058bd0f
2016-01-12 16:27:34 -05:00
Fredric Silberberg
713d54fd2f Added build dir specification for sim javadoc to not overwrite athena javadoc
Change-Id: Idcc1303628134dd37c6c178b0bd66cfe2d24f928
2016-01-11 22:26:25 -05:00
Peter_Mitrano
75a07fc3e4 fix sim_ds launch script
It seems the tilde character doesn't always resolve to the home
directory

Change-Id: I69ecbab266901b271a16ce81b60a8bf7873f8a20
2016-01-08 01:31:01 -05:00
Peter Johnson
6b740e87b3 Fix C++ PIDController SetToleranceBuffer and OnTarget locking.
Also implement OnTarget fix in simulation PIDController.

Change-Id: Ic4b452759f80aa769a721f22cb6e732c2a9a213a
2016-01-07 20:55:10 -08:00
78 changed files with 989 additions and 451 deletions

View File

@@ -18,7 +18,6 @@ allprojects {
maven {
url publishUrl
}
mavenLocal()
maven {
url repoBaseUrl
}

View File

@@ -227,6 +227,9 @@ extern "C"
bool getFPGAButton(int32_t *status);
int HALSetErrorData(const char *errors, int errorsLength, int wait_ms);
int HALSendError(int isError, int32_t errorCode, int isLVCode,
const char *details, const char *location, const char *callStack,
int printMsg);
int HALGetControlWord(HALControlWord *data);
int HALGetAllianceStation(enum HALAllianceStationID *allianceStation);

View File

@@ -32,6 +32,7 @@ static tGlobal *global = nullptr;
static tSysWatchdog *watchdog = nullptr;
static priority_mutex timeMutex;
static priority_mutex msgMutex;
static uint32_t timeEpoch = 0;
static uint32_t prevFPGATime = 0;
static void* rolloverNotifier = nullptr;
@@ -232,6 +233,54 @@ int HALSetErrorData(const char *errors, int errorsLength, int wait_ms)
return setErrorData(errors, errorsLength, wait_ms);
}
int HALSendError(int isError, int32_t errorCode, int isLVCode,
const char *details, const char *location, const char *callStack,
int printMsg)
{
// Avoid flooding console by keeping track of previous 5 error
// messages and only printing again if they're longer than 1 second old.
static constexpr int KEEP_MSGS = 5;
std::lock_guard<priority_mutex> lock(msgMutex);
static std::string prev_msg[KEEP_MSGS];
static uint64_t prev_msg_time[KEEP_MSGS] = { 0, 0, 0 };
int32_t status = 0;
uint64_t curTime = getFPGATime(&status);
int i;
for (i=0; i<KEEP_MSGS; ++i) {
if (prev_msg[i] == details) break;
}
int retval = 0;
if (i == KEEP_MSGS || (curTime - prev_msg_time[i]) >= 1000000) {
retval = FRC_NetworkCommunication_sendError(isError, errorCode, isLVCode, details, location, callStack);
if (printMsg) {
if (location && location[0] != '\0') {
fprintf(stderr, "%s at %s: ",
isError ? "Error" : "Warning",
location);
}
fprintf(stderr, "%s\n", details);
if (callStack && callStack[0] != '\0') {
fprintf(stderr, "%s\n", callStack);
}
}
if (i == KEEP_MSGS) {
// replace the oldest one
i = 0;
uint64_t first = prev_msg_time[0];
for (int j=1; j<KEEP_MSGS; ++j) {
if (prev_msg_time[j] < first) {
first = prev_msg_time[j];
i = j;
}
}
prev_msg[i] = details;
}
prev_msg_time[i] = curTime;
}
return retval;
}
bool HALGetSystemActive(int32_t *status)
{

View File

@@ -11,10 +11,10 @@
#define CONTROL_1 0x08041C00 /* PDP_Control_ClearStats */
#define EXPECTED_RESPONSE_TIMEOUT_MS (50)
#define GET_STATUS1() CtreCanNode::recMsg<PdpStatus1_t> rx = GetRx<PdpStatus1_t>(STATUS_1,EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS2() CtreCanNode::recMsg<PdpStatus2_t> rx = GetRx<PdpStatus2_t>(STATUS_2,EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS3() CtreCanNode::recMsg<PdpStatus3_t> rx = GetRx<PdpStatus3_t>(STATUS_3,EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS_ENERGY() CtreCanNode::recMsg<PDP_Status_Energy_t> rx = GetRx<PDP_Status_Energy_t>(STATUS_ENERGY,EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS1() CtreCanNode::recMsg<PdpStatus1_t> rx = GetRx<PdpStatus1_t>(STATUS_1|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS2() CtreCanNode::recMsg<PdpStatus2_t> rx = GetRx<PdpStatus2_t>(STATUS_2|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS3() CtreCanNode::recMsg<PdpStatus3_t> rx = GetRx<PdpStatus3_t>(STATUS_3|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS)
#define GET_STATUS_ENERGY() CtreCanNode::recMsg<PDP_Status_Energy_t> rx = GetRx<PDP_Status_Energy_t>(STATUS_ENERGY|GetDeviceNumber(),EXPECTED_RESPONSE_TIMEOUT_MS)
/* encoder/decoders */
typedef struct _PdpStatus1_t{

View File

@@ -34,11 +34,32 @@ int HALGetJoystickButtons(uint8_t joystickNum, HALJoystickButtons *buttons)
{
return FRC_NetworkCommunication_getJoystickButtons(joystickNum, &buttons->buttons, &buttons->count);
}
/**
* Retrieve the Joystick Descriptor for particular slot
* @param desc [out] descriptor (data transfer object) to fill in. desc is filled in regardless of success.
* In other words, if descriptor is not available, desc is filled in with default
* values matching the init-values in Java and C++ Driverstation for when caller
* requests a too-large joystick index.
*
* @return error code reported from Network Comm back-end. Zero is good, nonzero is bad.
*/
int HALGetJoystickDescriptor(uint8_t joystickNum, HALJoystickDescriptor *desc)
{
return FRC_NetworkCommunication_getJoystickDesc(joystickNum, &desc->isXbox, &desc->type, (char *)(&desc->name),
desc->isXbox = 0;
desc->type = -1;
desc->name[0] = '\0';
desc->axisCount = kMaxJoystickAxes; /* set to the desc->axisTypes's capacity */
desc->buttonCount = 0;
desc->povCount = 0;
int retval = FRC_NetworkCommunication_getJoystickDesc(joystickNum, &desc->isXbox, &desc->type, (char *)(&desc->name),
&desc->axisCount, (uint8_t *)&desc->axisTypes, &desc->buttonCount, &desc->povCount);
/* check the return, if there is an error and the RIOimage predates FRC2017, then axisCount needs to be cleared */
if(retval != 0)
{
/* set count to zero so downstream code doesn't decode invalid axisTypes. */
desc->axisCount = 0;
}
return retval;
}
int HALGetJoystickIsXbox(uint8_t joystickNum)

View File

@@ -1 +1 @@
java -Djava.library.path=~/wpilib/simulation/lib -jar ~/wpilib/simulation/jar/SimDS-all.jar
java -Djava.library.path=${HOME}/wpilib/simulation/lib -jar ~/wpilib/simulation/jar/SimDS-all.jar

View File

@@ -230,6 +230,7 @@ class CANJaguar : public MotorSafety,
mutable std::atomic<bool> m_receivedStatusMessage2{false};
bool m_controlEnabled = false;
bool m_stopped = false;
void verify();

View File

@@ -65,6 +65,7 @@ class CANSpeedController : public SpeedController {
virtual float Get() const = 0;
virtual void Set(float value, uint8_t syncGroup = 0) = 0;
virtual void StopMotor() = 0;
virtual void Disable() = 0;
virtual void SetP(double p) = 0;
virtual void SetI(double i) = 0;

View File

@@ -286,6 +286,9 @@ class CANTalon : public MotorSafety,
virtual void ConfigLimitMode(LimitMode mode) override;
virtual void ConfigForwardLimit(double forwardLimitPosition) override;
virtual void ConfigReverseLimit(double reverseLimitPosition) override;
void ConfigLimitSwitchOverrides(bool bForwardLimitSwitchEn, bool bReverseLimitSwitchEn);
void ConfigForwardSoftLimitEnable(bool bForwardSoftLimitEn);
void ConfigReverseSoftLimitEnable(bool bReverseSoftLimitEn);
/**
* Change the fwd limit switch setting to normally open or closed.
* Talon will disable momentarilly if the Talon's current setting
@@ -437,6 +440,7 @@ class CANTalon : public MotorSafety,
// actually test this.
bool m_controlEnabled = true;
bool m_stopped = false;
ControlMode m_controlMode = kPercentVbus;
TalonControlMode m_sendMode;

View File

@@ -31,6 +31,10 @@ class DriverStation : public SensorBase, public RobotStateInterface {
virtual ~DriverStation();
static DriverStation &GetInstance();
static void ReportError(std::string error);
static void ReportWarning(std::string error);
static void ReportError(bool is_error, int32_t code, const std::string& error,
const std::string& location,
const std::string& stack);
static const uint32_t kJoystickPorts = 6;
@@ -97,6 +101,7 @@ class DriverStation : public SensorBase, public RobotStateInterface {
private:
static DriverStation *m_instance;
void ReportJoystickUnpluggedError(std::string message);
void ReportJoystickUnpluggedWarning(std::string message);
void Run();
HALJoystickAxes m_joystickAxes[kJoystickPorts];

View File

@@ -21,6 +21,7 @@ class Jaguar : public SafePWM, public SpeedController {
virtual void Set(float value, uint8_t syncGroup = 0) override;
virtual float Get() const override;
virtual void Disable() override;
virtual void StopMotor() override;
virtual void PIDWrite(float output) override;
virtual void SetInverted(bool isInverted) override;

View File

@@ -21,6 +21,7 @@ class SD540 : public SafePWM, public SpeedController {
virtual void Set(float value, uint8_t syncGroup = 0) override;
virtual float Get() const override;
virtual void Disable() override;
virtual void StopMotor() override;
virtual void PIDWrite(float output) override;

View File

@@ -21,6 +21,7 @@ class Spark : public SafePWM, public SpeedController {
virtual void Set(float value, uint8_t syncGroup = 0) override;
virtual float Get() const override;
virtual void Disable() override;
virtual void StopMotor() override;
virtual void PIDWrite(float output) override;

View File

@@ -48,4 +48,9 @@ class SpeedController : public PIDOutput {
* @return isInverted The state of inversion, true is inverted.
*/
virtual bool GetInverted() const = 0;
/**
* Common interface to stop the motor until Set is called again.
*/
virtual void StopMotor() = 0;
};

View File

@@ -25,6 +25,7 @@ class Talon : public SafePWM, public SpeedController {
virtual void PIDWrite(float output) override;
virtual void SetInverted(bool isInverted) override;
virtual bool GetInverted() const override;
virtual void StopMotor() override;
private:
bool m_isInverted = false;

View File

@@ -22,6 +22,7 @@ class TalonSRX : public SafePWM, public SpeedController {
virtual void Set(float value, uint8_t syncGroup = 0) override;
virtual float Get() const override;
virtual void Disable() override;
virtual void StopMotor() override;
virtual void PIDWrite(float output) override;
virtual void SetInverted(bool isInverted) override;

View File

@@ -24,6 +24,7 @@ class Victor : public SafePWM, public SpeedController {
virtual void Set(float value, uint8_t syncGroup = 0) override;
virtual float Get() const override;
virtual void Disable() override;
virtual void StopMotor() override;
virtual void PIDWrite(float output) override;

View File

@@ -21,6 +21,7 @@ class VictorSP : public SafePWM, public SpeedController {
virtual void Set(float value, uint8_t syncGroup = 0) override;
virtual float Get() const override;
virtual void Disable() override;
virtual void StopMotor() override;
virtual void PIDWrite(float output) override;

View File

@@ -246,8 +246,11 @@ void CANJaguar::Set(float outputValue, uint8_t syncGroup) {
uint8_t dataBuffer[8];
uint8_t dataSize;
if (m_safetyHelper && !m_safetyHelper->IsAlive() && m_controlEnabled) {
if (m_safetyHelper) m_safetyHelper->Feed();
if (m_stopped) {
EnableControl();
m_stopped = false;
}
if (m_controlEnabled) {
@@ -290,8 +293,6 @@ void CANJaguar::Set(float outputValue, uint8_t syncGroup) {
}
sendMessage(messageID, dataBuffer, dataSize, kSendMessagePeriod);
if (m_safetyHelper) m_safetyHelper->Feed();
}
m_value = outputValue;
@@ -1934,12 +1935,14 @@ void CANJaguar::GetDescription(std::ostringstream& desc) const {
uint8_t CANJaguar::GetDeviceID() const { return m_deviceNumber; }
/**
* Common interface for stopping the motor
* Common interface for stopping the motor until the next Set() command
* Part of the MotorSafety interface
*
* @deprecated Call DisableControl instead.
*/
void CANJaguar::StopMotor() { DisableControl(); }
void CANJaguar::StopMotor() {
m_stopped = true;
}
/**
* Common interface for inverting direction of a speed controller.

View File

@@ -134,6 +134,12 @@ float CANTalon::Get() const {
void CANTalon::Set(float value, uint8_t syncGroup) {
/* feed safety helper since caller just updated our output */
m_safetyHelper->Feed();
if (m_stopped) {
EnableControl();
m_stopped = false;
}
if (m_controlEnabled) {
m_setPoint = value; /* cache set point for GetSetpoint() */
CTR_Code status = CTR_OKAY;
@@ -1206,7 +1212,43 @@ void CANTalon::DisableSoftPositionLimits() {
}
/**
* TODO documentation (see CANJaguar.cpp)
* Overrides the forward and reverse limit switch enables.
* Unlike ConfigLimitMode, this function allows individual control of forward and
* reverse limit switch enables.
* Unlike ConfigLimitMode, this function does not affect the soft-limit features of Talon SRX.
* @see ConfigLimitMode()
*/
void CANTalon::ConfigLimitSwitchOverrides(bool bForwardLimitSwitchEn, bool bReverseLimitSwitchEn) {
CTR_Code status = CTR_OKAY;
int fwdRevEnable;
/* chose correct signal value based on caller's requests enables */
if(!bForwardLimitSwitchEn) {
/* caller wants Forward Limit Switch OFF */
if(!bReverseLimitSwitchEn) {
/* caller wants both OFF */
fwdRevEnable = CanTalonSRX::kLimitSwitchOverride_DisableFwd_DisableRev;
} else {
/* caller Forward OFF and Reverse ON */
fwdRevEnable = CanTalonSRX::kLimitSwitchOverride_DisableFwd_EnableRev;
}
} else {
/* caller wants Forward Limit Switch ON */
if(!bReverseLimitSwitchEn) {
/* caller wants Forward ON and Reverse OFF */
fwdRevEnable = CanTalonSRX::kLimitSwitchOverride_EnableFwd_DisableRev;
} else {
/* caller wants both ON */
fwdRevEnable = CanTalonSRX::kLimitSwitchOverride_EnableFwd_EnableRev;
}
}
/* update signal and error check code */
status = m_impl->SetOverrideLimitSwitchEn(fwdRevEnable);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* Configures the soft limit enable (wear leveled persistent memory).
* Also sets the limit switch overrides.
*/
@@ -1283,6 +1325,32 @@ void CANTalon::ConfigForwardLimit(double forwardLimitPosition) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* Set the Forward Soft Limit Enable.
* This is the same setting that is in the Web-Based Configuration.
* @param bForwardSoftLimitEn true to enable Soft limit, false to disable.
*/
void CANTalon::ConfigForwardSoftLimitEnable(bool bForwardSoftLimitEn) {
CTR_Code status = CTR_OKAY;
status = m_impl->SetForwardSoftEnable(bForwardSoftLimitEn);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* Set the Reverse Soft Limit Enable.
* This is the same setting that is in the Web-Based Configuration.
* @param bReverseSoftLimitEn true to enable Soft limit, false to disable.
*/
void CANTalon::ConfigReverseSoftLimitEnable(bool bReverseSoftLimitEn) {
CTR_Code status = CTR_OKAY;
status = m_impl->SetReverseSoftEnable(bReverseSoftLimitEn);
if (status != CTR_OKAY) {
wpi_setErrorWithContext(status, getHALErrorMessage(status));
}
}
/**
* Change the fwd limit switch setting to normally open or closed.
* Talon will disable momentarilly if the Talon's current setting
@@ -1825,12 +1893,15 @@ void CANTalon::SetInverted(bool isInverted) { m_isInverted = isInverted; }
bool CANTalon::GetInverted() const { return m_isInverted; }
/**
* Common interface for stopping the motor
* Common interface for stopping the motor until the next Set() call
* Part of the MotorSafety interface
*
* @deprecated Call Disable instead.
*/
void CANTalon::StopMotor() { Disable(); }
void CANTalon::StopMotor() {
Disable();
m_stopped = true;
}
void CANTalon::ValueChanged(ITable* source, llvm::StringRef key,
std::shared_ptr<nt::Value> value, bool isNew) {

View File

@@ -189,16 +189,26 @@ void CameraServer::Serve() {
}
Request req;
if (read(conn, &req, sizeof(req)) == -1) {
char reqBuf[sizeof(req)];
size_t reqPos = 0;
while (reqPos < sizeof(req)) {
ssize_t sizeRead = read(conn, &reqBuf[reqPos], sizeof(req) - reqPos);
if (sizeRead < 0) break;
reqPos += sizeRead;
}
if (reqPos < sizeof(req)) {
wpi_setErrnoError();
close(conn);
continue;
} else {
req.fps = ntohl(req.fps);
req.compression = ntohl(req.compression);
req.size = ntohl(req.size);
}
memcpy(&req, reqBuf, sizeof(req));
req.fps = ntohl(req.fps);
req.compression = ntohl(req.compression);
req.size = ntohl(req.size);
// TODO: Support the SW Compression. The rest of the code below will work as
// though this
// check isn't here

View File

@@ -133,6 +133,18 @@ void DriverStation::ReportJoystickUnpluggedError(std::string message) {
}
}
/**
* Reports errors related to unplugged joysticks
* Throttles the errors so that they don't overwhelm the DS
*/
void DriverStation::ReportJoystickUnpluggedWarning(std::string message) {
double currentTime = Timer::GetFPGATimestamp();
if (currentTime > m_nextMessageTime) {
ReportWarning(message);
m_nextMessageTime = currentTime + JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL;
}
}
/**
* Returns the number of axes on a given joystick port
*
@@ -159,7 +171,7 @@ std::string DriverStation::GetJoystickName(uint32_t stick) const {
if (stick >= kJoystickPorts) {
wpi_setWPIError(BadJoystickIndex);
}
std::string retVal(m_joystickDescriptor[0].name);
std::string retVal(m_joystickDescriptor[stick].name);
return retVal;
}
@@ -255,9 +267,8 @@ float DriverStation::GetStickAxis(uint32_t stick, uint32_t axis) {
if (axis >= kMaxJoystickAxes)
wpi_setWPIError(BadJoystickAxis);
else
ReportJoystickUnpluggedError(
"WARNING: Joystick Axis missing, check if all controllers are "
"plugged in\n");
ReportJoystickUnpluggedWarning(
"Joystick Axis missing, check if all controllers are plugged in");
return 0.0f;
}
@@ -285,9 +296,8 @@ int DriverStation::GetStickPOV(uint32_t stick, uint32_t pov) {
if (pov >= kMaxJoystickPOVs)
wpi_setWPIError(BadJoystickAxis);
else
ReportJoystickUnpluggedError(
"WARNING: Joystick POV missing, check if all controllers are plugged "
"in\n");
ReportJoystickUnpluggedWarning(
"Joystick POV missing, check if all controllers are plugged in");
return -1;
}
@@ -323,14 +333,13 @@ bool DriverStation::GetStickButton(uint32_t stick, uint8_t button) {
}
if (button > m_joystickButtons[stick].count) {
ReportJoystickUnpluggedError(
"WARNING: Joystick Button missing, check if all controllers are "
"plugged in\n");
ReportJoystickUnpluggedWarning(
"Joystick Button missing, check if all controllers are plugged in");
return false;
}
if (button == 0) {
ReportJoystickUnpluggedError(
"ERROR: Button indexes begin at 1 in WPILib for C++ and Java");
"Button indexes begin at 1 in WPILib for C++ and Java");
return false;
}
return ((0x1 << (button - 1)) & m_joystickButtons[stick].buttons) != 0;
@@ -527,11 +536,25 @@ double DriverStation::GetMatchTime() const {
* The error is also printed to the program console.
*/
void DriverStation::ReportError(std::string error) {
std::cout << error << std::endl;
HALControlWord controlWord;
HALGetControlWord(&controlWord);
if (controlWord.dsAttached) {
HALSetErrorData(error.c_str(), error.size(), 0);
}
HALSendError(1, 1, 0, error.c_str(), "", "", 1);
}
/**
* Report a warning to the DriverStation messages window.
* The warning is also printed to the program console.
*/
void DriverStation::ReportWarning(std::string error) {
HALSendError(0, 1, 0, error.c_str(), "", "", 1);
}
/**
* Report an error to the DriverStation messages window.
* The error is also printed to the program console.
*/
void DriverStation::ReportError(bool is_error, int32_t code,
const std::string &error,
const std::string &location,
const std::string &stack) {
HALSendError(is_error, code, 0, error.c_str(), location.c_str(),
stack.c_str(), 1);
}

View File

@@ -77,3 +77,8 @@ bool Jaguar::GetInverted() const { return m_isInverted; }
* @param output Write out the PWM value as was found in the PIDController
*/
void Jaguar::PIDWrite(float output) { Set(output); }
/**
* Common interface to stop the motor until Set is called again.
*/
void Jaguar::StopMotor() { this->SafePWM::StopMotor(); }

View File

@@ -469,6 +469,7 @@ void PIDController::SetAbsoluteTolerance(float absTolerance) {
* @param bufLength Number of previous cycles to average. Defaults to 1.
*/
void PIDController::SetToleranceBuffer(unsigned bufLength) {
std::lock_guard<priority_recursive_mutex> sync(m_mutex);
m_bufLength = bufLength;
// Cut the buffer down to size if needed.
@@ -489,10 +490,9 @@ void PIDController::SetToleranceBuffer(unsigned bufLength) {
* This will return false until at least one input value has been computed.
*/
bool PIDController::OnTarget() const {
std::lock_guard<priority_recursive_mutex> sync(m_mutex);
if (m_buf.size() == 0) return false;
double error = GetAvgError();
std::lock_guard<priority_recursive_mutex> sync(m_mutex);
switch (m_toleranceType) {
case kPercentTolerance:
return fabs(error) < m_tolerance / 100 * (m_maximumInput - m_minimumInput);

View File

@@ -27,6 +27,7 @@ void RobotBase::setInstance(RobotBase *robot) {
RobotBase &RobotBase::getInstance() { return *m_instance; }
void RobotBase::robotSetup(RobotBase *robot) {
printf("\n********** Robot program starting **********\n");
robot->StartCompetition();
}
@@ -55,7 +56,7 @@ RobotBase::RobotBase() : m_ds(DriverStation::GetInstance()) {
file = fopen("/tmp/frc_versions/FRC_Lib_Version.ini", "w");
if (file != nullptr) {
fputs("2016 C++ Beta5.0", file);
fputs("2016 C++ Release 5", file);
fclose(file);
}
}

View File

@@ -745,9 +745,9 @@ void RobotDrive::GetDescription(std::ostringstream& desc) const {
}
void RobotDrive::StopMotor() {
if (m_frontLeftMotor != nullptr) m_frontLeftMotor->Disable();
if (m_frontRightMotor != nullptr) m_frontRightMotor->Disable();
if (m_rearLeftMotor != nullptr) m_rearLeftMotor->Disable();
if (m_rearRightMotor != nullptr) m_rearRightMotor->Disable();
if (m_frontLeftMotor != nullptr) m_frontLeftMotor->StopMotor();
if (m_frontRightMotor != nullptr) m_frontRightMotor->StopMotor();
if (m_rearLeftMotor != nullptr) m_rearLeftMotor->StopMotor();
if (m_rearRightMotor != nullptr) m_rearRightMotor->StopMotor();
m_safetyHelper->Feed();
}

View File

@@ -86,3 +86,8 @@ void SD540::Disable() { SetRaw(kPwmDisabled); }
* @param output Write out the PWM value as was found in the PIDController
*/
void SD540::PIDWrite(float output) { Set(output); }
/**
* Common interface to stop the motor until Set is called again.
*/
void SD540::StopMotor() { this->SafePWM::StopMotor(); }

View File

@@ -86,3 +86,8 @@ void Spark::Disable() { SetRaw(kPwmDisabled); }
* @param output Write out the PWM value as was found in the PIDController
*/
void Spark::PIDWrite(float output) { Set(output); }
/**
* Common interface to stop the motor until Set is called again.
*/
void Spark::StopMotor() { this->SafePWM::StopMotor(); }

View File

@@ -82,3 +82,8 @@ bool Talon::GetInverted() const { return m_isInverted; }
* @param output Write out the PWM value as was found in the PIDController
*/
void Talon::PIDWrite(float output) { Set(output); }
/**
* Common interface to stop the motor until Set is called again.
*/
void Talon::StopMotor() { this->SafePWM::StopMotor(); }

View File

@@ -79,3 +79,8 @@ bool TalonSRX::GetInverted() const { return m_isInverted; }
* @param output Write out the PWM value as was found in the PIDController
*/
void TalonSRX::PIDWrite(float output) { Set(output); }
/**
* Common interface to stop the motor until Set is called again.
*/
void TalonSRX::StopMotor() { this->SafePWM::StopMotor(); }

View File

@@ -25,6 +25,7 @@ constexpr double Ultrasonic::kSpeedOfSoundInchesPerSec;
Task Ultrasonic::m_task;
// automatic round robin mode
std::atomic<bool> Ultrasonic::m_automaticEnabled{false};
std::set<Ultrasonic*> Ultrasonic::m_sensors;
/**
* Background task that goes through the list of ultrasonic sensors and pings

View File

@@ -29,11 +29,13 @@ bool wpi_assert_impl(bool conditionValue, const char *conditionText,
const char *message, const char *fileName,
uint32_t lineNumber, const char *funcName) {
if (!conditionValue) {
std::stringstream locStream;
locStream << funcName << " [";
locStream << basename(fileName) << ":" << lineNumber << "]";
std::stringstream errorStream;
errorStream << "Assertion \"" << conditionText << "\" ";
errorStream << "on line " << lineNumber << " ";
errorStream << "of " << basename(fileName) << " ";
if (message[0] != '\0') {
errorStream << "failed: " << message << std::endl;
@@ -41,13 +43,12 @@ bool wpi_assert_impl(bool conditionValue, const char *conditionText,
errorStream << "failed." << std::endl;
}
errorStream << GetStackTrace(2);
std::string stack = GetStackTrace(2);
std::string location = locStream.str();
std::string error = errorStream.str();
// Print the error and send it to the DriverStation
std::cout << error << std::endl;
HALSetErrorData(error.c_str(), error.size(), 100);
HALSendError(1, 1, 0, error.c_str(), location.c_str(), stack.c_str(), 1);
}
return conditionValue;
@@ -65,12 +66,14 @@ void wpi_assertEqual_common_impl(const char *valueA, const char *valueB,
const char *fileName,
uint32_t lineNumber,
const char *funcName) {
std::stringstream locStream;
locStream << funcName << " [";
locStream << basename(fileName) << ":" << lineNumber << "]";
std::stringstream errorStream;
errorStream << "Assertion \"" << valueA << " " << equalityType << " "
<< valueB << "\" ";
errorStream << "on line " << lineNumber << " ";
errorStream << "of " << basename(fileName) << " ";
if (message[0] != '\0') {
errorStream << "failed: " << message << std::endl;
@@ -78,13 +81,12 @@ void wpi_assertEqual_common_impl(const char *valueA, const char *valueB,
errorStream << "failed." << std::endl;
}
errorStream << GetStackTrace(3);
std::string trace = GetStackTrace(3);
std::string location = locStream.str();
std::string error = errorStream.str();
// Print the error and send it to the DriverStation
std::cout << error << std::endl;
HALSetErrorData(error.c_str(), error.size(), 100);
HALSendError(1, 1, 0, error.c_str(), location.c_str(), trace.c_str(), 1);
}
/**

View File

@@ -82,3 +82,8 @@ bool Victor::GetInverted() const { return m_isInverted; }
* @param output Write out the PWM value as was found in the PIDController
*/
void Victor::PIDWrite(float output) { Set(output); }
/**
* Common interface to stop the motor until Set is called again.
*/
void Victor::StopMotor() { this->SafePWM::StopMotor(); }

View File

@@ -86,3 +86,8 @@ void VictorSP::Disable() { SetRaw(kPwmDisabled); }
* @param output Write out the PWM value as was found in the PIDController
*/
void VictorSP::PIDWrite(float output) { Set(output); }
/**
* Common interface to stop the motor until Set is called again.
*/
void VictorSP::StopMotor() { this->SafePWM::StopMotor(); }

View File

@@ -66,24 +66,21 @@ void Error::Set(Code code, llvm::StringRef contextMessage,
}
void Error::Report() {
std::stringstream errorStream;
std::stringstream locStream;
locStream << m_function << " [";
errorStream << "Error on line " << m_lineNumber << " ";
#if defined(_UNIX)
errorStream << "of " << basename(m_filename.c_str()) << ": ";
#elif defined(_WIN32)
#if defined(_WIN32)
const int MAX_DIR = 100;
char basename[MAX_DIR];
_splitpath_s(m_filename.c_str(), NULL, 0, basename, MAX_DIR, NULL, 0, NULL, 0);
errorStream << "of " << basename << ": ";
locStream << basename;
#else
locStream << basename(m_filename.c_str());
#endif
locStream << ":" << m_lineNumber << "]";
errorStream << m_message << std::endl;
errorStream << GetStackTrace(4);
std::string error = errorStream.str();
DriverStation::ReportError(error);
DriverStation::ReportError(true, m_code, m_message, locStream.str(),
GetStackTrace(4));
}
void Error::Clear() {

View File

@@ -7,9 +7,7 @@
#pragma once
#include "SensorBase.h"
#include "PIDSource.h"
#include "LiveWindow/LiveWindowSendable.h"
#include "GyroBase.h"
#include "simulation/SimGyro.h"
#include <memory>
@@ -19,7 +17,7 @@ class AnalogModule;
/**
* Use a rate gyro to return the robots heading relative to a starting position.
* The Gyro class tracks the robots heading based on the starting position. As the robot
* The AnalogGyro class tracks the robots heading based on the starting position. As the robot
* rotates the new heading is computed by integrating the rate of rotation returned
* by the sensor. When the class is instantiated, it does a short calibration routine
* where it samples the gyro while at rest to determine the default offset. This is
@@ -27,7 +25,7 @@ class AnalogModule;
* with a channel that is assigned one of the Analog accumulators from the FPGA. See
* AnalogInput for the current accumulator assignments.
*/
class Gyro : public SensorBase, public PIDSource, public LiveWindowSendable
class AnalogGyro : public GyroBase
{
public:
static const uint32_t kOversampleBits;
@@ -36,25 +34,15 @@ public:
static const float kCalibrationSampleTime;
static const float kDefaultVoltsPerDegreePerSecond;
explicit Gyro(uint32_t channel);
virtual ~Gyro() = default;
virtual float GetAngle() const;
virtual double GetRate() const;
virtual void Reset();
// PIDSource interface
void SetPIDSourceType(PIDSourceType pidSource) override;
double PIDGet() override;
void UpdateTable() override;
void StartLiveWindowMode() override;
void StopLiveWindowMode() override;
std::string GetSmartDashboardType() const override;
void InitTable(std::shared_ptr<ITable> subTable) override;
std::shared_ptr<ITable> GetTable() const override;
explicit AnalogGyro(uint32_t channel);
virtual ~AnalogGyro() = default;
float GetAngle() const;
void Calibrate() override;
double GetRate() const;
void Reset();
private:
void InitGyro(int channel);
void InitAnalogGyro(int channel);
SimGyro* impl;

View File

@@ -42,6 +42,8 @@ public:
virtual ~DriverStation() = default;
static DriverStation &GetInstance();
static void ReportError(std::string error);
static void ReportWarning(std::string error);
static void ReportError(bool is_error, int32_t code, const std::string& error, const std::string& location, const std::string& stack);
static const uint32_t kBatteryChannel = 7;
static const uint32_t kJoystickPorts = 4;

View File

@@ -9,6 +9,7 @@
#include "ErrorBase.h"
#include <stdlib.h>
#include <memory>
#include "MotorSafety.h"
#include "MotorSafetyHelper.h"
@@ -39,11 +40,17 @@ public:
uint32_t frontRightMotorChannel, uint32_t rearRightMotorChannel);
RobotDrive(SpeedController *leftMotor, SpeedController *rightMotor);
RobotDrive(SpeedController &leftMotor, SpeedController &rightMotor);
RobotDrive(std::shared_ptr<SpeedController> leftMotor,
std::shared_ptr<SpeedController> rightMotor);
RobotDrive(SpeedController *frontLeftMotor, SpeedController *rearLeftMotor,
SpeedController *frontRightMotor, SpeedController *rearRightMotor);
RobotDrive(SpeedController &frontLeftMotor, SpeedController &rearLeftMotor,
SpeedController &frontRightMotor, SpeedController &rearRightMotor);
virtual ~RobotDrive();
RobotDrive(std::shared_ptr<SpeedController> frontLeftMotor,
std::shared_ptr<SpeedController> rearLeftMotor,
std::shared_ptr<SpeedController> frontRightMotor,
std::shared_ptr<SpeedController> rearRightMotor);
virtual ~RobotDrive() = default;
RobotDrive(const RobotDrive&) = delete;
RobotDrive& operator=(const RobotDrive&) = delete;
@@ -87,14 +94,14 @@ protected:
static const int32_t kMaxNumberOfMotors = 4;
int32_t m_invertedMotors[kMaxNumberOfMotors];
int32_t m_invertedMotors[kMaxNumberOfMotors] = {1,1,1,1};
float m_sensitivity = 0.5;
double m_maxOutput = 1.0;
bool m_deleteSpeedControllers;
SpeedController *m_frontLeftMotor = nullptr;
SpeedController *m_frontRightMotor = nullptr;
SpeedController *m_rearLeftMotor = nullptr;
SpeedController *m_rearRightMotor = nullptr;
std::shared_ptr<SpeedController> m_frontLeftMotor;
std::shared_ptr<SpeedController> m_frontRightMotor;
std::shared_ptr<SpeedController> m_rearLeftMotor;
std::shared_ptr<SpeedController> m_rearRightMotor;
// FIXME: MotorSafetyHelper *m_safetyHelper;
private:

View File

@@ -47,7 +47,7 @@
#include "Counter.h"
#include "DigitalInput.h"
#include "Encoder.h"
#include "Gyro.h"
#include "AnalogGyro.h"
#include "GenericHID.h"
#include "Joystick.h"
#include "PIDController.h"

View File

@@ -5,16 +5,16 @@
/* the project. */
/*----------------------------------------------------------------------------*/
#include "Gyro.h"
#include "AnalogGyro.h"
#include "Timer.h"
#include "WPIErrors.h"
#include "LiveWindow/LiveWindow.h"
const uint32_t Gyro::kOversampleBits = 10;
const uint32_t Gyro::kAverageBits = 0;
const float Gyro::kSamplesPerSecond = 50.0;
const float Gyro::kCalibrationSampleTime = 5.0;
const float Gyro::kDefaultVoltsPerDegreePerSecond = 0.007;
const uint32_t AnalogGyro::kOversampleBits = 10;
const uint32_t AnalogGyro::kAverageBits = 0;
const float AnalogGyro::kSamplesPerSecond = 50.0;
const float AnalogGyro::kCalibrationSampleTime = 5.0;
const float AnalogGyro::kDefaultVoltsPerDegreePerSecond = 0.007;
/**
* Initialize the gyro.
@@ -24,7 +24,7 @@ const float Gyro::kDefaultVoltsPerDegreePerSecond = 0.007;
* in progress, this is typically done when the robot is first turned on while it's sitting at
* rest before the competition starts.
*/
void Gyro::InitGyro(int channel)
void AnalogGyro::InitAnalogGyro(int channel)
{
SetPIDSourceType(PIDSourceType::kDisplacement);
@@ -32,17 +32,17 @@ void Gyro::InitGyro(int channel)
int n = sprintf(buffer, "analog/%d", channel);
impl = new SimGyro(buffer);
LiveWindow::GetInstance()->AddSensor("Gyro", channel, this);
LiveWindow::GetInstance()->AddSensor("AnalogGyro", channel, this);
}
/**
* Gyro constructor with only a channel..
* AnalogGyro constructor with only a channel..
*
* @param channel The analog channel the gyro is connected to.
*/
Gyro::Gyro(uint32_t channel)
AnalogGyro::AnalogGyro(uint32_t channel)
{
InitGyro(channel);
InitAnalogGyro(channel);
}
/**
@@ -50,11 +50,15 @@ Gyro::Gyro(uint32_t channel)
* Resets the gyro to a heading of zero. This can be used if there is significant
* drift in the gyro and it needs to be recalibrated after it has been running.
*/
void Gyro::Reset()
void AnalogGyro::Reset()
{
impl->Reset();
}
void AnalogGyro::Calibrate(){
Reset();
}
/**
* Return the actual angle in degrees that the robot is currently facing.
*
@@ -66,7 +70,7 @@ void Gyro::Reset()
* @return the current heading of the robot in degrees. This heading is based on integration
* of the returned rate from the gyro.
*/
float Gyro::GetAngle() const
float AnalogGyro::GetAngle() const
{
return impl->GetAngle();
}
@@ -79,56 +83,7 @@ float Gyro::GetAngle() const
*
* @return the current rate in degrees per second
*/
double Gyro::GetRate() const
double AnalogGyro::GetRate() const
{
return impl->GetVelocity();
}
void Gyro::SetPIDSourceType(PIDSourceType pidSource)
{
m_pidSource = pidSource;
}
/**
* Get the angle in degrees for the PIDSource base object.
*
* @return The angle in degrees.
*/
double Gyro::PIDGet()
{
switch(GetPIDSourceType()){
case PIDSourceType::kRate:
return GetRate();
case PIDSourceType::kDisplacement:
return GetAngle();
default:
return 0;
}
}
void Gyro::UpdateTable() {
if (m_table != nullptr) {
m_table->PutNumber("Value", GetAngle());
}
}
void Gyro::StartLiveWindowMode() {
}
void Gyro::StopLiveWindowMode() {
}
std::string Gyro::GetSmartDashboardType() const {
return "Gyro";
}
void Gyro::InitTable(std::shared_ptr<ITable> subTable) {
m_table = subTable;
UpdateTable();
}
std::shared_ptr<ITable> Gyro::GetTable() const {
return m_table;
}

View File

@@ -315,6 +315,31 @@ void DriverStation::ReportError(std::string error)
std::cout << error << std::endl;
}
/**
* Report a warning to the DriverStation messages window.
* The warning is also printed to the program console.
*/
void DriverStation::ReportWarning(std::string error)
{
std::cout << error << std::endl;
}
/**
* Report an error to the DriverStation messages window.
* The error is also printed to the program console.
*/
void DriverStation::ReportError(bool is_error, int32_t code,
const std::string& error,
const std::string& location,
const std::string& stack)
{
if (!location.empty())
std::cout << (is_error ? "Error" : "Warning") << " at " << location << ": ";
std::cout << error << std::endl;
if (!stack.empty())
std::cout << stack << std::endl;
}
/**
* Return the team number that the Driver Station is configured for
* @return The team number

View File

@@ -500,6 +500,7 @@ void PIDController::SetAbsoluteTolerance(float absTolerance)
* @param bufLength Number of previous cycles to average. Defaults to 1.
*/
void PIDController::SetToleranceBuffer(unsigned bufLength) {
std::lock_guard<priority_recursive_mutex> lock(m_mutex);
m_bufLength = bufLength;
// Cut the buffer down to size if needed.
@@ -518,9 +519,9 @@ void PIDController::SetToleranceBuffer(unsigned bufLength) {
*/
bool PIDController::OnTarget() const
{
double error = GetError();
std::lock_guard<priority_recursive_mutex> sync(m_mutex);
if (m_buf.size() == 0) return false;
double error = GetError();
switch (m_toleranceType) {
case kPercentTolerance:
return fabs(error) < m_tolerance / 100 * (m_maximumInput - m_minimumInput);

View File

@@ -6,11 +6,10 @@
/*----------------------------------------------------------------------------*/
#include "RobotDrive.h"
//#include "CANJaguar.h"
#include "GenericHID.h"
#include "Joystick.h"
#include "Jaguar.h"
#include "Talon.h"
#include "Utility.h"
#include "WPIErrors.h"
#include <math.h>
@@ -20,6 +19,10 @@
const int32_t RobotDrive::kMaxNumberOfMotors;
static auto make_shared_nodelete(SpeedController *ptr) {
return std::shared_ptr<SpeedController>(ptr, NullDeleter<SpeedController>());
}
/*
* Driving functions
* These functions provide an interface to multiple motors that is used for C programming
@@ -40,19 +43,15 @@ void RobotDrive::InitRobotDrive() {
/** Constructor for RobotDrive with 2 motors specified with channel numbers.
* Set up parameters for a two wheel drive system where the
* left and right motor pwm channels are specified in the call.
* This call assumes Jaguars for controlling the motors.
* This call assumes Talosn for controlling the motors.
* @param leftMotorChannel The PWM channel number that drives the left motor.
* @param rightMotorChannel The PWM channel number that drives the right motor.
*/
RobotDrive::RobotDrive(uint32_t leftMotorChannel, uint32_t rightMotorChannel)
{
InitRobotDrive();
m_rearLeftMotor = new Jaguar(leftMotorChannel);
m_rearRightMotor = new Jaguar(rightMotorChannel);
for (int32_t i=0; i < kMaxNumberOfMotors; i++)
{
m_invertedMotors[i] = 1;
}
m_rearLeftMotor = std::make_shared<Talon>(leftMotorChannel);
m_rearRightMotor = std::make_shared<Talon>(rightMotorChannel);
SetLeftRightMotorOutputs(0.0, 0.0);
m_deleteSpeedControllers = true;
}
@@ -61,7 +60,7 @@ RobotDrive::RobotDrive(uint32_t leftMotorChannel, uint32_t rightMotorChannel)
* Constructor for RobotDrive with 4 motors specified with channel numbers.
* Set up parameters for a four wheel drive system where all four motor
* pwm channels are specified in the call.
* This call assumes Jaguars for controlling the motors.
* This call assumes Talons for controlling the motors.
* @param frontLeftMotor Front left motor channel number
* @param rearLeftMotor Rear Left motor channel number
* @param frontRightMotor Front right motor channel number
@@ -71,14 +70,10 @@ RobotDrive::RobotDrive(uint32_t frontLeftMotor, uint32_t rearLeftMotor,
uint32_t frontRightMotor, uint32_t rearRightMotor)
{
InitRobotDrive();
m_rearLeftMotor = new Jaguar(rearLeftMotor);
m_rearRightMotor = new Jaguar(rearRightMotor);
m_frontLeftMotor = new Jaguar(frontLeftMotor);
m_frontRightMotor = new Jaguar(frontRightMotor);
for (int32_t i=0; i < kMaxNumberOfMotors; i++)
{
m_invertedMotors[i] = 1;
}
m_rearLeftMotor = std::make_shared<Talon>(rearLeftMotor);
m_rearRightMotor = std::make_shared<Talon>(rearRightMotor);
m_frontLeftMotor = std::make_shared<Talon>(frontLeftMotor);
m_frontRightMotor = std::make_shared<Talon>(frontRightMotor);
SetLeftRightMotorOutputs(0.0, 0.0);
m_deleteSpeedControllers = true;
}
@@ -91,34 +86,36 @@ RobotDrive::RobotDrive(uint32_t frontLeftMotor, uint32_t rearLeftMotor,
* @param leftMotor The left SpeedController object used to drive the robot.
* @param rightMotor the right SpeedController object used to drive the robot.
*/
RobotDrive::RobotDrive(SpeedController *leftMotor, SpeedController *rightMotor)
{
RobotDrive::RobotDrive(SpeedController *leftMotor,
SpeedController *rightMotor) {
InitRobotDrive();
if (leftMotor == nullptr || rightMotor == nullptr)
{
if (leftMotor == nullptr || rightMotor == nullptr) {
wpi_setWPIError(NullParameter);
m_rearLeftMotor = m_rearRightMotor = nullptr;
return;
}
m_rearLeftMotor = leftMotor;
m_rearRightMotor = rightMotor;
for (int32_t i=0; i < kMaxNumberOfMotors; i++)
{
m_invertedMotors[i] = 1;
}
m_deleteSpeedControllers = false;
m_rearLeftMotor = make_shared_nodelete(leftMotor);
m_rearRightMotor = make_shared_nodelete(rightMotor);
}
RobotDrive::RobotDrive(SpeedController &leftMotor, SpeedController &rightMotor)
{
//TODO: Change to rvalue references & move syntax.
RobotDrive::RobotDrive(SpeedController &leftMotor,
SpeedController &rightMotor) {
InitRobotDrive();
m_rearLeftMotor = &leftMotor;
m_rearRightMotor = &rightMotor;
for (int32_t i=0; i < kMaxNumberOfMotors; i++)
{
m_invertedMotors[i] = 1;
m_rearLeftMotor = make_shared_nodelete(&leftMotor);
m_rearRightMotor = make_shared_nodelete(&rightMotor);
}
RobotDrive::RobotDrive(std::shared_ptr<SpeedController> leftMotor,
std::shared_ptr<SpeedController> rightMotor) {
InitRobotDrive();
if (leftMotor == nullptr || rightMotor == nullptr) {
wpi_setWPIError(NullParameter);
m_rearLeftMotor = m_rearRightMotor = nullptr;
return;
}
m_deleteSpeedControllers = false;
m_rearLeftMotor = leftMotor;
m_rearRightMotor = rightMotor;
}
/**
@@ -129,12 +126,40 @@ RobotDrive::RobotDrive(SpeedController &leftMotor, SpeedController &rightMotor)
* @param rearRightMotor The back right SpeedController object used to drive the robot.
* @param frontRightMotor The front right SpeedController object used to drive the robot.
*/
RobotDrive::RobotDrive(SpeedController *frontLeftMotor, SpeedController *rearLeftMotor,
SpeedController *frontRightMotor, SpeedController *rearRightMotor)
{
RobotDrive::RobotDrive(SpeedController *frontLeftMotor,
SpeedController *rearLeftMotor,
SpeedController *frontRightMotor,
SpeedController *rearRightMotor) {
InitRobotDrive();
if (frontLeftMotor == nullptr || rearLeftMotor == nullptr || frontRightMotor == nullptr || rearRightMotor == nullptr)
{
if (frontLeftMotor == nullptr || rearLeftMotor == nullptr ||
frontRightMotor == nullptr || rearRightMotor == nullptr) {
wpi_setWPIError(NullParameter);
return;
}
m_frontLeftMotor = make_shared_nodelete(frontLeftMotor);
m_rearLeftMotor = make_shared_nodelete(rearLeftMotor);
m_frontRightMotor = make_shared_nodelete(frontRightMotor);
m_rearRightMotor = make_shared_nodelete(rearRightMotor);
}
RobotDrive::RobotDrive(SpeedController &frontLeftMotor,
SpeedController &rearLeftMotor,
SpeedController &frontRightMotor,
SpeedController &rearRightMotor) {
InitRobotDrive();
m_frontLeftMotor = make_shared_nodelete(&frontLeftMotor);
m_rearLeftMotor = make_shared_nodelete(&rearLeftMotor);
m_frontRightMotor = make_shared_nodelete(&frontRightMotor);
m_rearRightMotor = make_shared_nodelete(&rearRightMotor);
}
RobotDrive::RobotDrive(std::shared_ptr<SpeedController> frontLeftMotor,
std::shared_ptr<SpeedController> rearLeftMotor,
std::shared_ptr<SpeedController> frontRightMotor,
std::shared_ptr<SpeedController> rearRightMotor) {
InitRobotDrive();
if (frontLeftMotor == nullptr || rearLeftMotor == nullptr ||
frontRightMotor == nullptr || rearRightMotor == nullptr) {
wpi_setWPIError(NullParameter);
return;
}
@@ -142,42 +167,6 @@ RobotDrive::RobotDrive(SpeedController *frontLeftMotor, SpeedController *rearLef
m_rearLeftMotor = rearLeftMotor;
m_frontRightMotor = frontRightMotor;
m_rearRightMotor = rearRightMotor;
for (int32_t i=0; i < kMaxNumberOfMotors; i++)
{
m_invertedMotors[i] = 1;
}
m_deleteSpeedControllers = false;
}
RobotDrive::RobotDrive(SpeedController &frontLeftMotor, SpeedController &rearLeftMotor,
SpeedController &frontRightMotor, SpeedController &rearRightMotor)
{
InitRobotDrive();
m_frontLeftMotor = &frontLeftMotor;
m_rearLeftMotor = &rearLeftMotor;
m_frontRightMotor = &frontRightMotor;
m_rearRightMotor = &rearRightMotor;
for (int32_t i=0; i < kMaxNumberOfMotors; i++)
{
m_invertedMotors[i] = 1;
}
m_deleteSpeedControllers = false;
}
/**
* RobotDrive destructor.
* Deletes motor objects that were not passed in and created internally only.
**/
RobotDrive::~RobotDrive()
{
if (m_deleteSpeedControllers)
{
delete m_frontLeftMotor;
delete m_rearLeftMotor;
delete m_frontRightMotor;
delete m_rearRightMotor;
}
// FIXME: delete m_safetyHelper;
}
/**

View File

@@ -58,7 +58,7 @@ class TestBench {
/* PDP channels */
static const uint32_t kJaguarPDPChannel = 6;
static const uint32_t kVictorPDPChannel = 8;
static const uint32_t kTalonPDPChannel = 11;
static const uint32_t kTalonPDPChannel = 10;
/* PCM channels */
static const int32_t kSolenoidChannel1 = 0;

View File

@@ -68,3 +68,9 @@ TEST(CANTalonTest, DISABLED_PositionModeWorks) {
talon.Disable();
EXPECT_NEAR(talon.Get(), 500, 1000);
}
TEST(CANTalonTest, GetFaults) {
CANTalon talon(deviceId);
EXPECT_EQ(talon.GetFaults(),0);
EXPECT_EQ(talon.GetStickyFaults(),0);
}

View File

@@ -84,7 +84,7 @@ TEST_P(MotorEncoderTest, Increment) {
Reset();
/* Drive the speed controller briefly to move the encoder */
m_speedController->Set(1.0);
m_speedController->Set(0.2f);
Wait(kMotorTime);
m_speedController->Set(0.0);
@@ -100,7 +100,7 @@ TEST_P(MotorEncoderTest, Decrement) {
Reset();
/* Drive the speed controller briefly to move the encoder */
m_speedController->Set(-1.0f);
m_speedController->Set(-0.2f);
Wait(kMotorTime);
m_speedController->Set(0.0f);
@@ -131,12 +131,12 @@ TEST_P(MotorEncoderTest, ClampSpeed) {
*/
TEST_P(MotorEncoderTest, PositionPIDController) {
Reset();
double goal = 1000;
m_encoder->SetPIDSourceType(PIDSourceType::kDisplacement);
PIDController pid(0.001f, 0.0005f, 0.0f, m_encoder, m_speedController);
pid.SetAbsoluteTolerance(20.0f);
pid.SetOutputRange(-0.3f, 0.3f);
pid.SetSetpoint(2500);
pid.SetAbsoluteTolerance(50.0f);
pid.SetOutputRange(-0.2f, 0.2f);
pid.SetSetpoint(goal);
/* 10 seconds should be plenty time to get to the setpoint */
pid.Enable();
@@ -145,7 +145,7 @@ TEST_P(MotorEncoderTest, PositionPIDController) {
RecordProperty("PIDError", pid.GetError());
EXPECT_TRUE(pid.OnTarget()) << "PID loop did not converge within 10 seconds.";
EXPECT_TRUE(pid.OnTarget()) << "PID loop did not converge within 10 seconds. Goal was: "<<goal<<" Error was: "<<pid.GetError();
}
/**
@@ -156,20 +156,18 @@ TEST_P(MotorEncoderTest, VelocityPIDController) {
m_encoder->SetPIDSourceType(PIDSourceType::kRate);
PIDController pid(1e-5, 0.0f, 3e-5, 8e-5, m_encoder, m_speedController);
pid.SetAbsoluteTolerance(50.0f);
pid.SetToleranceBuffer(10);
pid.SetAbsoluteTolerance(200.0f);
pid.SetToleranceBuffer(50);
pid.SetOutputRange(-0.3f, 0.3f);
pid.SetSetpoint(2000);
pid.SetSetpoint(600);
/* 10 seconds should be plenty time to get to the setpoint */
pid.Enable();
Wait(10.0);
RecordProperty("PIDError", pid.GetAvgError());
EXPECT_TRUE(pid.OnTarget()) << "PID loop did not converge within 10 seconds. Goal was: " << 2000 << " Error was: " << pid.GetError();
pid.Disable();
RecordProperty("PIDError", pid.GetError());
EXPECT_TRUE(pid.OnTarget()) << "PID loop did not converge within 10 seconds. Goal was: " << 600 << " Error was: " << pid.GetError();
}
/**

View File

@@ -14,7 +14,7 @@
#include "TestBench.h"
enum MotorInvertingTestType { TEST_VICTOR, TEST_JAGUAR, TEST_TALON };
static const double motorSpeed = 0.25;
static const double motorSpeed = 0.15;
static const double delayTime = 0.5;
std::ostream &operator<<(std::ostream &os, MotorInvertingTestType const &type) {
switch (type) {

View File

@@ -0,0 +1,79 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2014-2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include <Timer.h>
#include "gtest/gtest.h"
#include "TestBench.h"
#include "PIDSource.h"
#include "PIDController.h"
#include "PIDOutput.h"
class PIDToleranceTest : public testing::Test{
protected:
const double setpoint = 50.0;
const double range = 200;
const double tolerance = 10.0;
class fakeInput : public PIDSource{
public:
double val = 0;
void SetPIDSourceType(PIDSourceType pidSource){
}
PIDSourceType GetPIDSourceType(){
return PIDSourceType::kDisplacement;
}
double PIDGet(){;
return val;
}
};
class fakeOutput : public PIDOutput{
void PIDWrite(float output){
}
};
fakeInput inp;
fakeOutput out;
PIDController *pid;
virtual void SetUp() override {
pid = new PIDController(0.5,0.0,0.0,&inp,&out);
pid->SetInputRange(-range/2,range/2);
}
virtual void TearDown() override {
delete pid;
}
virtual void reset(){
inp.val = 0;
}
};
TEST_F(PIDToleranceTest, Absolute){
reset();
pid->SetAbsoluteTolerance(tolerance);
pid->SetSetpoint(setpoint);
pid->Enable();
EXPECT_FALSE(pid->OnTarget())<<"Error was in tolerance when it should not have been. Error was " << pid->GetAvgError();
inp.val = setpoint+tolerance/2;
Wait(1.0);
EXPECT_TRUE(pid->OnTarget())<<"Error was not in tolerance when it should have been. Error was " << pid->GetAvgError();
inp.val = setpoint+10*tolerance;
Wait(1.0);
EXPECT_FALSE(pid->OnTarget())<<"Error was in tolerance when it should not have been. Error was " << pid->GetAvgError();
}
TEST_F(PIDToleranceTest, Percent){
reset();
pid->SetPercentTolerance(tolerance);
pid->SetSetpoint(setpoint);
pid->Enable();
EXPECT_FALSE(pid->OnTarget())<<"Error was in tolerance when it should not have been. Error was " << pid->GetAvgError();
inp.val = setpoint+(tolerance)/200*range;//half of percent tolerance away from setpoint
Wait(1.0);
EXPECT_TRUE(pid->OnTarget())<<"Error was not in tolerance when it should have been. Error was " << pid->GetAvgError();
inp.val = setpoint+(tolerance)/50*range;//double percent tolerance away from setPoint
Wait(1.0);
EXPECT_FALSE(pid->OnTarget())<<"Error was in tolerance when it should not have been. Error was " << pid->GetAvgError();
}

View File

@@ -56,40 +56,3 @@ TEST_F(PowerDistributionPanelTest, CheckCurrentTalon) {
<< "The Talon current was not positive";
}
/**
* Test if the current changes when the motor is driven using a victor
*/
TEST_F(PowerDistributionPanelTest, CheckCurrentVictor) {
Wait(kMotorTime);
/* The Current should be 0 */
EXPECT_FLOAT_EQ(0, m_pdp->GetCurrent(TestBench::kVictorPDPChannel))
<< "The Victor current was non-zero";
/* Set the motor to full forward */
m_victor->Set(1.0);
Wait(kMotorTime);
/* The current should now be positive */
ASSERT_GT(m_pdp->GetCurrent(TestBench::kVictorPDPChannel), 0)
<< "The Victor current was not positive";
}
/**
* Test if the current changes when the motor is driven using a jaguar
*/
TEST_F(PowerDistributionPanelTest, CheckCurrentJaguar) {
Wait(kMotorTime);
/* The Current should be 0 */
EXPECT_FLOAT_EQ(0, m_pdp->GetCurrent(TestBench::kJaguarPDPChannel))
<< "The Jaguar current was non-zero";
/* Set the motor to full forward */
m_jaguar->Set(1.0);
Wait(kMotorTime);
/* The current should now be positive */
ASSERT_GT(m_pdp->GetCurrent(TestBench::kJaguarPDPChannel), 0)
<< "The Jaguar current was not positive";
}

View File

@@ -42,6 +42,7 @@ task wpilibjSimJavadoc(type: Javadoc) {
description = 'Generates javadoc for the simulation components'
group = 'WPILib'
source sourceSets.sim.allJava, sourceSets.shared.allJava
destinationDir = file("$buildDir/docs/java-simulation")
classpath = files([sourceSets.sim.compileClasspath, sourceSets.shared.compileClasspath])
}
@@ -52,27 +53,8 @@ task wpilibjSimJavadocJar(type: Jar, dependsOn: wpilibjSimJavadoc) {
from wpilibjSimJavadoc.destinationDir
}
// Maven publishing configuration
publishing {
publications {
wpilibjSim(MavenPublication) {
artifact wpilibjSimJar
artifact(wpilibjSimSources) {
classifier = "sources"
}
artifact(wpilibjSimJavadocJar) {
classifier "javadoc"
}
groupId 'edu.wpi.first.wpilibj'
artifactId 'wpilibJavaSim'
version '0.1.0-SNAPSHOT'
}
}
}
//we need to move the simulation jars to the install directory
task copyJars(type: Copy) {
task copyJars(type: Copy, dependsOn: wpilibjSimJar) {
description = 'copy wpilibj simulation jar to make simulation zip'
group = 'WPILib Simulation'
from wpilibjSimJar.archivePath

View File

@@ -363,7 +363,7 @@ JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_ProcessMotionP
{
return ((CanTalonSRX*)handle)->ProcessMotionProfileBuffer();
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_OverTemp
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_1OverTemp
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -371,7 +371,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_OverT
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_UnderVoltage
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_1UnderVoltage
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -379,7 +379,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_Under
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_ForLim
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_1ForLim
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -387,7 +387,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_ForLi
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_RevLim
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_1RevLim
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -395,7 +395,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_RevLi
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_HardwareFailure
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_1HardwareFailure
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -403,7 +403,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_Hardw
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_ForSoftLim
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_1ForSoftLim
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -411,7 +411,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_ForSo
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_RevSoftLim
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_1RevSoftLim
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -419,7 +419,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetFault_RevSo
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_OverTemp
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_1OverTemp
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -427,7 +427,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_UnderVoltage
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_1UnderVoltage
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -435,7 +435,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_ForLim
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_1ForLim
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -443,7 +443,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_RevLim
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_1RevLim
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -451,7 +451,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_ForSoftLim
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_1ForSoftLim
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -459,7 +459,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_RevSoftLim
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetStckyFault_1RevSoftLim
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -683,7 +683,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetPulseWidthR
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_IsValid
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_1IsValid
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -691,7 +691,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_IsV
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_ProfileSlotSelect
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_1ProfileSlotSelect
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -699,7 +699,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_Pro
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_VelOnly
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_1VelOnly
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -707,7 +707,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_Vel
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_IsLast
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_1IsLast
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -763,7 +763,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetCount
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_Velocity
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_1Velocity
(JNIEnv * env, jclass, jlong handle)
{
int retval;
@@ -771,7 +771,7 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_Vel
CheckCTRStatus(env, status);
return retval;
}
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_Position
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_CanTalonJNI_GetActTraj_1Position
(JNIEnv * env, jclass, jlong handle)
{
int retval;

View File

@@ -323,4 +323,26 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_communication_FRCNetworkCommun
return returnValue;
}
/*
* Class: edu_wpi_first_wpilibj_communication_FRCNetworkCommunicationsLibrary
* Method: HALSendError
* Signature: (ZIZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_communication_FRCNetworkCommunicationsLibrary_HALSendError
(JNIEnv * env, jclass, jboolean isError, jint errorCode, jboolean isLVCode, jstring details, jstring location, jstring callStack, jboolean printMsg)
{
const char * detailsStr = env->GetStringUTFChars(details, NULL);
const char * locationStr = env->GetStringUTFChars(location, NULL);
const char * callStackStr = env->GetStringUTFChars(callStack, NULL);
NETCOMM_LOG(logDEBUG) << "Send Error: " << detailsStr;
NETCOMM_LOG(logDEBUG) << "Location: " << locationStr;
NETCOMM_LOG(logDEBUG) << "Call Stack: " << callStackStr;
jint returnValue = HALSendError(isError, errorCode, isLVCode, detailsStr, locationStr, callStackStr, printMsg);
env->ReleaseStringUTFChars(details,detailsStr);
env->ReleaseStringUTFChars(location,locationStr);
env->ReleaseStringUTFChars(callStack,callStackStr);
return returnValue;
}
} // extern "C"

View File

@@ -14,6 +14,7 @@
#include "HAL/HAL.hpp"
#include "errno.h"
#include <string.h>
#include <cstring>
#include <string>
// set the logging level
@@ -42,7 +43,7 @@ static jclass canMessageNotAllowedExCls = nullptr;
static jclass canNotInitializedExCls = nullptr;
static jclass uncleanStatusExCls = nullptr;
static void GetStackTrace(JNIEnv *env, std::string& res) {
static void GetStackTrace(JNIEnv *env, std::string& res, std::string& func) {
// create a throwable
static jmethodID constructorId = nullptr;
if (!constructorId)
@@ -72,6 +73,7 @@ static void GetStackTrace(JNIEnv *env, std::string& res) {
toStringId = env->GetMethodID(stackTraceElementCls, "toString",
"()Ljava/lang/String;");
bool haveLoc = false;
for (jsize i = 0; i < stackTraceLength; i++) {
// add the result of toString method of each element in the result
jobject curStackTraceElement = env->GetObjectArrayElement(stackTrace, i);
@@ -91,6 +93,16 @@ static void GetStackTrace(JNIEnv *env, std::string& res) {
const char *tmp = env->GetStringUTFChars(stackElementString, nullptr);
res += tmp;
res += '\n';
// func is caller of immediate caller (if there was one)
// or, if we see it, the first user function
if (i == 1)
func = tmp;
else if (i > 1 && !haveLoc &&
std::strncmp(tmp, "edu.wpi.first.wpilibj", 21) != 0) {
func = tmp;
haveLoc = true;
}
env->ReleaseStringUTFChars(stackElementString, tmp);
env->DeleteLocalRef(curStackTraceElement);
@@ -110,14 +122,10 @@ void ReportError(JNIEnv *env, int32_t status, bool do_throw) {
env->ThrowNew(runtimeExCls, buf);
delete[] buf;
} else {
std::string fullmsg = message;
fullmsg += " at ";
GetStackTrace(env, fullmsg);
fprintf(stderr, "%s\n", fullmsg.c_str());
HALControlWord controlWord;
HALGetControlWord(&controlWord);
if (controlWord.dsAttached)
HALSetErrorData(fullmsg.c_str(), fullmsg.size(), 0);
std::string stack = " at ";
std::string func;
GetStackTrace(env, stack, func);
HALSendError(1, status, 0, message, func.c_str(), stack.c_str(), 1);
}
}

View File

@@ -375,6 +375,14 @@ public class CANJaguar implements MotorSafety, PIDOutput, CANSpeedController {
byte[] data = new byte[8];
byte dataSize;
if (m_safetyHelper != null)
m_safetyHelper.feed();
if (m_stopped) {
enableControl();
m_stopped = false;
}
if (m_controlEnabled) {
switch (m_controlMode) {
case PercentVbus:
@@ -412,9 +420,6 @@ public class CANJaguar implements MotorSafety, PIDOutput, CANSpeedController {
}
sendMessage(messageID, data, dataSize, kSendMessagePeriod);
if (m_safetyHelper != null)
m_safetyHelper.feed();
}
m_value = outputValue;
@@ -1890,6 +1895,7 @@ public class CANJaguar implements MotorSafety, PIDOutput, CANSpeedController {
static final int kReceiveStatusAttempts = 50;
boolean m_controlEnabled = true;
boolean m_stopped = false;
static void sendMessageHelper(int messageID, byte[] data, int dataSize, int period)
throws CANMessageNotFoundException {
@@ -2244,9 +2250,9 @@ public class CANJaguar implements MotorSafety, PIDOutput, CANSpeedController {
* @deprecated Use disableControl instead.
*/
@Override
@Deprecated
public void stopMotor() {
disableControl();
m_stopped = true;
}
/*

View File

@@ -284,6 +284,7 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
int m_deviceNumber;
boolean m_controlEnabled;
boolean m_stopped = false;
int m_profile;
double m_setPoint;
@@ -423,6 +424,10 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
public void set(double outputValue) {
/* feed safety helper since caller just updated our output */
m_safetyHelper.feed();
if(m_stopped) {
enableControl();
m_stopped = false;
}
if (m_controlEnabled) {
m_setPoint = outputValue; /* cache set point for getSetpoint() */
switch (m_controlMode) {
@@ -1212,9 +1217,9 @@ public class CANTalon implements MotorSafety, PIDOutput, PIDSource, CANSpeedCont
* @deprecated Use disableControl instead.
*/
@Override
@Deprecated
public void stopMotor() {
disableControl();
m_stopped = true;
}
@Override

View File

@@ -211,6 +211,18 @@ public class DriverStation implements RobotState.Interface {
}
}
/**
* Reports errors related to unplugged joysticks Throttles the errors so that
* they don't overwhelm the DS
*/
private void reportJoystickUnpluggedWarning(String message) {
double currentTime = Timer.getFPGATimestamp();
if (currentTime > m_nextMessageTime) {
reportWarning(message, false);
m_nextMessageTime = currentTime + JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL;
}
}
/**
* Get the value of the axis on a joystick. This depends on the mapping of the
* joystick connected to the specified port.
@@ -229,8 +241,8 @@ public class DriverStation implements RobotState.Interface {
}
if (axis >= m_joystickAxes[stick].length) {
reportJoystickUnpluggedError("WARNING: Joystick axis " + axis + " on port " + stick
+ " not available, check if controller is plugged in\n");
reportJoystickUnpluggedWarning("Joystick axis " + axis + " on port " + stick
+ " not available, check if controller is plugged in");
return 0.0;
}
@@ -273,8 +285,8 @@ public class DriverStation implements RobotState.Interface {
}
if (pov >= m_joystickPOVs[stick].length) {
reportJoystickUnpluggedError("WARNING: Joystick POV " + pov + " on port " + stick
+ " not available, check if controller is plugged in\n");
reportJoystickUnpluggedWarning("Joystick POV " + pov + " on port " + stick
+ " not available, check if controller is plugged in");
return -1;
}
@@ -324,12 +336,12 @@ public class DriverStation implements RobotState.Interface {
if (button > m_joystickButtons[stick].count) {
reportJoystickUnpluggedError("WARNING: Joystick Button " + button + " on port " + stick
+ " not available, check if controller is plugged in\n");
reportJoystickUnpluggedWarning("Joystick Button " + button + " on port " + stick
+ " not available, check if controller is plugged in");
return false;
}
if (button <= 0) {
reportJoystickUnpluggedError("ERROR: Button indexes begin at 1 in WPILib for C++ and Java\n");
reportJoystickUnpluggedError("Button indexes begin at 1 in WPILib for C++ and Java");
return false;
}
return ((0x1 << (button - 1)) & m_joystickButtons[stick].buttons) != 0;
@@ -365,8 +377,8 @@ public class DriverStation implements RobotState.Interface {
// TODO: Remove this when calling for descriptor on empty stick no longer
// crashes
if (1 > m_joystickButtons[stick].count && 1 > m_joystickAxes[stick].length) {
reportJoystickUnpluggedError("WARNING: Joystick on port " + stick
+ " not available, check if controller is plugged in\n");
reportJoystickUnpluggedWarning("Joystick on port " + stick
+ " not available, check if controller is plugged in");
return false;
}
boolean retVal = false;
@@ -390,8 +402,8 @@ public class DriverStation implements RobotState.Interface {
// TODO: Remove this when calling for descriptor on empty stick no longer
// crashes
if (1 > m_joystickButtons[stick].count && 1 > m_joystickAxes[stick].length) {
reportJoystickUnpluggedError("WARNING: Joystick on port " + stick
+ " not available, check if controller is plugged in\n");
reportJoystickUnpluggedWarning("Joystick on port " + stick
+ " not available, check if controller is plugged in");
return -1;
}
return FRCNetworkCommunicationsLibrary.HALGetJoystickType((byte) stick);
@@ -411,8 +423,8 @@ public class DriverStation implements RobotState.Interface {
// TODO: Remove this when calling for descriptor on empty stick no longer
// crashes
if (1 > m_joystickButtons[stick].count && 1 > m_joystickAxes[stick].length) {
reportJoystickUnpluggedError("WARNING: Joystick on port " + stick
+ " not available, check if controller is plugged in\n");
reportJoystickUnpluggedWarning("Joystick on port " + stick
+ " not available, check if controller is plugged in");
return "";
}
return FRCNetworkCommunicationsLibrary.HALGetJoystickName((byte) stick);
@@ -600,19 +612,39 @@ public class DriverStation implements RobotState.Interface {
* @param printTrace If true, append stack trace to error string
*/
public static void reportError(String error, boolean printTrace) {
String errorString = error;
if (printTrace) {
errorString += " at ";
StackTraceElement[] traces = Thread.currentThread().getStackTrace();
for (int i = 2; i < traces.length; i++) {
errorString += traces[i].toString() + "\n";
reportErrorImpl(true, 1, error, printTrace);
}
/**
* Report warning to Driver Station. Also prints error to System.err Optionally
* appends Stack trace to warning message
*$
* @param printTrace If true, append stack trace to warning string
*/
public static void reportWarning(String error, boolean printTrace) {
reportErrorImpl(false, 1, error, printTrace);
}
private static void reportErrorImpl(boolean is_error, int code, String error, boolean printTrace) {
StackTraceElement[] traces = Thread.currentThread().getStackTrace();
String locString;
if (traces.length > 3)
locString = traces[3].toString();
else
locString = new String();
boolean haveLoc = false;
String traceString = new String();
traceString = " at ";
for (int i = 3; i < traces.length; i++) {
String loc = traces[i].toString();
traceString += loc + "\n";
// get first user function
if (!haveLoc && !loc.startsWith("edu.wpi.first.wpilibj")) {
locString = loc;
haveLoc = true;
}
}
System.err.println(errorString);
HALControlWord controlWord = FRCNetworkCommunicationsLibrary.HALGetControlWord();
if (controlWord.getDSAttached()) {
FRCNetworkCommunicationsLibrary.HALSetErrorData(errorString);
}
FRCNetworkCommunicationsLibrary.HALSendError(is_error, code, false, error, locString, printTrace ? traceString : "", true);
}
/**

View File

@@ -92,7 +92,7 @@ public class MotorSafetyHelper {
if (!m_enabled || RobotState.isDisabled() || RobotState.isTest())
return;
if (m_stopTime < Timer.getFPGATimestamp()) {
System.err.println(m_safeObject.getDescription() + "... Output not updated often enough.");
DriverStation.reportError(m_safeObject.getDescription() + "... Output not updated often enough.", false);
m_safeObject.stopMotor();
}

View File

@@ -223,7 +223,7 @@ public abstract class RobotBase {
output = new FileOutputStream(file);
output.write("2016 Java Beta5.0".getBytes());
output.write("2016 Java Release 5".getBytes());
} catch (IOException ex) {
ex.printStackTrace();
@@ -238,6 +238,7 @@ public abstract class RobotBase {
boolean errorOnExit = false;
try {
System.out.println("********** Robot program starting **********");
robot.startCompetition();
} catch (Throwable t) {
DriverStation.reportError(

View File

@@ -794,16 +794,16 @@ public class RobotDrive implements MotorSafety {
public void stopMotor() {
if (m_frontLeftMotor != null) {
m_frontLeftMotor.set(0.0);
m_frontLeftMotor.stopMotor();
}
if (m_frontRightMotor != null) {
m_frontRightMotor.set(0.0);
m_frontRightMotor.stopMotor();
}
if (m_rearLeftMotor != null) {
m_rearLeftMotor.set(0.0);
m_rearLeftMotor.stopMotor();
}
if (m_rearRightMotor != null) {
m_rearRightMotor.set(0.0);
m_rearRightMotor.stopMotor();
}
if (m_safetyHelper != null)
m_safetyHelper.feed();

View File

@@ -51,10 +51,14 @@ public interface SpeedController extends PIDOutput {
*/
boolean getInverted();
/**
* Disable the speed controller
*/
void disable();
/**
* Stops motor movement. Motor can be moved again by calling set without having
* to re-enable the motor.
*/
void stopMotor();
}

View File

@@ -233,4 +233,6 @@ public class FRCNetworkCommunicationsLibrary extends JNIWrapper {
public static native boolean HALGetBrownedOut();
public static native int HALSetErrorData(String error);
public static native int HALSendError(boolean isError, int errorCode, boolean isLVCode, String details, String location, String callStack, boolean printMsg);
}

View File

@@ -6,7 +6,8 @@
package edu.wpi.first.wpilibj;
import java.util.TimerTask;
import java.util.LinkedList;
import java.util.ArrayDeque;
import java.util.Queue;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.livewindow.LiveWindowSendable;
@@ -42,7 +43,7 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
private Tolerance m_tolerance; // the tolerance object used to check if on
// target
private int m_bufLength = 1;
private LinkedList<Double> m_buf;
private Queue<Double> m_buf;
private double m_bufTotal = 0.0;
private double m_setpoint = 0.0;
private double m_prevSetpoint = 0.0;
@@ -162,7 +163,7 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
HLUsageReporting.reportPIDController(instances);
m_tolerance = new NullTolerance();
m_buf = new LinkedList<Double>();
m_buf = new ArrayDeque<Double>(m_bufLength+1);
}
/**
@@ -311,11 +312,11 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
result = m_result;
// Update the buffer.
m_buf.push(m_error);
m_buf.add(m_error);
m_bufTotal += m_error;
// Remove old elements when the buffer is full.
if (m_buf.size() > m_bufLength) {
m_bufTotal -= m_buf.pop();
m_bufTotal -= m_buf.remove();
}
}
@@ -646,7 +647,7 @@ public class PIDController implements PIDInterface, LiveWindowSendable, Controll
// Cut the existing buffer down to size if needed.
while (m_buf.size() > bufLength) {
m_bufTotal -= m_buf.pop();
m_bufTotal -= m_buf.remove();
}
}

View File

@@ -0,0 +1,132 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj;
import edu.wpi.first.wpilibj.Timer;
/**
* The MotorSafetyHelper object is constructed for every object that wants to
* implement the Motor Safety protocol. The helper object has the code to
* actually do the timing and call the motors Stop() method when the timeout
* expires. The motor object is expected to call the Feed() method whenever the
* motors value is updated.
*
* @author brad
*/
public class MotorSafetyHelper {
double m_expiration;
boolean m_enabled;
double m_stopTime;
MotorSafety m_safeObject;
MotorSafetyHelper m_nextHelper;
static MotorSafetyHelper m_headHelper = null;
/**
* The constructor for a MotorSafetyHelper object. The helper object is
* constructed for every object that wants to implement the Motor Safety
* protocol. The helper object has the code to actually do the timing and call
* the motors Stop() method when the timeout expires. The motor object is
* expected to call the Feed() method whenever the motors value is updated.
*
* @param safeObject a pointer to the motor object implementing MotorSafety.
* This is used to call the Stop() method on the motor.
*/
public MotorSafetyHelper(MotorSafety safeObject) {
m_safeObject = safeObject;
m_enabled = false;
m_expiration = MotorSafety.DEFAULT_SAFETY_EXPIRATION;
m_stopTime = Timer.getFPGATimestamp();
m_nextHelper = m_headHelper;
m_headHelper = this;
}
/**
* Feed the motor safety object. Resets the timer on this object that is used
* to do the timeouts.
*/
public void feed() {
m_stopTime = Timer.getFPGATimestamp() + m_expiration;
}
/**
* Set the expiration time for the corresponding motor safety object.
*$
* @param expirationTime The timeout value in seconds.
*/
public void setExpiration(double expirationTime) {
m_expiration = expirationTime;
}
/**
* Retrieve the timeout value for the corresponding motor safety object.
*$
* @return the timeout value in seconds.
*/
public double getExpiration() {
return m_expiration;
}
/**
* Determine of the motor is still operating or has timed out.
*$
* @return a true value if the motor is still operating normally and hasn't
* timed out.
*/
public boolean isAlive() {
return !m_enabled || m_stopTime > Timer.getFPGATimestamp();
}
/**
* Check if this motor has exceeded its timeout. This method is called
* periodically to determine if this motor has exceeded its timeout value. If
* it has, the stop method is called, and the motor is shut down until its
* value is updated again.
*/
public void check() {
if (!m_enabled || RobotState.isDisabled() || RobotState.isTest())
return;
if (m_stopTime < Timer.getFPGATimestamp()) {
DriverStation.reportError(m_safeObject.getDescription() + "... Output not updated often enough.", false);
m_safeObject.stopMotor();
}
}
/**
* Enable/disable motor safety for this device Turn on and off the motor
* safety option for this PWM object.
*$
* @param enabled True if motor safety is enforced for this object
*/
public void setSafetyEnabled(boolean enabled) {
m_enabled = enabled;
}
/**
* Return the state of the motor safety enabled flag Return if the motor
* safety is currently enabled for this devicce.
*$
* @return True if motor safety is enforced for this device
*/
public boolean isSafetyEnabled() {
return m_enabled;
}
/**
* Check the motors to see if any have timed out. This static method is called
* periodically to poll all the motors and stop any that have timed out.
*/
// TODO: these should be synchronized with the setting methods in case it's
// called from a different thread
public static void checkMotors() {
for (MotorSafetyHelper msh = m_headHelper; msh != null; msh = msh.m_nextHelper) {
msh.check();
}
}
}

View File

@@ -131,4 +131,26 @@ public class CANTalonTest extends AbstractComsSetup {
}
}
//Test Get Fault methods (artf4814)
@Test
public void testGetFaults() {
CANTalon talon = new CANTalon(0);
talon.clearStickyFaults();
assertTrue(talon.getFaultOverTemp()==0);
assertTrue(talon.getFaultUnderVoltage()==0);
assertTrue(talon.getFaultForLim()==0);
assertTrue(talon.getFaultRevLim()==0);
assertTrue(talon.getFaultHardwareFailure()==0);
assertTrue(talon.getFaultForSoftLim()==0);
assertTrue(talon.getFaultRevSoftLim()==0);
assertTrue(talon.getStickyFaultOverTemp()==0);
// assertTrue(talon.getStickyFaultUnderVoltage()==0);
assertTrue(talon.getStickyFaultForLim()==0);
assertTrue(talon.getStickyFaultRevLim()==0);
assertTrue(talon.getStickyFaultForSoftLim()==0);
assertTrue(talon.getStickyFaultRevSoftLim()==0);
}
}

View File

@@ -46,14 +46,14 @@ public class GyroTest extends AbstractComsSetup {
@Test
public void testAllGyroTests() {
testInitial();
testGyroAngle();
testDeviationOverTime();
testInitial(tpcam.getGyro());
testDeviationOverTime(tpcam.getGyro());
testGyroAngle(tpcam.getGyro());
testGyroAngleCalibratedParameters();
}
public void testInitial() {
double angle = tpcam.getGyro().getAngle();
public void testInitial(AnalogGyro gyro) {
double angle = gyro.getAngle();
assertEquals(errorMessage(angle, 0), 0, angle, .5);
}
@@ -63,7 +63,7 @@ public class GyroTest extends AbstractComsSetup {
* for so setAngle is significantly off. This has been calibrated for the
* servo on the rig.
*/
public void testGyroAngle() {
public void testGyroAngle(AnalogGyro gyro) {
// Set angle
for (int i = 0; i < 5; i++) {
tpcam.getPan().set(0);
@@ -72,7 +72,7 @@ public class GyroTest extends AbstractComsSetup {
Timer.delay(0.5);
// Reset for setup
tpcam.getGyro().reset();
gyro.reset();
Timer.delay(0.5);
// Perform test
@@ -82,7 +82,7 @@ public class GyroTest extends AbstractComsSetup {
}
Timer.delay(1.2);
double angle = tpcam.getGyro().getAngle();
double angle = gyro.getAngle();
double difference = TEST_ANGLE - angle;
@@ -91,16 +91,16 @@ public class GyroTest extends AbstractComsSetup {
assertEquals(errorMessage(diff, TEST_ANGLE), TEST_ANGLE, angle, 10);
}
public void testDeviationOverTime() {
public void testDeviationOverTime(AnalogGyro gyro) {
// Make sure that the test isn't influenced by any previous motions.
Timer.delay(0.5);
tpcam.getGyro().reset();
gyro.reset();
Timer.delay(0.25);
double angle = tpcam.getGyro().getAngle();
double angle = gyro.getAngle();
assertEquals(errorMessage(angle, 0), 0, angle, .5);
Timer.delay(5);
angle = tpcam.getGyro().getAngle();
assertEquals("After 5 seconds " + errorMessage(angle, 0), 0, angle, 1);
angle = gyro.getAngle();
assertEquals("After 5 seconds " + errorMessage(angle, 0), 0, angle, 2.0);
}
/**
@@ -113,34 +113,11 @@ public class GyroTest extends AbstractComsSetup {
int cCenter = tpcam.getGyro().getCenter();
tpcam.freeGyro();
tpcam.setupGyroParam(cCenter, cOffset);
Timer.delay(TiltPanCameraFixture.RESET_TIME);
// Repeat tests
// Set angle
for (int i = 0; i < 5; i++) {
tpcam.getPan().set(0);
Timer.delay(.1);
}
Timer.delay(0.5);
// Reset for setup
tpcam.getGyroParam().reset();
Timer.delay(0.5);
// Perform test
for (int i = 0; i < 53; i++) {
tpcam.getPan().set(i / 100.0);
Timer.delay(0.05);
}
Timer.delay(1.2);
double angle = tpcam.getGyroParam().getAngle();
double difference = TEST_ANGLE - angle;
double diff = Math.abs(difference);
assertEquals(errorMessage(diff, TEST_ANGLE), TEST_ANGLE, angle, 10);
testInitial(tpcam.getGyroParam());
testDeviationOverTime(tpcam.getGyroParam());
testGyroAngle(tpcam.getGyroParam());
}
private String errorMessage(double difference, double target) {

View File

@@ -60,7 +60,7 @@ public class MotorEncoderTest extends AbstractComsSetup {
@Before
public void setUp() {
double initialSpeed = me.getMotor().get();
assertTrue(me.getType() + " Did not start with an initial speeed of 0 instead got: "
assertTrue(me.getType() + " Did not start with an initial speed of 0 instead got: "
+ initialSpeed, Math.abs(initialSpeed) < 0.001);
me.setup();
@@ -101,7 +101,7 @@ public class MotorEncoderTest extends AbstractComsSetup {
public void testIncrement() {
int startValue = me.getEncoder().get();
me.getMotor().set(.75);
me.getMotor().set(.2);
Timer.delay(MOTOR_RUNTIME);
int currentValue = me.getEncoder().get();
assertTrue(me.getType() + " Encoder not incremented: start: " + startValue + "; current: "
@@ -117,7 +117,7 @@ public class MotorEncoderTest extends AbstractComsSetup {
public void testDecrement() {
int startValue = me.getEncoder().get();
me.getMotor().set(-.75);
me.getMotor().set(-.2);
Timer.delay(MOTOR_RUNTIME);
int currentValue = me.getEncoder().get();
assertTrue(me.getType() + " Encoder not decremented: start: " + startValue + "; current: "
@@ -170,18 +170,18 @@ public class MotorEncoderTest extends AbstractComsSetup {
@Test
public void testPositionPIDController() {
me.getEncoder().setPIDSourceType(PIDSourceType.kDisplacement);
PIDController pid = new PIDController(0.003, 0.001, 0, me.getEncoder(), me.getMotor());
pid.setAbsoluteTolerance(50);
PIDController pid = new PIDController(0.001, 0.0005, 0, me.getEncoder(), me.getMotor());
pid.setAbsoluteTolerance(50.0);
pid.setOutputRange(-0.2, 0.2);
pid.setSetpoint(2500);
pid.setSetpoint(1000);
pid.enable();
Timer.delay(10.0);
pid.disable();
assertTrue(
"PID loop did not reach setpoint within 10 seconds. The error was: " + pid.getError(),
pid.onTarget());
"PID loop did not reach setpoint within 10 seconds. The average error was: " + pid.getAvgError() +
"The current error was" + pid.getError(), pid.onTarget());
pid.free();
}
@@ -194,7 +194,7 @@ public class MotorEncoderTest extends AbstractComsSetup {
pid.setAbsoluteTolerance(200);
pid.setToleranceBuffer(50);
pid.setOutputRange(-0.3, 0.3);
pid.setSetpoint(2000);
pid.setSetpoint(600);
pid.enable();
Timer.delay(10.0);

View File

@@ -30,7 +30,7 @@ import java.util.logging.Logger;
@RunWith(Parameterized.class)
public class MotorInvertingTest extends AbstractComsSetup {
static MotorEncoderFixture<?> fixture = null;
private static final double motorspeed = 0.35;
private static final double motorspeed = 0.2;
private static final double delaytime = 0.3;

View File

@@ -65,9 +65,7 @@ public class PDPTest extends AbstractComsSetup {
public static Collection<Object[]> generateData() {
// logger.fine("Loading the MotorList");
return Arrays.asList(new Object[][] {
{TestBench.getInstance().getTalonPair(), new Double(0.0)},
{TestBench.getInstance().getVictorPair(), new Double(0.0)},
{TestBench.getInstance().getJaguarPair(), new Double(0.0)}});
{TestBench.getInstance().getTalonPair(), new Double(0.0)}});
}
@After
@@ -97,7 +95,7 @@ public class PDPTest extends AbstractComsSetup {
/* Set the motor to full forward */
me.getMotor().set(1.0);
Timer.delay(0.25);
Timer.delay(2);
/* The current should now be greater than the low current */
assertThat("The driven current is not greater than the resting current.",

View File

@@ -46,7 +46,7 @@ public class PIDTest extends AbstractComsSetup {
private NetworkTable table;
private static final double absoluteTolerance = 50;
private static final double outputRange = 0.3;
private static final double outputRange = 0.25;
private PIDController controller = null;
private static MotorEncoderFixture me = null;
@@ -181,7 +181,7 @@ public class PIDTest extends AbstractComsSetup {
public void testRotateToTarget() {
setupAbsoluteTolerance();
setupOutputRange();
double setpoint = 2500.0;
double setpoint = 1000.0;
assertEquals(pidData() + "did not start at 0", 0, controller.get(), 0);
controller.setSetpoint(setpoint);
assertEquals(pidData() + "did not have an error of " + setpoint, setpoint,

View File

@@ -0,0 +1,88 @@
package edu.wpi.first.wpilibj;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import edu.wpi.first.wpilibj.test.AbstractComsSetup;
public class PIDToleranceTest extends AbstractComsSetup {
private static final Logger logger = Logger.getLogger(PIDToleranceTest.class.getName());
private PIDController pid;
private final double setPoint = 50.0;
private final double tolerance = 10.0;
private final double range = 200;
private class fakeInput implements PIDSource{
public double val;
public fakeInput(){
val = 0;
}
@Override
public PIDSourceType getPIDSourceType() {
return PIDSourceType.kDisplacement;
}
@Override
public double pidGet() {
return val;
}
@Override
public void setPIDSourceType(PIDSourceType arg0) {}
};
private fakeInput inp;
private PIDOutput out = new PIDOutput(){
@Override
public void pidWrite(double out) {
}
};
@Override
protected Logger getClassLogger() {
return logger;
}
@Before
public void setUp() throws Exception{
inp = new fakeInput();
pid = new PIDController(0.05,0.0,0.0,inp,out);
pid.setInputRange(-range/2, range/2);
}
@After
public void tearDown() throws Exception{
pid.free();
pid = null;
}
@Test
public void testAbsoluteTolerance(){
pid.setAbsoluteTolerance(tolerance);
pid.setSetpoint(setPoint);
pid.enable();
Timer.delay(1);
assertFalse("Error was in tolerance when it should not have been. Error was "+pid.getAvgError(),pid.onTarget());
inp.val = setPoint+tolerance/2;
Timer.delay(1.0);
assertTrue("Error was not in tolerance when it should have been. Error was "+pid.getAvgError(),pid.onTarget());
inp.val = setPoint + 10*tolerance;
Timer.delay(1.0);
assertFalse("Error was in tolerance when it should not have been. Error was "+pid.getAvgError(),pid.onTarget());
}
@Test
public void testPercentTolerance(){
pid.setPercentTolerance(tolerance);
pid.setSetpoint(setPoint);
pid.enable();
assertFalse("Error was in tolerance when it should not have been. Error was "+pid.getAvgError(),pid.onTarget());
inp.val = setPoint+(tolerance)/200*range;//half of percent tolerance away from setPoint
Timer.delay(1.0);
assertTrue("Error was not in tolerance when it should have been. Error was "+pid.getAvgError(),pid.onTarget());
inp.val = setPoint + (tolerance)/50*range;//double percent tolerance away from setPoint
Timer.delay(1.0);
assertFalse("Error was in tolerance when it should not have been. Error was "+pid.getAvgError(),pid.onTarget());
}
}

View File

@@ -25,7 +25,7 @@ import edu.wpi.first.wpilibj.test.AbstractTestSuite;
DIOCrossConnectTest.class, EncoderTest.class, FilterNoiseTest.class,
FilterOutputTest.class, GyroTest.class, MotorEncoderTest.class,
MotorInvertingTest.class, PCMTest.class, PDPTest.class, PIDTest.class,
PreferencesTest.class, RelayCrossConnectTest.class, SampleTest.class,
TimerTest.class})
PIDToleranceTest.class, PreferencesTest.class, RelayCrossConnectTest.class,
SampleTest.class, TimerTest.class})
public class WpiLibJTestSuite extends AbstractTestSuite {
}

View File

@@ -18,9 +18,9 @@ import java.util.logging.Logger;
*/
public class CANJaguarInversionTest extends AbstractCANTest {
private static final Logger logger = Logger.getLogger(CANJaguarInversionTest.class.getName());
private static final double motorVoltage = 5.0;
private static final double motorPercent = 0.5;
private static final double motorSpeed = 100;
private static final double motorVoltage = 2.0;
private static final double motorPercent = 0.1;
private static final double motorSpeed = 10;
private static final double delayTime = 0.75;
private static final double speedModeDelayTime = 2.0;

View File

@@ -37,7 +37,7 @@ public class CANPercentQuadEncoderModeTest extends AbstractCANTest {
private static final Logger logger = Logger.getLogger(CANPercentQuadEncoderModeTest.class
.getName());
private static final double kStoppedValue = 0;
private static final double kRunningValue = 1;
private static final double kRunningValue = 0.3;
/*
* (non-Javadoc)

View File

@@ -31,7 +31,7 @@ public class CANSpeedQuadEncoderModeTest extends AbstractCANTest {
/** The stopped value in rev/min */
private static final double kStoppedValue = 0;
/** The running value in rev/min */
private static final double kRunningValue = 200;
private static final double kRunningValue = 50;
@Override
protected Logger getClassLogger() {

View File

@@ -65,6 +65,7 @@ public abstract class TiltPanCameraFixture implements ITestFixture {
@Override
public boolean reset() {
if(gyro != null)
gyro.reset();
return true;
}
@@ -101,8 +102,14 @@ public abstract class TiltPanCameraFixture implements ITestFixture {
tilt = null;
pan.free();
pan = null;
if(gyro !=null){//in case not freed during gyro tests
gyro.free();
gyro = null;
}
if(gyroParam != null){//in case gyro tests failed before getting to this point
gyroParam.free();
gyroParam = null;
}
return true;
}

View File

@@ -68,7 +68,7 @@ public final class TestBench {
/* PowerDistributionPanel channels */
public static final int kJaguarPDPChannel = 6;
public static final int kVictorPDPChannel = 8;
public static final int kTalonPDPChannel = 11;
public static final int kTalonPDPChannel = 10;
public static final int kCANJaguarPDPChannel = 5;
/* CAN ASSOICATED CHANNELS */