2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2018-01-02 09:20:21 -08:00
|
|
|
/* Copyright (c) 2008-2018 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
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "DriverStation.h"
|
2016-09-14 20:52:06 -07:00
|
|
|
|
2016-10-09 11:46:01 -07:00
|
|
|
#include <chrono>
|
|
|
|
|
|
2017-08-27 00:11:52 -07:00
|
|
|
#include <HAL/HAL.h>
|
|
|
|
|
#include <HAL/Power.h>
|
|
|
|
|
#include <HAL/cpp/Log.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
|
|
|
|
2014-06-12 18:07:45 -04:00
|
|
|
#include "AnalogInput.h"
|
2013-12-15 18:30:16 -05:00
|
|
|
#include "MotorSafetyHelper.h"
|
2016-05-20 17:30:37 -07:00
|
|
|
#include "Timer.h"
|
2013-12-15 18:30:16 -05:00
|
|
|
#include "Utility.h"
|
|
|
|
|
#include "WPIErrors.h"
|
2014-01-06 10:12:21 -05:00
|
|
|
|
2017-11-09 19:59:29 -08:00
|
|
|
namespace frc {
|
|
|
|
|
struct MatchInfoData {
|
|
|
|
|
std::string eventName;
|
|
|
|
|
std::string gameSpecificMessage;
|
|
|
|
|
int matchNumber = 0;
|
|
|
|
|
int replayNumber = 0;
|
|
|
|
|
DriverStation::MatchType matchType = DriverStation::MatchType::kNone;
|
|
|
|
|
};
|
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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::unique_lock<wpi::mutex> lock(m_cacheDataMutex);
|
2017-10-27 21:45:56 -07:00
|
|
|
if (button > m_joystickButtons[stick].count) {
|
|
|
|
|
// Unlock early so error printing isn't locked.
|
|
|
|
|
lock.unlock();
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return m_joystickButtons[stick].buttons & 1 << (button - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::unique_lock<wpi::mutex> lock(m_cacheDataMutex);
|
2017-10-27 21:45:56 -07:00
|
|
|
if (button > m_joystickButtons[stick].count) {
|
|
|
|
|
// Unlock early so error printing isn't locked.
|
|
|
|
|
lock.unlock();
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
if (button == 0) {
|
|
|
|
|
ReportJoystickUnpluggedError(
|
|
|
|
|
"ERROR: Button indexes begin at 1 in WPILib for C++ and Java");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::unique_lock<wpi::mutex> lock(m_cacheDataMutex);
|
2017-10-27 21:45:56 -07:00
|
|
|
if (button > m_joystickButtons[stick].count) {
|
|
|
|
|
// Unlock early so error printing isn't locked.
|
|
|
|
|
lock.unlock();
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
if (axis >= HAL_kMaxJoystickAxes) {
|
|
|
|
|
wpi_setWPIError(BadJoystickAxis);
|
|
|
|
|
return 0.0;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::unique_lock<wpi::mutex> lock(m_cacheDataMutex);
|
2016-07-14 20:50:38 -07:00
|
|
|
if (axis >= m_joystickAxes[stick].count) {
|
|
|
|
|
// Unlock early so error printing isn't locked.
|
2018-05-16 00:13:52 -07:00
|
|
|
lock.unlock();
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return m_joystickAxes[stick].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-05-16 00:13:52 -07:00
|
|
|
if (pov >= HAL_kMaxJoystickPOVs) {
|
|
|
|
|
wpi_setWPIError(BadJoystickAxis);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::unique_lock<wpi::mutex> lock(m_cacheDataMutex);
|
2016-07-14 20:50:38 -07:00
|
|
|
if (pov >= m_joystickPOVs[stick].count) {
|
|
|
|
|
// Unlock early so error printing isn't locked.
|
|
|
|
|
lock.unlock();
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return m_joystickPOVs[stick].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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return m_joystickButtons[stick].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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return m_joystickAxes[stick].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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
Implements locking in C++ DriverStation, and adds double buffering to DS Thread (#25)
Currently, about 5ms of every 20ms loop the DS thread would hold
the mutex, while grabbing data. During this time, and call to grab
joystick data would be blocked. This change grabs the joystick data
to a cache, and then grabs the mutex and moves the data references
around. This is much more efficient then the old code, and gives
teams more of their teleop loop time back for use.
Another major change this does is use preallocated arrays when entering
the JNI. Previously every JNI DS call would allocate an entire new array.
With a GC'd language where those arrays go on the heap, thats a problem,
and creates tons of garbage. That garbage is no longer created anymore,
as all arrays and byte buffers sent to JNI in the DS are preallocated.
In addition, GetJoystickName was always returning joystick 0 data, which
this fixes.
2016-05-21 00:41:15 -07:00
|
|
|
return m_joystickPOVs[stick].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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
Implements locking in C++ DriverStation, and adds double buffering to DS Thread (#25)
Currently, about 5ms of every 20ms loop the DS thread would hold
the mutex, while grabbing data. During this time, and call to grab
joystick data would be blocked. This change grabs the joystick data
to a cache, and then grabs the mutex and moves the data references
around. This is much more efficient then the old code, and gives
teams more of their teleop loop time back for use.
Another major change this does is use preallocated arrays when entering
the JNI. Previously every JNI DS call would allocate an entire new array.
With a GC'd language where those arrays go on the heap, thats a problem,
and creates tons of garbage. That garbage is no longer created anymore,
as all arrays and byte buffers sent to JNI in the DS are preallocated.
In addition, GetJoystickName was always returning joystick 0 data, which
this fixes.
2016-05-21 00:41:15 -07:00
|
|
|
return m_joystickButtons[stick].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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return static_cast<bool>(m_joystickDescriptor[stick].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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return static_cast<int>(m_joystickDescriptor[stick].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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2018-05-16 00:13:52 -07:00
|
|
|
return m_joystickDescriptor[stick].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
|
|
|
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2016-07-14 20:50:38 -07:00
|
|
|
return m_joystickDescriptor[stick].axisTypes[axis];
|
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;
|
2016-07-15 13:39:26 -07:00
|
|
|
UpdateControlWord(false, 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;
|
2016-07-15 13:39:26 -07:00
|
|
|
UpdateControlWord(false, 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::IsAutonomous() const {
|
2016-07-09 00:24:26 -07:00
|
|
|
HAL_ControlWord controlWord;
|
2016-07-15 13:39:26 -07:00
|
|
|
UpdateControlWord(false, 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;
|
2016-07-15 13:39:26 -07:00
|
|
|
UpdateControlWord(false, 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;
|
2016-07-15 13:39:26 -07:00
|
|
|
UpdateControlWord(false, 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;
|
2016-07-15 13:39:26 -07:00
|
|
|
UpdateControlWord(false, 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;
|
2016-07-15 13:39:26 -07:00
|
|
|
UpdateControlWord(false, controlWord);
|
2016-07-14 20:50:38 -07:00
|
|
|
return controlWord.fmsAttached;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
bool DriverStation::IsSysActive() const {
|
|
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
bool retVal = HAL_GetSystemActive(&status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return retVal;
|
2014-11-18 10:56:25 -05:00
|
|
|
}
|
|
|
|
|
|
2016-05-25 23:09:24 -07:00
|
|
|
bool DriverStation::IsBrownedOut() const {
|
2015-06-25 15:07:55 -04:00
|
|
|
int32_t status = 0;
|
2016-07-09 00:24:26 -07:00
|
|
|
bool retVal = HAL_GetBrownedOut(&status);
|
|
|
|
|
wpi_setErrorWithContext(status, HAL_GetErrorMessage(status));
|
2015-06-25 15:07:55 -04:00
|
|
|
return retVal;
|
2014-11-18 10:56:25 -05:00
|
|
|
}
|
|
|
|
|
|
2017-11-09 19:59:29 -08:00
|
|
|
std::string DriverStation::GetGameSpecificMessage() const {
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2017-11-09 19:59:29 -08:00
|
|
|
return m_matchInfo->gameSpecificMessage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string DriverStation::GetEventName() const {
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2017-11-09 19:59:29 -08:00
|
|
|
return m_matchInfo->eventName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DriverStation::MatchType DriverStation::GetMatchType() const {
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2017-11-09 19:59:29 -08:00
|
|
|
return m_matchInfo->matchType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int DriverStation::GetMatchNumber() const {
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2017-11-09 19:59:29 -08:00
|
|
|
return m_matchInfo->matchNumber;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int DriverStation::GetReplayNumber() const {
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
2017-11-09 19:59:29 -08:00
|
|
|
return m_matchInfo->replayNumber;
|
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
std::unique_lock<wpi::mutex> lock(m_waitForDataMutex);
|
|
|
|
|
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
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
void DriverStation::GetData() {
|
|
|
|
|
// Get the status of all of the joysticks, and save to the cache
|
|
|
|
|
for (uint8_t stick = 0; stick < kJoystickPorts; stick++) {
|
|
|
|
|
HAL_GetJoystickAxes(stick, &m_joystickAxesCache[stick]);
|
|
|
|
|
HAL_GetJoystickPOVs(stick, &m_joystickPOVsCache[stick]);
|
|
|
|
|
HAL_GetJoystickButtons(stick, &m_joystickButtonsCache[stick]);
|
|
|
|
|
HAL_GetJoystickDescriptor(stick, &m_joystickDescriptorCache[stick]);
|
|
|
|
|
}
|
2017-11-09 19:59:29 -08:00
|
|
|
// Grab match specific data
|
|
|
|
|
HAL_MatchInfo matchInfo;
|
|
|
|
|
auto status = HAL_GetMatchInfo(&matchInfo);
|
|
|
|
|
if (status == 0) {
|
|
|
|
|
m_matchInfoCache->eventName = matchInfo.eventName;
|
|
|
|
|
m_matchInfoCache->matchNumber = matchInfo.matchNumber;
|
|
|
|
|
m_matchInfoCache->replayNumber = matchInfo.replayNumber;
|
|
|
|
|
m_matchInfoCache->matchType =
|
|
|
|
|
static_cast<DriverStation::MatchType>(matchInfo.matchType);
|
|
|
|
|
m_matchInfoCache->gameSpecificMessage = matchInfo.gameSpecificMessage;
|
|
|
|
|
}
|
|
|
|
|
HAL_FreeMatchInfo(&matchInfo);
|
|
|
|
|
|
2016-07-15 13:39:26 -07:00
|
|
|
// Force a control word update, to make sure the data is the newest.
|
|
|
|
|
HAL_ControlWord controlWord;
|
|
|
|
|
UpdateControlWord(true, controlWord);
|
2017-10-27 21:45:56 -07:00
|
|
|
|
2018-01-18 23:17:28 -08:00
|
|
|
{
|
|
|
|
|
// Obtain a write lock on the data, swap the cached data into the
|
|
|
|
|
// main data arrays
|
|
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
|
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < kJoystickPorts; i++) {
|
|
|
|
|
// If buttons weren't pressed and are now, set flags in m_buttonsPressed
|
|
|
|
|
m_joystickButtonsPressed[i] |=
|
|
|
|
|
~m_joystickButtons[i].buttons & m_joystickButtonsCache[i].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] |=
|
|
|
|
|
m_joystickButtons[i].buttons & ~m_joystickButtonsCache[i].buttons;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_joystickAxes.swap(m_joystickAxesCache);
|
|
|
|
|
m_joystickPOVs.swap(m_joystickPOVsCache);
|
|
|
|
|
m_joystickButtons.swap(m_joystickButtonsCache);
|
|
|
|
|
m_joystickDescriptor.swap(m_joystickDescriptorCache);
|
|
|
|
|
m_matchInfo.swap(m_matchInfoCache);
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
|
|
|
|
|
2018-01-18 23:17:28 -08:00
|
|
|
{
|
|
|
|
|
std::lock_guard<wpi::mutex> waitLock(m_waitForDataMutex);
|
|
|
|
|
// Nofify all threads
|
|
|
|
|
m_waitForDataCounter++;
|
|
|
|
|
m_waitForDataCond.notify_all();
|
|
|
|
|
}
|
2018-01-18 21:54:33 -08:00
|
|
|
|
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
|
|
|
m_joystickAxes = std::make_unique<HAL_JoystickAxes[]>(kJoystickPorts);
|
|
|
|
|
m_joystickPOVs = std::make_unique<HAL_JoystickPOVs[]>(kJoystickPorts);
|
|
|
|
|
m_joystickButtons = std::make_unique<HAL_JoystickButtons[]>(kJoystickPorts);
|
|
|
|
|
m_joystickDescriptor =
|
|
|
|
|
std::make_unique<HAL_JoystickDescriptor[]>(kJoystickPorts);
|
2017-11-09 19:59:29 -08:00
|
|
|
m_matchInfo = std::make_unique<MatchInfoData>();
|
2016-07-14 20:50:38 -07:00
|
|
|
m_joystickAxesCache = std::make_unique<HAL_JoystickAxes[]>(kJoystickPorts);
|
|
|
|
|
m_joystickPOVsCache = std::make_unique<HAL_JoystickPOVs[]>(kJoystickPorts);
|
|
|
|
|
m_joystickButtonsCache =
|
|
|
|
|
std::make_unique<HAL_JoystickButtons[]>(kJoystickPorts);
|
|
|
|
|
m_joystickDescriptorCache =
|
|
|
|
|
std::make_unique<HAL_JoystickDescriptor[]>(kJoystickPorts);
|
2017-11-09 19:59:29 -08:00
|
|
|
m_matchInfoCache = std::make_unique<MatchInfoData>();
|
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++) {
|
|
|
|
|
m_joystickAxes[i].count = 0;
|
|
|
|
|
m_joystickPOVs[i].count = 0;
|
|
|
|
|
m_joystickButtons[i].count = 0;
|
|
|
|
|
m_joystickDescriptor[i].isXbox = 0;
|
|
|
|
|
m_joystickDescriptor[i].type = -1;
|
|
|
|
|
m_joystickDescriptor[i].name[0] = '\0';
|
|
|
|
|
|
|
|
|
|
m_joystickAxesCache[i].count = 0;
|
|
|
|
|
m_joystickPOVsCache[i].count = 0;
|
|
|
|
|
m_joystickButtonsCache[i].count = 0;
|
|
|
|
|
m_joystickDescriptorCache[i].isXbox = 0;
|
|
|
|
|
m_joystickDescriptorCache[i].type = -1;
|
|
|
|
|
m_joystickDescriptorCache[i].name[0] = '\0';
|
2017-10-27 21:45:56 -07:00
|
|
|
|
|
|
|
|
m_joystickButtonsPressed[i] = 0;
|
|
|
|
|
m_joystickButtonsReleased[i] = 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;
|
2017-11-23 00:36:57 -08:00
|
|
|
int safetyCounter = 0;
|
2016-07-14 20:50:38 -07:00
|
|
|
while (m_isRunning) {
|
|
|
|
|
HAL_WaitForDSData();
|
|
|
|
|
GetData();
|
|
|
|
|
|
2017-11-23 00:36:57 -08:00
|
|
|
if (IsDisabled()) safetyCounter = 0;
|
|
|
|
|
|
|
|
|
|
if (++safetyCounter >= 4) {
|
2016-07-14 20:50:38 -07:00
|
|
|
MotorSafetyHelper::CheckMotors();
|
2017-11-23 00:36:57 -08:00
|
|
|
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
|
|
|
|
|
|
|
|
void DriverStation::UpdateControlWord(bool force,
|
|
|
|
|
HAL_ControlWord& controlWord) const {
|
|
|
|
|
auto now = std::chrono::steady_clock::now();
|
2017-11-13 09:51:48 -08:00
|
|
|
std::lock_guard<wpi::mutex> lock(m_controlWordMutex);
|
2016-07-15 13:39:26 -07:00
|
|
|
// Update every 50 ms or on force.
|
|
|
|
|
if ((now - m_lastControlWordUpdate > std::chrono::milliseconds(50)) ||
|
|
|
|
|
force) {
|
|
|
|
|
HAL_GetControlWord(&m_controlWordCache);
|
|
|
|
|
m_lastControlWordUpdate = now;
|
|
|
|
|
}
|
|
|
|
|
controlWord = m_controlWordCache;
|
|
|
|
|
}
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MatchInfoData tmpDataStore;
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<wpi::mutex> lock(m_cacheDataMutex);
|
|
|
|
|
tmpDataStore = *m_matchInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_matchDataSender->alliance.SetBoolean(isRedAlliance);
|
|
|
|
|
m_matchDataSender->station.SetDouble(stationNumber);
|
|
|
|
|
m_matchDataSender->eventName.SetString(tmpDataStore.eventName);
|
|
|
|
|
m_matchDataSender->gameSpecificMessage.SetString(
|
|
|
|
|
tmpDataStore.gameSpecificMessage);
|
|
|
|
|
m_matchDataSender->matchNumber.SetDouble(tmpDataStore.matchNumber);
|
|
|
|
|
m_matchDataSender->replayNumber.SetDouble(tmpDataStore.replayNumber);
|
|
|
|
|
m_matchDataSender->matchType.SetDouble(
|
|
|
|
|
static_cast<int>(tmpDataStore.matchType));
|
|
|
|
|
|
|
|
|
|
HAL_ControlWord ctlWord;
|
|
|
|
|
{
|
|
|
|
|
// Valid, as in other places we guarentee ctlWord >= int32
|
|
|
|
|
std::lock_guard<wpi::mutex> lock(m_controlWordMutex);
|
|
|
|
|
ctlWord = m_controlWordCache;
|
|
|
|
|
}
|
|
|
|
|
int32_t wordInt = 0;
|
|
|
|
|
std::memcpy(&wordInt, &ctlWord, sizeof(wordInt));
|
|
|
|
|
m_matchDataSender->controlWord.SetDouble(wordInt);
|
|
|
|
|
}
|