2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2019-06-10 22:03:15 -07:00
|
|
|
/* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */
|
2013-12-15 18:30:16 -05:00
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
2016-01-02 03:02:34 -08:00
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
2018-07-20 00:03:45 -07:00
|
|
|
#include "frc/DriverStation.h"
|
2016-09-14 20:52:06 -07:00
|
|
|
|
2016-10-09 11:46:01 -07:00
|
|
|
#include <chrono>
|
|
|
|
|
|
2018-07-20 00:03:45 -07:00
|
|
|
#include <hal/HAL.h>
|
|
|
|
|
#include <hal/Power.h>
|
2018-01-18 23:17:28 -08:00
|
|
|
#include <networktables/NetworkTable.h>
|
|
|
|
|
#include <networktables/NetworkTableEntry.h>
|
|
|
|
|
#include <networktables/NetworkTableInstance.h>
|
2018-04-29 23:33:19 -07:00
|
|
|
#include <wpi/SmallString.h>
|
|
|
|
|
#include <wpi/StringRef.h>
|
2017-08-27 00:11:52 -07:00
|
|
|
|
2018-07-20 00:03:45 -07:00
|
|
|
#include "frc/AnalogInput.h"
|
2018-12-29 16:19:23 -08:00
|
|
|
#include "frc/MotorSafety.h"
|
2018-07-20 00:03:45 -07:00
|
|
|
#include "frc/Timer.h"
|
|
|
|
|
#include "frc/Utility.h"
|
|
|
|
|
#include "frc/WPIErrors.h"
|
2014-01-06 10:12:21 -05:00
|
|
|
|
2017-11-09 19:59:29 -08:00
|
|
|
namespace frc {
|
2018-01-18 23:17:28 -08:00
|
|
|
|
|
|
|
|
class MatchDataSender {
|
|
|
|
|
public:
|
|
|
|
|
std::shared_ptr<nt::NetworkTable> table;
|
|
|
|
|
nt::NetworkTableEntry typeMetadata;
|
|
|
|
|
nt::NetworkTableEntry gameSpecificMessage;
|
|
|
|
|
nt::NetworkTableEntry eventName;
|
|
|
|
|
nt::NetworkTableEntry matchNumber;
|
|
|
|
|
nt::NetworkTableEntry replayNumber;
|
|
|
|
|
nt::NetworkTableEntry matchType;
|
|
|
|
|
nt::NetworkTableEntry alliance;
|
|
|
|
|
nt::NetworkTableEntry station;
|
|
|
|
|
nt::NetworkTableEntry controlWord;
|
|
|
|
|
|
|
|
|
|
MatchDataSender() {
|
|
|
|
|
table = nt::NetworkTableInstance::GetDefault().GetTable("FMSInfo");
|
|
|
|
|
typeMetadata = table->GetEntry(".type");
|
|
|
|
|
typeMetadata.ForceSetString("FMSInfo");
|
|
|
|
|
gameSpecificMessage = table->GetEntry("GameSpecificMessage");
|
|
|
|
|
gameSpecificMessage.ForceSetString("");
|
|
|
|
|
eventName = table->GetEntry("EventName");
|
|
|
|
|
eventName.ForceSetString("");
|
|
|
|
|
matchNumber = table->GetEntry("MatchNumber");
|
|
|
|
|
matchNumber.ForceSetDouble(0);
|
|
|
|
|
replayNumber = table->GetEntry("ReplayNumber");
|
|
|
|
|
replayNumber.ForceSetDouble(0);
|
|
|
|
|
matchType = table->GetEntry("MatchType");
|
|
|
|
|
matchType.ForceSetDouble(0);
|
|
|
|
|
alliance = table->GetEntry("IsRedAlliance");
|
|
|
|
|
alliance.ForceSetBoolean(true);
|
|
|
|
|
station = table->GetEntry("StationNumber");
|
|
|
|
|
station.ForceSetDouble(1);
|
|
|
|
|
controlWord = table->GetEntry("FMSControlData");
|
|
|
|
|
controlWord.ForceSetDouble(0);
|
|
|
|
|
}
|
|
|
|
|
};
|
2017-11-09 19:59:29 -08:00
|
|
|
} // namespace frc
|
|
|
|
|
|
2016-11-01 22:33:12 -07:00
|
|
|
using namespace frc;
|
|
|
|
|
|
2017-11-19 19:04:28 -08:00
|
|
|
static constexpr double kJoystickUnpluggedMessageInterval = 1.0;
|
2013-12-15 18:30:16 -05:00
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
DriverStation::~DriverStation() {
|
2014-08-14 00:07:02 -07:00
|
|
|
m_isRunning = false;
|
2017-11-28 19:12:05 -08:00
|
|
|
// Trigger a DS mutex release in case there is no driver station running.
|
|
|
|
|
HAL_ReleaseDSMutex();
|
2016-11-01 20:12:08 -07:00
|
|
|
m_dsThread.join();
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2016-05-20 17:30:37 -07:00
|
|
|
DriverStation& DriverStation::GetInstance() {
|
2016-06-19 00:13:18 -07:00
|
|
|
static DriverStation instance;
|
|
|
|
|
return instance;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2018-04-29 23:33:19 -07:00
|
|
|
void DriverStation::ReportError(const wpi::Twine& error) {
|
|
|
|
|
wpi::SmallString<128> temp;
|
2017-12-01 21:31:35 -08:00
|
|
|
HAL_SendError(1, 1, 0, error.toNullTerminatedStringRef(temp).data(), "", "",
|
|
|
|
|
1);
|
2014-12-11 16:44:55 -05:00
|
|
|
}
|
|
|
|
|
|
2018-04-29 23:33:19 -07:00
|
|
|
void DriverStation::ReportWarning(const wpi::Twine& error) {
|
|
|
|
|
wpi::SmallString<128> temp;
|
2017-12-01 21:31:35 -08:00
|
|
|
HAL_SendError(0, 1, 0, error.toNullTerminatedStringRef(temp).data(), "", "",
|
|
|
|
|
1);
|
2014-12-03 07:42:48 -05:00
|
|
|
}
|
|
|
|
|
|
2017-11-22 17:06:57 -08:00
|
|
|
void DriverStation::ReportError(bool isError, int32_t code,
|
2018-04-29 23:33:19 -07:00
|
|
|
const wpi::Twine& error,
|
|
|
|
|
const wpi::Twine& location,
|
|
|
|
|
const wpi::Twine& stack) {
|
|
|
|
|
wpi::SmallString<128> errorTemp;
|
|
|
|
|
wpi::SmallString<128> locationTemp;
|
|
|
|
|
wpi::SmallString<128> stackTemp;
|
2017-12-01 21:31:35 -08:00
|
|
|
HAL_SendError(isError, code, 0,
|
|
|
|
|
error.toNullTerminatedStringRef(errorTemp).data(),
|
|
|
|
|
location.toNullTerminatedStringRef(locationTemp).data(),
|
|
|
|
|
stack.toNullTerminatedStringRef(stackTemp).data(), 1);
|
2016-02-04 22:29:11 -08:00
|
|
|
}
|
|
|
|
|
|
2017-10-27 21:45:56 -07:00
|
|
|
bool DriverStation::GetStickButton(int stick, int button) {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2017-10-27 21:45:56 -07:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
if (button <= 0) {
|
2017-10-27 21:45:56 -07:00
|
|
|
ReportJoystickUnpluggedError(
|
|
|
|
|
"ERROR: Button indexes begin at 1 in WPILib for C++ and Java");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickButtons buttons;
|
|
|
|
|
HAL_GetJoystickButtons(stick, &buttons);
|
|
|
|
|
|
|
|
|
|
if (button > buttons.count) {
|
2017-10-27 21:45:56 -07:00
|
|
|
ReportJoystickUnpluggedWarning(
|
2018-05-16 00:13:52 -07:00
|
|
|
"Joystick Button missing, check if all controllers are plugged in");
|
2017-10-27 21:45:56 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
return buttons.buttons & 1 << (button - 1);
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DriverStation::GetStickButtonPressed(int stick, int button) {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2017-10-27 21:45:56 -07:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
if (button <= 0) {
|
2017-10-27 21:45:56 -07:00
|
|
|
ReportJoystickUnpluggedError(
|
|
|
|
|
"ERROR: Button indexes begin at 1 in WPILib for C++ and Java");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickButtons buttons;
|
|
|
|
|
HAL_GetJoystickButtons(stick, &buttons);
|
|
|
|
|
|
|
|
|
|
if (button > buttons.count) {
|
2017-10-27 21:45:56 -07:00
|
|
|
ReportJoystickUnpluggedWarning(
|
2018-05-16 00:13:52 -07:00
|
|
|
"Joystick Button missing, check if all controllers are plugged in");
|
2017-10-27 21:45:56 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-07-07 19:17:14 -07:00
|
|
|
std::unique_lock lock(m_buttonEdgeMutex);
|
2017-10-27 21:45:56 -07:00
|
|
|
// If button was pressed, clear flag and return true
|
|
|
|
|
if (m_joystickButtonsPressed[stick] & 1 << (button - 1)) {
|
|
|
|
|
m_joystickButtonsPressed[stick] &= ~(1 << (button - 1));
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DriverStation::GetStickButtonReleased(int stick, int button) {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2017-10-27 21:45:56 -07:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-12-07 01:31:14 -05:00
|
|
|
if (button <= 0) {
|
2017-10-27 21:45:56 -07:00
|
|
|
ReportJoystickUnpluggedError(
|
|
|
|
|
"ERROR: Button indexes begin at 1 in WPILib for C++ and Java");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickButtons buttons;
|
|
|
|
|
HAL_GetJoystickButtons(stick, &buttons);
|
|
|
|
|
|
|
|
|
|
if (button > buttons.count) {
|
2017-10-27 21:45:56 -07:00
|
|
|
ReportJoystickUnpluggedWarning(
|
2018-05-16 00:13:52 -07:00
|
|
|
"Joystick Button missing, check if all controllers are plugged in");
|
2017-10-27 21:45:56 -07:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-07-07 19:17:14 -07:00
|
|
|
std::unique_lock lock(m_buttonEdgeMutex);
|
2017-10-27 21:45:56 -07:00
|
|
|
// If button was released, clear flag and return true
|
|
|
|
|
if (m_joystickButtonsReleased[stick] & 1 << (button - 1)) {
|
|
|
|
|
m_joystickButtonsReleased[stick] &= ~(1 << (button - 1));
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-20 07:25:03 -08:00
|
|
|
double DriverStation::GetStickAxis(int stick, int axis) {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
2018-05-16 00:13:52 -07:00
|
|
|
return 0.0;
|
|
|
|
|
}
|
2018-12-07 01:31:14 -05:00
|
|
|
if (axis < 0 || axis >= HAL_kMaxJoystickAxes) {
|
2018-05-16 00:13:52 -07:00
|
|
|
wpi_setWPIError(BadJoystickAxis);
|
|
|
|
|
return 0.0;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickAxes axes;
|
|
|
|
|
HAL_GetJoystickAxes(stick, &axes);
|
|
|
|
|
|
|
|
|
|
if (axis >= axes.count) {
|
2018-05-16 00:13:52 -07:00
|
|
|
ReportJoystickUnpluggedWarning(
|
|
|
|
|
"Joystick Axis missing, check if all controllers are plugged in");
|
2016-11-20 07:25:03 -08:00
|
|
|
return 0.0;
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
return axes.axes[axis];
|
2014-12-05 20:13:23 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
int DriverStation::GetStickPOV(int stick, int pov) {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return -1;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-12-07 01:31:14 -05:00
|
|
|
if (pov < 0 || pov >= HAL_kMaxJoystickPOVs) {
|
2018-05-16 00:13:52 -07:00
|
|
|
wpi_setWPIError(BadJoystickAxis);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickPOVs povs;
|
|
|
|
|
HAL_GetJoystickPOVs(stick, &povs);
|
|
|
|
|
|
|
|
|
|
if (pov >= povs.count) {
|
2018-05-16 00:13:52 -07:00
|
|
|
ReportJoystickUnpluggedWarning(
|
|
|
|
|
"Joystick POV missing, check if all controllers are plugged in");
|
2016-07-14 20:50:38 -07:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
return povs.povs[pov];
|
2015-06-15 12:34:57 -04:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
int DriverStation::GetStickButtons(int stick) const {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return 0;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickButtons buttons;
|
|
|
|
|
HAL_GetJoystickButtons(stick, &buttons);
|
|
|
|
|
|
|
|
|
|
return buttons.buttons;
|
2015-06-15 12:34:57 -04:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
int DriverStation::GetStickAxisCount(int stick) const {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return 0;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickAxes axes;
|
|
|
|
|
HAL_GetJoystickAxes(stick, &axes);
|
|
|
|
|
|
|
|
|
|
return axes.count;
|
2015-06-15 12:34:57 -04:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
int DriverStation::GetStickPOVCount(int stick) const {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickPOVs povs;
|
|
|
|
|
HAL_GetJoystickPOVs(stick, &povs);
|
|
|
|
|
|
|
|
|
|
return povs.count;
|
2014-12-05 20:13:23 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
int DriverStation::GetStickButtonCount(int stick) const {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickButtons buttons;
|
|
|
|
|
HAL_GetJoystickButtons(stick, &buttons);
|
|
|
|
|
|
|
|
|
|
return buttons.count;
|
2014-12-05 20:13:23 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
bool DriverStation::GetJoystickIsXbox(int stick) const {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return false;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickDescriptor descriptor;
|
|
|
|
|
HAL_GetJoystickDescriptor(stick, &descriptor);
|
|
|
|
|
|
|
|
|
|
return static_cast<bool>(descriptor.isXbox);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
int DriverStation::GetJoystickType(int stick) const {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickDescriptor descriptor;
|
|
|
|
|
HAL_GetJoystickDescriptor(stick, &descriptor);
|
|
|
|
|
|
|
|
|
|
return static_cast<int>(descriptor.type);
|
2014-10-17 14:46:25 -04:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
std::string DriverStation::GetJoystickName(int stick) const {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickDescriptor descriptor;
|
|
|
|
|
HAL_GetJoystickDescriptor(stick, &descriptor);
|
|
|
|
|
|
|
|
|
|
return descriptor.name;
|
2014-12-18 10:57:11 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
int DriverStation::GetJoystickAxisType(int stick, int axis) const {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2015-06-25 15:07:55 -04:00
|
|
|
wpi_setWPIError(BadJoystickIndex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return -1;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_JoystickDescriptor descriptor;
|
|
|
|
|
HAL_GetJoystickDescriptor(stick, &descriptor);
|
|
|
|
|
|
|
|
|
|
return static_cast<bool>(descriptor.axisTypes);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
bool DriverStation::IsEnabled() const {
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_ControlWord controlWord;
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_GetControlWord(&controlWord);
|
2015-06-25 15:07:55 -04:00
|
|
|
return controlWord.enabled && controlWord.dsAttached;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
bool DriverStation::IsDisabled() const {
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_ControlWord controlWord;
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_GetControlWord(&controlWord);
|
2015-06-25 15:07:55 -04:00
|
|
|
return !(controlWord.enabled && controlWord.dsAttached);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2019-07-16 09:18:23 -05:00
|
|
|
bool DriverStation::IsEStopped() const {
|
|
|
|
|
HAL_ControlWord controlWord;
|
|
|
|
|
HAL_GetControlWord(&controlWord);
|
|
|
|
|
return controlWord.eStop;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
bool DriverStation::IsAutonomous() const {
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_ControlWord controlWord;
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_GetControlWord(&controlWord);
|
2015-06-25 15:07:55 -04:00
|
|
|
return controlWord.autonomous;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
bool DriverStation::IsOperatorControl() const {
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_ControlWord controlWord;
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_GetControlWord(&controlWord);
|
2015-06-25 15:07:55 -04:00
|
|
|
return !(controlWord.autonomous || controlWord.test);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
bool DriverStation::IsTest() const {
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_ControlWord controlWord;
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_GetControlWord(&controlWord);
|
2015-06-25 15:07:55 -04:00
|
|
|
return controlWord.test;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
bool DriverStation::IsDSAttached() const {
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_ControlWord controlWord;
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_GetControlWord(&controlWord);
|
2015-06-25 15:07:55 -04:00
|
|
|
return controlWord.dsAttached;
|
2014-11-18 10:56:25 -05:00
|
|
|
}
|
|
|
|
|
|
2017-05-08 20:21:47 -07:00
|
|
|
bool DriverStation::IsNewControlData() const { return HAL_IsNewControlData(); }
|
2016-07-14 20:50:38 -07:00
|
|
|
|
|
|
|
|
bool DriverStation::IsFMSAttached() const {
|
|
|
|
|
HAL_ControlWord controlWord;
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_GetControlWord(&controlWord);
|
2016-07-14 20:50:38 -07:00
|
|
|
return controlWord.fmsAttached;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 19:59:29 -08:00
|
|
|
std::string DriverStation::GetGameSpecificMessage() const {
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_MatchInfo info;
|
|
|
|
|
HAL_GetMatchInfo(&info);
|
|
|
|
|
return std::string(reinterpret_cast<char*>(info.gameSpecificMessage),
|
|
|
|
|
info.gameSpecificMessageSize);
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string DriverStation::GetEventName() const {
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_MatchInfo info;
|
|
|
|
|
HAL_GetMatchInfo(&info);
|
|
|
|
|
return info.eventName;
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DriverStation::MatchType DriverStation::GetMatchType() const {
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_MatchInfo info;
|
|
|
|
|
HAL_GetMatchInfo(&info);
|
|
|
|
|
return static_cast<DriverStation::MatchType>(info.matchType);
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int DriverStation::GetMatchNumber() const {
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_MatchInfo info;
|
|
|
|
|
HAL_GetMatchInfo(&info);
|
|
|
|
|
return info.matchNumber;
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int DriverStation::GetReplayNumber() const {
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_MatchInfo info;
|
|
|
|
|
HAL_GetMatchInfo(&info);
|
|
|
|
|
return info.replayNumber;
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
DriverStation::Alliance DriverStation::GetAlliance() const {
|
2016-07-10 16:24:57 -07:00
|
|
|
int32_t status = 0;
|
|
|
|
|
auto allianceStationID = HAL_GetAllianceStation(&status);
|
2015-06-25 15:07:55 -04:00
|
|
|
switch (allianceStationID) {
|
2016-07-09 00:24:26 -07:00
|
|
|
case HAL_AllianceStationID_kRed1:
|
|
|
|
|
case HAL_AllianceStationID_kRed2:
|
|
|
|
|
case HAL_AllianceStationID_kRed3:
|
2015-06-25 15:07:55 -04:00
|
|
|
return kRed;
|
2016-07-09 00:24:26 -07:00
|
|
|
case HAL_AllianceStationID_kBlue1:
|
|
|
|
|
case HAL_AllianceStationID_kBlue2:
|
|
|
|
|
case HAL_AllianceStationID_kBlue3:
|
2015-06-25 15:07:55 -04:00
|
|
|
return kBlue;
|
|
|
|
|
default:
|
|
|
|
|
return kInvalid;
|
|
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 00:01:45 -07:00
|
|
|
int DriverStation::GetLocation() const {
|
2016-07-10 16:24:57 -07:00
|
|
|
int32_t status = 0;
|
|
|
|
|
auto allianceStationID = HAL_GetAllianceStation(&status);
|
2015-06-25 15:07:55 -04:00
|
|
|
switch (allianceStationID) {
|
2016-07-09 00:24:26 -07:00
|
|
|
case HAL_AllianceStationID_kRed1:
|
|
|
|
|
case HAL_AllianceStationID_kBlue1:
|
2015-06-25 15:07:55 -04:00
|
|
|
return 1;
|
2016-07-09 00:24:26 -07:00
|
|
|
case HAL_AllianceStationID_kRed2:
|
|
|
|
|
case HAL_AllianceStationID_kBlue2:
|
2015-06-25 15:07:55 -04:00
|
|
|
return 2;
|
2016-07-09 00:24:26 -07:00
|
|
|
case HAL_AllianceStationID_kRed3:
|
|
|
|
|
case HAL_AllianceStationID_kBlue3:
|
2015-06-25 15:07:55 -04:00
|
|
|
return 3;
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2016-10-09 11:46:01 -07:00
|
|
|
void DriverStation::WaitForData() { WaitForData(0); }
|
|
|
|
|
|
|
|
|
|
bool DriverStation::WaitForData(double timeout) {
|
2018-01-18 21:54:33 -08:00
|
|
|
auto timeoutTime =
|
|
|
|
|
std::chrono::steady_clock::now() + std::chrono::duration<double>(timeout);
|
|
|
|
|
|
2019-07-07 19:17:14 -07:00
|
|
|
std::unique_lock lock(m_waitForDataMutex);
|
2018-01-18 21:54:33 -08:00
|
|
|
int currentCount = m_waitForDataCounter;
|
|
|
|
|
while (m_waitForDataCounter == currentCount) {
|
|
|
|
|
if (timeout > 0) {
|
|
|
|
|
auto timedOut = m_waitForDataCond.wait_until(lock, timeoutTime);
|
|
|
|
|
if (timedOut == std::cv_status::timeout) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
m_waitForDataCond.wait(lock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
double DriverStation::GetMatchTime() const {
|
2016-07-10 16:24:57 -07:00
|
|
|
int32_t status;
|
|
|
|
|
return HAL_GetMatchTime(&status);
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|
2014-10-20 17:19:28 -04:00
|
|
|
|
2016-11-20 07:25:03 -08:00
|
|
|
double DriverStation::GetBatteryVoltage() const {
|
2016-07-14 20:50:38 -07:00
|
|
|
int32_t status = 0;
|
2016-11-20 07:25:03 -08:00
|
|
|
double voltage = HAL_GetVinVoltage(&status);
|
2016-07-14 20:50:38 -07:00
|
|
|
wpi_setErrorWithContext(status, "getVinVoltage");
|
|
|
|
|
|
|
|
|
|
return voltage;
|
2016-02-04 22:29:11 -08:00
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
|
2019-11-05 21:33:09 -08:00
|
|
|
void DriverStation::WakeupWaitForData() {
|
|
|
|
|
std::scoped_lock waitLock(m_waitForDataMutex);
|
|
|
|
|
// Nofify all threads
|
|
|
|
|
m_waitForDataCounter++;
|
|
|
|
|
m_waitForDataCond.notify_all();
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
void DriverStation::GetData() {
|
2018-01-18 23:17:28 -08:00
|
|
|
{
|
2018-07-18 22:22:41 -07:00
|
|
|
// Compute the pressed and released buttons
|
|
|
|
|
HAL_JoystickButtons currentButtons;
|
2019-07-07 19:17:14 -07:00
|
|
|
std::unique_lock lock(m_buttonEdgeMutex);
|
2018-01-18 23:17:28 -08:00
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < kJoystickPorts; i++) {
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_GetJoystickButtons(i, ¤tButtons);
|
|
|
|
|
|
2018-01-18 23:17:28 -08:00
|
|
|
// If buttons weren't pressed and are now, set flags in m_buttonsPressed
|
|
|
|
|
m_joystickButtonsPressed[i] |=
|
2018-07-18 22:22:41 -07:00
|
|
|
~m_previousButtonStates[i].buttons & currentButtons.buttons;
|
2017-10-27 21:45:56 -07:00
|
|
|
|
2018-01-18 23:17:28 -08:00
|
|
|
// If buttons were pressed and aren't now, set flags in m_buttonsReleased
|
|
|
|
|
m_joystickButtonsReleased[i] |=
|
2018-07-18 22:22:41 -07:00
|
|
|
m_previousButtonStates[i].buttons & ~currentButtons.buttons;
|
2018-01-18 23:17:28 -08:00
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
m_previousButtonStates[i] = currentButtons;
|
|
|
|
|
}
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
|
|
|
|
|
2019-11-05 21:33:09 -08:00
|
|
|
WakeupWaitForData();
|
2018-01-18 23:17:28 -08:00
|
|
|
SendMatchData();
|
2016-02-04 22:29:11 -08:00
|
|
|
}
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
DriverStation::DriverStation() {
|
2018-05-24 17:03:19 -07:00
|
|
|
HAL_Initialize(500, 0);
|
2018-01-18 21:54:33 -08:00
|
|
|
m_waitForDataCounter = 0;
|
2016-07-14 20:50:38 -07:00
|
|
|
|
2018-01-18 23:17:28 -08:00
|
|
|
m_matchDataSender = std::make_unique<MatchDataSender>();
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
// All joysticks should default to having zero axes, povs and buttons, so
|
|
|
|
|
// uninitialized memory doesn't get sent to speed controllers.
|
|
|
|
|
for (unsigned int i = 0; i < kJoystickPorts; i++) {
|
2017-10-27 21:45:56 -07:00
|
|
|
m_joystickButtonsPressed[i] = 0;
|
|
|
|
|
m_joystickButtonsReleased[i] = 0;
|
2018-07-18 22:22:41 -07:00
|
|
|
m_previousButtonStates[i].count = 0;
|
|
|
|
|
m_previousButtonStates[i].buttons = 0;
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
|
2016-11-01 20:12:08 -07:00
|
|
|
m_dsThread = std::thread(&DriverStation::Run, this);
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
|
2018-04-29 23:33:19 -07:00
|
|
|
void DriverStation::ReportJoystickUnpluggedError(const wpi::Twine& message) {
|
2016-07-14 20:50:38 -07:00
|
|
|
double currentTime = Timer::GetFPGATimestamp();
|
|
|
|
|
if (currentTime > m_nextMessageTime) {
|
|
|
|
|
ReportError(message);
|
2017-11-19 19:04:28 -08:00
|
|
|
m_nextMessageTime = currentTime + kJoystickUnpluggedMessageInterval;
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-29 23:33:19 -07:00
|
|
|
void DriverStation::ReportJoystickUnpluggedWarning(const wpi::Twine& message) {
|
2016-07-14 20:50:38 -07:00
|
|
|
double currentTime = Timer::GetFPGATimestamp();
|
|
|
|
|
if (currentTime > m_nextMessageTime) {
|
|
|
|
|
ReportWarning(message);
|
2017-11-19 19:04:28 -08:00
|
|
|
m_nextMessageTime = currentTime + kJoystickUnpluggedMessageInterval;
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DriverStation::Run() {
|
|
|
|
|
m_isRunning = true;
|
2018-12-29 16:19:23 -08:00
|
|
|
int safetyCounter = 0;
|
2016-07-14 20:50:38 -07:00
|
|
|
while (m_isRunning) {
|
|
|
|
|
HAL_WaitForDSData();
|
|
|
|
|
GetData();
|
|
|
|
|
|
2018-12-29 16:19:23 -08:00
|
|
|
if (IsDisabled()) safetyCounter = 0;
|
|
|
|
|
|
|
|
|
|
if (++safetyCounter >= 4) {
|
|
|
|
|
MotorSafety::CheckMotors();
|
|
|
|
|
safetyCounter = 0;
|
|
|
|
|
}
|
2016-07-14 20:50:38 -07:00
|
|
|
if (m_userInDisabled) HAL_ObserveUserProgramDisabled();
|
|
|
|
|
if (m_userInAutonomous) HAL_ObserveUserProgramAutonomous();
|
|
|
|
|
if (m_userInTeleop) HAL_ObserveUserProgramTeleop();
|
|
|
|
|
if (m_userInTest) HAL_ObserveUserProgramTest();
|
|
|
|
|
}
|
2014-10-20 17:19:28 -04:00
|
|
|
}
|
2016-07-15 13:39:26 -07:00
|
|
|
|
2018-05-31 20:47:15 -07:00
|
|
|
void DriverStation::SendMatchData() {
|
|
|
|
|
int32_t status = 0;
|
|
|
|
|
HAL_AllianceStationID alliance = HAL_GetAllianceStation(&status);
|
|
|
|
|
bool isRedAlliance = false;
|
|
|
|
|
int stationNumber = 1;
|
|
|
|
|
switch (alliance) {
|
|
|
|
|
case HAL_AllianceStationID::HAL_AllianceStationID_kBlue1:
|
|
|
|
|
isRedAlliance = false;
|
|
|
|
|
stationNumber = 1;
|
|
|
|
|
break;
|
|
|
|
|
case HAL_AllianceStationID::HAL_AllianceStationID_kBlue2:
|
|
|
|
|
isRedAlliance = false;
|
|
|
|
|
stationNumber = 2;
|
|
|
|
|
break;
|
|
|
|
|
case HAL_AllianceStationID::HAL_AllianceStationID_kBlue3:
|
|
|
|
|
isRedAlliance = false;
|
|
|
|
|
stationNumber = 3;
|
|
|
|
|
break;
|
|
|
|
|
case HAL_AllianceStationID::HAL_AllianceStationID_kRed1:
|
|
|
|
|
isRedAlliance = true;
|
|
|
|
|
stationNumber = 1;
|
|
|
|
|
break;
|
|
|
|
|
case HAL_AllianceStationID::HAL_AllianceStationID_kRed2:
|
|
|
|
|
isRedAlliance = true;
|
|
|
|
|
stationNumber = 2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
isRedAlliance = true;
|
|
|
|
|
stationNumber = 3;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_MatchInfo tmpDataStore;
|
|
|
|
|
HAL_GetMatchInfo(&tmpDataStore);
|
2018-05-31 20:47:15 -07:00
|
|
|
|
|
|
|
|
m_matchDataSender->alliance.SetBoolean(isRedAlliance);
|
|
|
|
|
m_matchDataSender->station.SetDouble(stationNumber);
|
|
|
|
|
m_matchDataSender->eventName.SetString(tmpDataStore.eventName);
|
|
|
|
|
m_matchDataSender->gameSpecificMessage.SetString(
|
2018-07-18 22:22:41 -07:00
|
|
|
std::string(reinterpret_cast<char*>(tmpDataStore.gameSpecificMessage),
|
|
|
|
|
tmpDataStore.gameSpecificMessageSize));
|
2018-05-31 20:47:15 -07:00
|
|
|
m_matchDataSender->matchNumber.SetDouble(tmpDataStore.matchNumber);
|
|
|
|
|
m_matchDataSender->replayNumber.SetDouble(tmpDataStore.replayNumber);
|
|
|
|
|
m_matchDataSender->matchType.SetDouble(
|
|
|
|
|
static_cast<int>(tmpDataStore.matchType));
|
|
|
|
|
|
|
|
|
|
HAL_ControlWord ctlWord;
|
2018-07-18 22:22:41 -07:00
|
|
|
HAL_GetControlWord(&ctlWord);
|
2018-05-31 20:47:15 -07:00
|
|
|
int32_t wordInt = 0;
|
|
|
|
|
std::memcpy(&wordInt, &ctlWord, sizeof(wordInt));
|
|
|
|
|
m_matchDataSender->controlWord.SetDouble(wordInt);
|
|
|
|
|
}
|