[sim] Add joystick simulation support (#2595)

This adds joystick functions to DriverStationSim, and new GenericHIDSim,
JoystickSim, and XboxControllerSim classes.
This commit is contained in:
Peter Johnson
2020-07-15 00:33:57 -07:00
committed by GitHub
parent b06ddcdd86
commit b9feb81226
19 changed files with 1979 additions and 19 deletions

View File

@@ -40,16 +40,48 @@ public class DriverStationDataJNI extends JNIWrapper {
public static native boolean getDsAttached();
public static native void setDsAttached(boolean dsAttached);
public static native int registerAllianceStationIdCallback(NotifyCallback callback, boolean initialNotify);
public static native void cancelAllianceStationIdCallback(int uid);
public static native int getAllianceStationId();
public static native void setAllianceStationId(int allianceStationId);
public static native int registerMatchTimeCallback(NotifyCallback callback, boolean initialNotify);
public static native void cancelMatchTimeCallback(int uid);
public static native double getMatchTime();
public static native void setMatchTime(double matchTime);
public static native void setJoystickAxes(byte joystickNum, float[] axesArray);
public static native void setJoystickPOVs(byte joystickNum, short[] povsArray);
public static native void setJoystickButtons(byte joystickNum, int buttons, int count);
public static native long getJoystickOutputs(int stick);
public static native int getJoystickRumble(int stick, int rumbleNum);
public static native void setMatchInfo(String eventName, String gameSpecificMessage, int matchNumber, int replayNumber, int matchType);
public static native void registerAllCallbacks(NotifyCallback callback, boolean initialNotify);
public static native void notifyNewData();
public static native void setSendError(boolean shouldSend);
public static native void setSendConsoleLine(boolean shouldSend);
public static native void setJoystickButton(int stick, int button, boolean state);
public static native void setJoystickAxis(int stick, int axis, double value);
public static native void setJoystickPOV(int stick, int pov, int value);
public static native void setJoystickButtonsValue(int stick, int buttons);
public static native void setJoystickAxisCount(int stick, int count);
public static native void setJoystickPOVCount(int stick, int count);
public static native void setJoystickButtonCount(int stick, int count);
public static native void setJoystickIsXbox(int stick, boolean isXbox);
public static native void setJoystickType(int stick, int type);
public static native void setJoystickName(int stick, String name);
public static native void setJoystickAxisType(int stick, int axis, int type);
public static native void setGameSpecificMessage(String message);
public static native void setEventName(String name);
public static native void setMatchType(int type);
public static native void setMatchNumber(int matchNumber);
public static native void setReplayNumber(int replayNumber);
public static native void resetData();
}

View File

@@ -45,6 +45,38 @@ void HALSIM_SetMatchInfo(const HAL_MatchInfo* info) {}
void HALSIM_NotifyDriverStationNewData(void) {}
void HALSIM_SetJoystickButton(int32_t stick, int32_t button, HAL_Bool state) {}
void HALSIM_SetJoystickAxis(int32_t stick, int32_t axis, double value) {}
void HALSIM_SetJoystickPOV(int32_t stick, int32_t pov, int32_t value) {}
void HALSIM_SetJoystickButtonsValue(int32_t stick, uint32_t buttons) {}
void HALSIM_SetJoystickAxisCount(int32_t stick, int32_t count) {}
void HALSIM_SetJoystickPOVCount(int32_t stick, int32_t count) {}
void HALSIM_SetJoystickButtonCount(int32_t stick, int32_t count) {}
void HALSIM_SetJoystickIsXbox(int32_t stick, HAL_Bool isXbox) {}
void HALSIM_SetJoystickType(int32_t stick, int32_t type) {}
void HALSIM_SetJoystickName(int32_t stick, const char* name) {}
void HALSIM_SetJoystickAxisType(int32_t stick, int32_t axis, int32_t type) {}
void HALSIM_SetGameSpecificMessage(const char* message) {}
void HALSIM_SetEventName(const char* name) {}
void HALSIM_SetMatchType(HAL_MatchType type) {}
void HALSIM_SetMatchNumber(int32_t matchNumber) {}
void HALSIM_SetReplayNumber(int32_t replayNumber) {}
void HALSIM_RegisterDriverStationAllCallbacks(HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify) {}

View File

@@ -325,6 +325,109 @@ Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setDsAttached
HALSIM_SetDriverStationDsAttached(value);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: registerAllianceStationIdCallback
* Signature: (Ljava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_registerAllianceStationIdCallback
(JNIEnv* env, jclass, jobject callback, jboolean initialNotify)
{
return sim::AllocateCallbackNoIndex(
env, callback, initialNotify,
&HALSIM_RegisterDriverStationAllianceStationIdCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: cancelAllianceStationIdCallback
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_cancelAllianceStationIdCallback
(JNIEnv* env, jclass, jint handle)
{
return sim::FreeCallbackNoIndex(
env, handle, &HALSIM_CancelDriverStationAllianceStationIdCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: getAllianceStationId
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_getAllianceStationId
(JNIEnv*, jclass)
{
return HALSIM_GetDriverStationAllianceStationId();
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setAllianceStationId
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setAllianceStationId
(JNIEnv*, jclass, jint value)
{
HALSIM_SetDriverStationAllianceStationId(
static_cast<HAL_AllianceStationID>(value));
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: registerMatchTimeCallback
* Signature: (Ljava/lang/Object;Z)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_registerMatchTimeCallback
(JNIEnv* env, jclass, jobject callback, jboolean initialNotify)
{
return sim::AllocateCallbackNoIndex(
env, callback, initialNotify,
&HALSIM_RegisterDriverStationMatchTimeCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: cancelMatchTimeCallback
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_cancelMatchTimeCallback
(JNIEnv* env, jclass, jint handle)
{
return sim::FreeCallbackNoIndex(env, handle,
&HALSIM_CancelDriverStationMatchTimeCallback);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: getMatchTime
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_getMatchTime
(JNIEnv*, jclass)
{
return HALSIM_GetDriverStationMatchTime();
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setMatchTime
* Signature: (D)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setMatchTime
(JNIEnv*, jclass, jdouble value)
{
HALSIM_SetDriverStationMatchTime(value);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickAxes
@@ -393,6 +496,38 @@ Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickButtons
HALSIM_SetJoystickButtons(joystickNum, &joystickButtons);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: getJoystickOutputs
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_getJoystickOutputs
(JNIEnv* env, jclass, jint stick)
{
int64_t outputs = 0;
int32_t leftRumble;
int32_t rightRumble;
HALSIM_GetJoystickOutputs(stick, &outputs, &leftRumble, &rightRumble);
return outputs;
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: getJoystickRumble
* Signature: (II)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_getJoystickRumble
(JNIEnv* env, jclass, jint stick, jint rumbleNum)
{
int64_t outputs;
int32_t leftRumble = 0;
int32_t rightRumble = 0;
HALSIM_GetJoystickOutputs(stick, &outputs, &leftRumble, &rightRumble);
return rumbleNum == 0 ? leftRumble : rightRumble;
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setMatchInfo
@@ -483,6 +618,198 @@ Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setSendConsoleLine
}
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickButton
* Signature: (IIZ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickButton
(JNIEnv*, jclass, jint stick, jint button, jboolean state)
{
HALSIM_SetJoystickButton(stick, button, state);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickAxis
* Signature: (IID)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickAxis
(JNIEnv*, jclass, jint stick, jint axis, jdouble value)
{
HALSIM_SetJoystickAxis(stick, axis, value);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickPOV
* Signature: (III)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickPOV
(JNIEnv*, jclass, jint stick, jint pov, jint value)
{
HALSIM_SetJoystickPOV(stick, pov, value);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickButtonsValue
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickButtonsValue
(JNIEnv*, jclass, jint stick, jint buttons)
{
HALSIM_SetJoystickButtonsValue(stick, buttons);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickAxisCount
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickAxisCount
(JNIEnv*, jclass, jint stick, jint count)
{
HALSIM_SetJoystickAxisCount(stick, count);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickPOVCount
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickPOVCount
(JNIEnv*, jclass, jint stick, jint count)
{
HALSIM_SetJoystickPOVCount(stick, count);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickButtonCount
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickButtonCount
(JNIEnv*, jclass, jint stick, jint count)
{
HALSIM_SetJoystickButtonCount(stick, count);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickIsXbox
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickIsXbox
(JNIEnv*, jclass, jint stick, jboolean isXbox)
{
HALSIM_SetJoystickIsXbox(stick, isXbox);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickType
* Signature: (II)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickType
(JNIEnv*, jclass, jint stick, jint type)
{
HALSIM_SetJoystickType(stick, type);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickName
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickName
(JNIEnv* env, jclass, jint stick, jstring name)
{
HALSIM_SetJoystickName(stick, JStringRef{env, name}.c_str());
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setJoystickAxisType
* Signature: (III)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickAxisType
(JNIEnv*, jclass, jint stick, jint axis, jint type)
{
HALSIM_SetJoystickAxisType(stick, axis, type);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setGameSpecificMessage
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setGameSpecificMessage
(JNIEnv* env, jclass, jstring message)
{
HALSIM_SetGameSpecificMessage(JStringRef{env, message}.c_str());
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setEventName
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setEventName
(JNIEnv* env, jclass, jstring name)
{
HALSIM_SetEventName(JStringRef{env, name}.c_str());
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setMatchType
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setMatchType
(JNIEnv*, jclass, jint type)
{
HALSIM_SetMatchType(static_cast<HAL_MatchType>(static_cast<int>(type)));
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setMatchNumber
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setMatchNumber
(JNIEnv*, jclass, jint matchNumber)
{
HALSIM_SetMatchNumber(matchNumber);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: setReplayNumber
* Signature: (I)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setReplayNumber
(JNIEnv*, jclass, jint replayNumber)
{
HALSIM_SetReplayNumber(replayNumber);
}
/*
* Class: edu_wpi_first_hal_simulation_DriverStationDataJNI
* Method: resetData

View File

@@ -80,6 +80,25 @@ void HALSIM_GetJoystickOutputs(int32_t joystickNum, int64_t* outputs,
void HALSIM_SetMatchInfo(const HAL_MatchInfo* info);
void HALSIM_SetJoystickButton(int32_t stick, int32_t button, HAL_Bool state);
void HALSIM_SetJoystickAxis(int32_t stick, int32_t axis, double value);
void HALSIM_SetJoystickPOV(int32_t stick, int32_t pov, int32_t value);
void HALSIM_SetJoystickButtonsValue(int32_t stick, uint32_t buttons);
void HALSIM_SetJoystickAxisCount(int32_t stick, int32_t count);
void HALSIM_SetJoystickPOVCount(int32_t stick, int32_t count);
void HALSIM_SetJoystickButtonCount(int32_t stick, int32_t count);
void HALSIM_SetJoystickIsXbox(int32_t stick, HAL_Bool isXbox);
void HALSIM_SetJoystickType(int32_t stick, int32_t type);
void HALSIM_SetJoystickName(int32_t stick, const char* name);
void HALSIM_SetJoystickAxisType(int32_t stick, int32_t axis, int32_t type);
void HALSIM_SetGameSpecificMessage(const char* message);
void HALSIM_SetEventName(const char* name);
void HALSIM_SetMatchType(HAL_MatchType type);
void HALSIM_SetMatchNumber(int32_t matchNumber);
void HALSIM_SetReplayNumber(int32_t replayNumber);
void HALSIM_RegisterDriverStationAllCallbacks(HAL_NotifyCallback callback,
void* param,
HAL_Bool initialNotify);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
/* Copyright (c) 2017-2020 FIRST. 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. */
@@ -12,6 +12,8 @@
#include "DriverStationDataInternal.h"
#include "hal/DriverStation.h"
static constexpr int kNumJoysticks = 6;
namespace hal {
struct JoystickOutputStore {
int64_t outputs = 0;
@@ -47,13 +49,14 @@ void DriverStationData::ResetData() {
{
std::scoped_lock lock(m_joystickDataMutex);
m_joystickAxes = std::make_unique<HAL_JoystickAxes[]>(6);
m_joystickPOVs = std::make_unique<HAL_JoystickPOVs[]>(6);
m_joystickButtons = std::make_unique<HAL_JoystickButtons[]>(6);
m_joystickOutputs = std::make_unique<JoystickOutputStore[]>(6);
m_joystickDescriptor = std::make_unique<HAL_JoystickDescriptor[]>(6);
m_joystickAxes = std::make_unique<HAL_JoystickAxes[]>(kNumJoysticks);
m_joystickPOVs = std::make_unique<HAL_JoystickPOVs[]>(kNumJoysticks);
m_joystickButtons = std::make_unique<HAL_JoystickButtons[]>(kNumJoysticks);
m_joystickOutputs = std::make_unique<JoystickOutputStore[]>(kNumJoysticks);
m_joystickDescriptor =
std::make_unique<HAL_JoystickDescriptor[]>(kNumJoysticks);
for (int i = 0; i < 6; i++) {
for (int i = 0; i < kNumJoysticks; i++) {
m_joystickAxes[i].count = 0;
m_joystickPOVs[i].count = 0;
m_joystickButtons[i].count = 0;
@@ -71,21 +74,25 @@ void DriverStationData::ResetData() {
void DriverStationData::GetJoystickAxes(int32_t joystickNum,
HAL_JoystickAxes* axes) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
*axes = m_joystickAxes[joystickNum];
}
void DriverStationData::GetJoystickPOVs(int32_t joystickNum,
HAL_JoystickPOVs* povs) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
*povs = m_joystickPOVs[joystickNum];
}
void DriverStationData::GetJoystickButtons(int32_t joystickNum,
HAL_JoystickButtons* buttons) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
*buttons = m_joystickButtons[joystickNum];
}
void DriverStationData::GetJoystickDescriptor(
int32_t joystickNum, HAL_JoystickDescriptor* descriptor) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
*descriptor = m_joystickDescriptor[joystickNum];
// Always ensure name is null terminated
@@ -95,6 +102,7 @@ void DriverStationData::GetJoystickOutputs(int32_t joystickNum,
int64_t* outputs,
int32_t* leftRumble,
int32_t* rightRumble) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
*leftRumble = m_joystickOutputs[joystickNum].leftRumble;
*outputs = m_joystickOutputs[joystickNum].outputs;
@@ -107,22 +115,26 @@ void DriverStationData::GetMatchInfo(HAL_MatchInfo* info) {
void DriverStationData::SetJoystickAxes(int32_t joystickNum,
const HAL_JoystickAxes* axes) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickAxes[joystickNum] = *axes;
}
void DriverStationData::SetJoystickPOVs(int32_t joystickNum,
const HAL_JoystickPOVs* povs) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickPOVs[joystickNum] = *povs;
}
void DriverStationData::SetJoystickButtons(int32_t joystickNum,
const HAL_JoystickButtons* buttons) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickButtons[joystickNum] = *buttons;
}
void DriverStationData::SetJoystickDescriptor(
int32_t joystickNum, const HAL_JoystickDescriptor* descriptor) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickDescriptor[joystickNum] = *descriptor;
}
@@ -130,6 +142,7 @@ void DriverStationData::SetJoystickDescriptor(
void DriverStationData::SetJoystickOutputs(int32_t joystickNum, int64_t outputs,
int32_t leftRumble,
int32_t rightRumble) {
if (joystickNum < 0 || joystickNum >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickOutputs[joystickNum].leftRumble = leftRumble;
m_joystickOutputs[joystickNum].outputs = outputs;
@@ -144,6 +157,116 @@ void DriverStationData::SetMatchInfo(const HAL_MatchInfo* info) {
void DriverStationData::NotifyNewData() { HAL_ReleaseDSMutex(); }
void DriverStationData::SetJoystickButton(int32_t stick, int32_t button,
HAL_Bool state) {
if (stick < 0 || stick >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
if (state)
m_joystickButtons[stick].buttons |= 1 << (button - 1);
else
m_joystickButtons[stick].buttons &= ~(1 << (button - 1));
}
void DriverStationData::SetJoystickAxis(int32_t stick, int32_t axis,
double value) {
if (stick < 0 || stick >= kNumJoysticks) return;
if (axis < 0 || axis >= HAL_kMaxJoystickAxes) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickAxes[stick].axes[axis] = value;
}
void DriverStationData::SetJoystickPOV(int32_t stick, int32_t pov,
int32_t value) {
if (stick < 0 || stick >= kNumJoysticks) return;
if (pov < 0 || pov >= HAL_kMaxJoystickPOVs) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickPOVs[stick].povs[pov] = value;
}
void DriverStationData::SetJoystickButtons(int32_t stick, uint32_t buttons) {
if (stick < 0 || stick >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickButtons[stick].buttons = buttons;
}
void DriverStationData::SetJoystickAxisCount(int32_t stick, int32_t count) {
if (stick < 0 || stick >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickAxes[stick].count = count;
m_joystickDescriptor[stick].axisCount = count;
}
void DriverStationData::SetJoystickPOVCount(int32_t stick, int32_t count) {
if (stick < 0 || stick >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickPOVs[stick].count = count;
m_joystickDescriptor[stick].povCount = count;
}
void DriverStationData::SetJoystickButtonCount(int32_t stick, int32_t count) {
if (stick < 0 || stick >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickButtons[stick].count = count;
m_joystickDescriptor[stick].buttonCount = count;
}
void DriverStationData::SetJoystickIsXbox(int32_t stick, HAL_Bool isXbox) {
if (stick < 0 || stick >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickDescriptor[stick].isXbox = isXbox;
}
void DriverStationData::SetJoystickType(int32_t stick, int32_t type) {
if (stick < 0 || stick >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickDescriptor[stick].type = type;
}
void DriverStationData::SetJoystickName(int32_t stick, const char* name) {
if (stick < 0 || stick >= kNumJoysticks) return;
std::scoped_lock lock(m_joystickDataMutex);
std::strncpy(m_joystickDescriptor[stick].name, name,
sizeof(m_joystickDescriptor[stick].name) - 1);
}
void DriverStationData::SetJoystickAxisType(int32_t stick, int32_t axis,
int32_t type) {
if (stick < 0 || stick >= kNumJoysticks) return;
if (axis < 0 || axis >= HAL_kMaxJoystickAxes) return;
std::scoped_lock lock(m_joystickDataMutex);
m_joystickDescriptor[stick].axisTypes[axis] = type;
}
void DriverStationData::SetGameSpecificMessage(const char* message) {
std::scoped_lock lock(m_matchInfoMutex);
std::strncpy(reinterpret_cast<char*>(m_matchInfo->gameSpecificMessage),
message, sizeof(m_matchInfo->gameSpecificMessage) - 1);
*(std::end(m_matchInfo->gameSpecificMessage) - 1) = '\0';
m_matchInfo->gameSpecificMessageSize = std::strlen(message);
}
void DriverStationData::SetEventName(const char* name) {
std::scoped_lock lock(m_matchInfoMutex);
std::strncpy(m_matchInfo->eventName, name,
sizeof(m_matchInfo->eventName) - 1);
*(std::end(m_matchInfo->eventName) - 1) = '\0';
}
void DriverStationData::SetMatchType(HAL_MatchType type) {
std::scoped_lock lock(m_matchInfoMutex);
m_matchInfo->matchType = type;
}
void DriverStationData::SetMatchNumber(int32_t matchNumber) {
std::scoped_lock lock(m_matchInfoMutex);
m_matchInfo->matchNumber = matchNumber;
}
void DriverStationData::SetReplayNumber(int32_t replayNumber) {
std::scoped_lock lock(m_matchInfoMutex);
m_matchInfo->replayNumber = replayNumber;
}
extern "C" {
void HALSIM_ResetDriverStationData(void) { SimDriverStationData->ResetData(); }
@@ -191,6 +314,70 @@ void HALSIM_NotifyDriverStationNewData(void) {
SimDriverStationData->NotifyNewData();
}
void HALSIM_SetJoystickButton(int32_t stick, int32_t button, HAL_Bool state) {
SimDriverStationData->SetJoystickButton(stick, button, state);
}
void HALSIM_SetJoystickAxis(int32_t stick, int32_t axis, double value) {
SimDriverStationData->SetJoystickAxis(stick, axis, value);
}
void HALSIM_SetJoystickPOV(int32_t stick, int32_t pov, int32_t value) {
SimDriverStationData->SetJoystickPOV(stick, pov, value);
}
void HALSIM_SetJoystickButtonsValue(int32_t stick, uint32_t buttons) {
SimDriverStationData->SetJoystickButtons(stick, buttons);
}
void HALSIM_SetJoystickAxisCount(int32_t stick, int32_t count) {
SimDriverStationData->SetJoystickAxisCount(stick, count);
}
void HALSIM_SetJoystickPOVCount(int32_t stick, int32_t count) {
SimDriverStationData->SetJoystickPOVCount(stick, count);
}
void HALSIM_SetJoystickButtonCount(int32_t stick, int32_t count) {
SimDriverStationData->SetJoystickButtonCount(stick, count);
}
void HALSIM_SetJoystickIsXbox(int32_t stick, HAL_Bool isXbox) {
SimDriverStationData->SetJoystickIsXbox(stick, isXbox);
}
void HALSIM_SetJoystickType(int32_t stick, int32_t type) {
SimDriverStationData->SetJoystickType(stick, type);
}
void HALSIM_SetJoystickName(int32_t stick, const char* name) {
SimDriverStationData->SetJoystickName(stick, name);
}
void HALSIM_SetJoystickAxisType(int32_t stick, int32_t axis, int32_t type) {
SimDriverStationData->SetJoystickAxisType(stick, axis, type);
}
void HALSIM_SetGameSpecificMessage(const char* message) {
SimDriverStationData->SetGameSpecificMessage(message);
}
void HALSIM_SetEventName(const char* name) {
SimDriverStationData->SetEventName(name);
}
void HALSIM_SetMatchType(HAL_MatchType type) {
SimDriverStationData->SetMatchType(type);
}
void HALSIM_SetMatchNumber(int32_t matchNumber) {
SimDriverStationData->SetMatchNumber(matchNumber);
}
void HALSIM_SetReplayNumber(int32_t replayNumber) {
SimDriverStationData->SetReplayNumber(replayNumber);
}
#define REGISTER(NAME) \
SimDriverStationData->NAME.RegisterCallback(callback, param, initialNotify)

View File

@@ -58,6 +58,25 @@ class DriverStationData {
void NotifyNewData();
void SetJoystickButton(int32_t stick, int32_t button, HAL_Bool state);
void SetJoystickAxis(int32_t stick, int32_t axis, double value);
void SetJoystickPOV(int32_t stick, int32_t pov, int32_t value);
void SetJoystickButtons(int32_t stick, uint32_t buttons);
void SetJoystickAxisCount(int32_t stick, int32_t count);
void SetJoystickPOVCount(int32_t stick, int32_t count);
void SetJoystickButtonCount(int32_t stick, int32_t count);
void SetJoystickIsXbox(int32_t stick, HAL_Bool isXbox);
void SetJoystickType(int32_t stick, int32_t type);
void SetJoystickName(int32_t stick, const char* name);
void SetJoystickAxisType(int32_t stick, int32_t axis, int32_t type);
void SetGameSpecificMessage(const char* message);
void SetEventName(const char* name);
void SetMatchType(HAL_MatchType type);
void SetMatchNumber(int32_t matchNumber);
void SetReplayNumber(int32_t replayNumber);
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetEnabledName> enabled{false};
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetAutonomousName> autonomous{false};
SimDataValue<HAL_Bool, HAL_MakeBoolean, GetTestName> test{false};

View File

@@ -11,8 +11,10 @@
#include <utility>
#include <hal/simulation/DriverStationData.h>
#include <hal/simulation/MockHooks.h>
#include "CallbackStore.h"
#include "frc/DriverStation.h"
namespace frc {
namespace sim {
@@ -108,7 +110,261 @@ class DriverStationSim {
HALSIM_SetDriverStationDsAttached(dsAttached);
}
static void NotifyNewData() { HALSIM_NotifyDriverStationNewData(); }
static std::unique_ptr<CallbackStore> RegisterAllianceStationIdCallback(
NotifyCallback callback, bool initialNotify) {
auto store = std::make_unique<CallbackStore>(
-1, callback, &HALSIM_CancelDriverStationAllianceStationIdCallback);
store->SetUid(HALSIM_RegisterDriverStationAllianceStationIdCallback(
&CallbackStoreThunk, store.get(), initialNotify));
return store;
}
static HAL_AllianceStationID GetAllianceStationId() {
return HALSIM_GetDriverStationAllianceStationId();
}
static void SetAllianceStationId(HAL_AllianceStationID allianceStationId) {
HALSIM_SetDriverStationAllianceStationId(allianceStationId);
}
static std::unique_ptr<CallbackStore> RegisterMatchTimeCallback(
NotifyCallback callback, bool initialNotify) {
auto store = std::make_unique<CallbackStore>(
-1, callback, &HALSIM_CancelDriverStationMatchTimeCallback);
store->SetUid(HALSIM_RegisterDriverStationMatchTimeCallback(
&CallbackStoreThunk, store.get(), initialNotify));
return store;
}
static double GetMatchTime() { return HALSIM_GetDriverStationMatchTime(); }
static void SetMatchTime(double matchTime) {
HALSIM_SetDriverStationMatchTime(matchTime);
}
/**
* Updates DriverStation data so that new values are visible to the user
* program.
*/
static void NotifyNewData() {
HALSIM_NotifyDriverStationNewData();
DriverStation::GetInstance().WaitForData();
}
/**
* Sets suppression of DriverStation::ReportError and ReportWarning messages.
*
* @param shouldSend If false then messages will be suppressed.
*/
static void SetSendError(bool shouldSend) {
if (shouldSend) {
HALSIM_SetSendError(nullptr);
} else {
HALSIM_SetSendError([](HAL_Bool isError, int32_t errorCode,
HAL_Bool isLVCode, const char* details,
const char* location, const char* callStack,
HAL_Bool printMsg) { return 0; });
}
}
/**
* Sets suppression of DriverStation::SendConsoleLine messages.
*
* @param shouldSend If false then messages will be suppressed.
*/
static void SetSendConsoleLine(bool shouldSend) {
if (shouldSend) {
HALSIM_SetSendConsoleLine(nullptr);
} else {
HALSIM_SetSendConsoleLine([](const char* line) { return 0; });
}
}
/**
* Gets the joystick outputs.
*
* @param stick The joystick number
* @return The joystick outputs
*/
static int64_t GetJoystickOutputs(int stick) {
int64_t outputs = 0;
int32_t leftRumble;
int32_t rightRumble;
HALSIM_GetJoystickOutputs(stick, &outputs, &leftRumble, &rightRumble);
return outputs;
}
/**
* Gets the joystick rumble.
*
* @param stick The joystick number
* @param rumbleNum Rumble to get (0=left, 1=right)
* @return The joystick rumble value
*/
static int GetJoystickRumble(int stick, int rumbleNum) {
int64_t outputs;
int32_t leftRumble = 0;
int32_t rightRumble = 0;
HALSIM_GetJoystickOutputs(stick, &outputs, &leftRumble, &rightRumble);
return rumbleNum == 0 ? leftRumble : rightRumble;
}
/**
* Sets the state of one joystick button. Button indexes begin at 1.
*
* @param stick The joystick number
* @param button The button index, beginning at 1
* @param state The state of the joystick button
*/
static void SetJoystickButton(int stick, int button, bool state) {
HALSIM_SetJoystickButton(stick, button, state);
}
/**
* Gets the value of the axis on a joystick.
*
* @param stick The joystick number
* @param axis The analog axis number
* @param value The value of the axis on the joystick
*/
static void SetJoystickAxis(int stick, int axis, double value) {
HALSIM_SetJoystickAxis(stick, axis, value);
}
/**
* Gets the state of a POV on a joystick.
*
* @param stick The joystick number
* @param pov The POV number
* @param value the angle of the POV in degrees, or -1 for not pressed
*/
static void SetJoystickPOV(int stick, int pov, int value) {
HALSIM_SetJoystickPOV(stick, pov, value);
}
/**
* Sets the state of all the buttons on a joystick.
*
* @param stick The joystick number
* @param buttons The bitmap state of the buttons on the joystick
*/
static void SetJoystickButtons(int stick, uint32_t buttons) {
HALSIM_SetJoystickButtonsValue(stick, buttons);
}
/**
* Sets the number of axes for a joystick.
*
* @param stick The joystick number
* @param count The number of axes on the indicated joystick
*/
static void SetJoystickAxisCount(int stick, int count) {
HALSIM_SetJoystickAxisCount(stick, count);
}
/**
* Sets the number of POVs for a joystick.
*
* @param stick The joystick number
* @param count The number of POVs on the indicated joystick
*/
static void SetJoystickPOVCount(int stick, int count) {
HALSIM_SetJoystickPOVCount(stick, count);
}
/**
* Sets the number of buttons for a joystick.
*
* @param stick The joystick number
* @param count The number of buttons on the indicated joystick
*/
static void SetJoystickButtonCount(int stick, int count) {
HALSIM_SetJoystickButtonCount(stick, count);
}
/**
* Sets the value of isXbox for a joystick.
*
* @param stick The joystick number
* @param isXbox The value of isXbox
*/
static void SetJoystickIsXbox(int stick, bool isXbox) {
HALSIM_SetJoystickIsXbox(stick, isXbox);
}
/**
* Sets the value of type for a joystick.
*
* @param stick The joystick number
* @param type The value of type
*/
static void SetJoystickType(int stick, int type) {
HALSIM_SetJoystickType(stick, type);
}
/**
* Sets the name of a joystick.
*
* @param stick The joystick number
* @param name The value of name
*/
static void SetJoystickName(int stick, const char* name) {
HALSIM_SetJoystickName(stick, name);
}
/**
* Sets the types of Axes for a joystick.
*
* @param stick The joystick number
* @param axis The target axis
* @param type The type of axis
*/
static void SetJoystickAxisType(int stick, int axis, int type) {
HALSIM_SetJoystickAxisType(stick, axis, type);
}
/**
* Sets the game specific message.
*
* @param message the game specific message
*/
static void SetGameSpecificMessage(const char* message) {
HALSIM_SetGameSpecificMessage(message);
}
/**
* Sets the event name.
*
* @param name the event name
*/
static void SetEventName(const char* name) { HALSIM_SetEventName(name); }
/**
* Sets the match type.
*
* @param type the match type
*/
static void SetMatchType(DriverStation::MatchType type) {
HALSIM_SetMatchType(static_cast<HAL_MatchType>(static_cast<int>(type)));
}
/**
* Sets the match number.
*
* @param matchNumber the match number
*/
static void SetMatchNumber(int matchNumber) {
HALSIM_SetMatchNumber(matchNumber);
}
/**
* Sets the replay number.
*
* @param replayNumber the replay number
*/
static void SetReplayNumber(int replayNumber) {
HALSIM_SetReplayNumber(replayNumber);
}
static void ResetData() { HALSIM_ResetDriverStationData(); }
};

View File

@@ -0,0 +1,97 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/GenericHID.h"
#include "frc/simulation/DriverStationSim.h"
namespace frc {
namespace sim {
/**
* Class to control a simulated generic joystick.
*/
class GenericHIDSim {
public:
/**
* Constructs from a GenericHID object.
*
* @param joystick joystick to simulate
*/
explicit GenericHIDSim(const GenericHID& joystick)
: m_port{joystick.GetPort()} {}
/**
* Constructs from a joystick port number.
*
* @param port port number
*/
explicit GenericHIDSim(int port) : m_port{port} {}
/**
* Updates joystick data so that new values are visible to the user program.
*/
void NotifyNewData() { DriverStationSim::NotifyNewData(); }
void SetRawButton(int button, bool value) {
DriverStationSim::SetJoystickButton(m_port, button, value);
}
void SetRawAxis(int axis, double value) {
DriverStationSim::SetJoystickAxis(m_port, axis, value);
}
void SetPOV(int pov, int value) {
DriverStationSim::SetJoystickPOV(m_port, pov, value);
}
void SetPOV(int value) { SetPOV(0, value); }
void SetAxisCount(int count) {
DriverStationSim::SetJoystickAxisCount(m_port, count);
}
void SetPOVCount(int count) {
DriverStationSim::SetJoystickPOVCount(m_port, count);
}
void SetButtonCount(int count) {
DriverStationSim::SetJoystickButtonCount(m_port, count);
}
void SetType(GenericHID::HIDType type) {
DriverStationSim::SetJoystickType(m_port, type);
}
void SetName(const char* name) {
DriverStationSim::SetJoystickName(m_port, name);
}
void SetAxisType(int axis, int type) {
DriverStationSim::SetJoystickAxisType(m_port, axis, type);
}
bool GetOutput(int outputNumber) {
int64_t outputs = GetOutputs();
return (outputs & (static_cast<int64_t>(1) << (outputNumber - 1))) != 0;
}
int64_t GetOutputs() { return DriverStationSim::GetJoystickOutputs(m_port); }
double GetRumble(GenericHID::RumbleType type) {
int value = DriverStationSim::GetJoystickRumble(
m_port, type == GenericHID::kLeftRumble ? 0 : 1);
return value / 65535.0;
}
protected:
int m_port;
};
} // namespace sim
} // namespace frc

View File

@@ -0,0 +1,85 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/Joystick.h"
#include "frc/simulation/GenericHIDSim.h"
namespace frc {
namespace sim {
/**
* Class to control a simulated joystick.
*/
class JoystickSim : public GenericHIDSim {
public:
/**
* Constructs from a Joystick object.
*
* @param joystick joystick to simulate
*/
explicit JoystickSim(const Joystick& joystick)
: GenericHIDSim{joystick}, m_joystick{&joystick} {
// default to a reasonable joystick configuration
SetAxisCount(5);
SetButtonCount(12);
SetPOVCount(1);
}
/**
* Constructs from a joystick port number.
*
* @param port port number
*/
explicit JoystickSim(int port) : GenericHIDSim{port} {
// default to a reasonable joystick configuration
SetAxisCount(5);
SetButtonCount(12);
SetPOVCount(1);
}
void SetX(double value) {
SetRawAxis(
m_joystick ? m_joystick->GetXChannel() : Joystick::kDefaultXChannel,
value);
}
void SetY(double value) {
SetRawAxis(
m_joystick ? m_joystick->GetYChannel() : Joystick::kDefaultYChannel,
value);
}
void SetZ(double value) {
SetRawAxis(
m_joystick ? m_joystick->GetZChannel() : Joystick::kDefaultZChannel,
value);
}
void SetTwist(double value) {
SetRawAxis(m_joystick ? m_joystick->GetTwistChannel()
: Joystick::kDefaultTwistChannel,
value);
}
void SetThrottle(double value) {
SetRawAxis(m_joystick ? m_joystick->GetThrottleChannel()
: Joystick::kDefaultThrottleChannel,
value);
}
void SetTrigger(bool state) { SetRawButton(1, state); }
void SetTop(bool state) { SetRawButton(2, state); }
private:
const Joystick* m_joystick = nullptr;
};
} // namespace sim
} // namespace frc

View File

@@ -0,0 +1,111 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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. */
/*----------------------------------------------------------------------------*/
#pragma once
#include "frc/XboxController.h"
#include "frc/simulation/GenericHIDSim.h"
namespace frc {
namespace sim {
/**
* Class to control a simulated Xbox 360 or Xbox One controller.
*/
class XboxControllerSim : public GenericHIDSim {
public:
/**
* Constructs from a XboxController object.
*
* @param joystick controller to simulate
*/
explicit XboxControllerSim(const XboxController& joystick)
: GenericHIDSim{joystick} {
SetAxisCount(6);
SetButtonCount(10);
}
/**
* Constructs from a joystick port number.
*
* @param port port number
*/
explicit XboxControllerSim(int port) : GenericHIDSim{port} {
SetAxisCount(6);
SetButtonCount(10);
}
void SetX(GenericHID::JoystickHand hand, double value) {
if (hand == GenericHID::kLeftHand) {
SetRawAxis(static_cast<int>(XboxController::Axis::kLeftX), value);
} else {
SetRawAxis(static_cast<int>(XboxController::Axis::kRightX), value);
}
}
void SetY(GenericHID::JoystickHand hand, double value) {
if (hand == GenericHID::kLeftHand) {
SetRawAxis(static_cast<int>(XboxController::Axis::kLeftY), value);
} else {
SetRawAxis(static_cast<int>(XboxController::Axis::kRightY), value);
}
}
void SetTriggerAxis(GenericHID::JoystickHand hand, double value) {
if (hand == GenericHID::kLeftHand) {
SetRawAxis(static_cast<int>(XboxController::Axis::kLeftTrigger), value);
} else {
SetRawAxis(static_cast<int>(XboxController::Axis::kRightTrigger), value);
}
}
void SetBumper(GenericHID::JoystickHand hand, bool state) {
if (hand == GenericHID::kLeftHand) {
SetRawButton(static_cast<int>(XboxController::Button::kBumperLeft),
state);
} else {
SetRawButton(static_cast<int>(XboxController::Button::kBumperRight),
state);
}
}
void SetStickButton(GenericHID::JoystickHand hand, bool state) {
if (hand == GenericHID::kLeftHand) {
SetRawButton(static_cast<int>(XboxController::Button::kStickLeft), state);
} else {
SetRawButton(static_cast<int>(XboxController::Button::kStickRight),
state);
}
}
void SetAButton(bool state) {
SetRawButton(static_cast<int>(XboxController::Button::kA), state);
}
void SetBButton(bool state) {
SetRawButton(static_cast<int>(XboxController::Button::kB), state);
}
void SetXButton(bool state) {
SetRawButton(static_cast<int>(XboxController::Button::kX), state);
}
void SetYButton(bool state) {
SetRawButton(static_cast<int>(XboxController::Button::kY), state);
}
void SetBackButton(bool state) {
SetRawButton(static_cast<int>(XboxController::Button::kBack), state);
}
void SetStartButton(bool state) {
SetRawButton(static_cast<int>(XboxController::Button::kStart), state);
}
};
} // namespace sim
} // namespace frc

View File

@@ -0,0 +1,39 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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 "frc/Joystick.h" // NOLINT(build/include_order)
#include "frc/simulation/JoystickSim.h"
#include "gtest/gtest.h"
using namespace frc;
TEST(JoystickTests, GetX) {
Joystick joy{1};
sim::JoystickSim joysim{joy};
joysim.SetX(0.25);
joysim.NotifyNewData();
ASSERT_NEAR(joy.GetX(), 0.25, 0.001);
joysim.SetX(0);
joysim.NotifyNewData();
ASSERT_NEAR(joy.GetX(), 0, 0.001);
}
TEST(JoystickTests, GetY) {
Joystick joy{1};
sim::JoystickSim joysim{joy};
joysim.SetY(0.25);
joysim.NotifyNewData();
ASSERT_NEAR(joy.GetY(), 0.25, 0.001);
joysim.SetY(0);
joysim.NotifyNewData();
ASSERT_NEAR(joy.GetY(), 0, 0.001);
}

View File

@@ -0,0 +1,74 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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 "frc/XboxController.h" // NOLINT(build/include_order)
#include "frc/simulation/XboxControllerSim.h"
#include "gtest/gtest.h"
using namespace frc;
TEST(XboxControllerTests, GetX) {
XboxController joy{2};
sim::XboxControllerSim joysim{joy};
joysim.SetX(XboxController::kLeftHand, 0.35);
joysim.SetX(XboxController::kRightHand, 0.45);
joysim.NotifyNewData();
ASSERT_NEAR(joy.GetX(XboxController::kLeftHand), 0.35, 0.001);
ASSERT_NEAR(joy.GetX(XboxController::kRightHand), 0.45, 0.001);
}
TEST(XboxControllerTests, GetBumper) {
XboxController joy{1};
sim::XboxControllerSim joysim{joy};
joysim.SetBumper(XboxController::kLeftHand, false);
joysim.SetBumper(XboxController::kRightHand, true);
joysim.NotifyNewData();
ASSERT_FALSE(joy.GetBumper(XboxController::kLeftHand));
ASSERT_TRUE(joy.GetBumper(XboxController::kRightHand));
// need to call pressed and released to clear flags
joy.GetBumperPressed(XboxController::kLeftHand);
joy.GetBumperReleased(XboxController::kLeftHand);
joy.GetBumperPressed(XboxController::kRightHand);
joy.GetBumperReleased(XboxController::kRightHand);
joysim.SetBumper(XboxController::kLeftHand, true);
joysim.SetBumper(XboxController::kRightHand, false);
joysim.NotifyNewData();
ASSERT_TRUE(joy.GetBumper(XboxController::kLeftHand));
ASSERT_TRUE(joy.GetBumperPressed(XboxController::kLeftHand));
ASSERT_FALSE(joy.GetBumperReleased(XboxController::kLeftHand));
ASSERT_FALSE(joy.GetBumper(XboxController::kRightHand));
ASSERT_FALSE(joy.GetBumperPressed(XboxController::kRightHand));
ASSERT_TRUE(joy.GetBumperReleased(XboxController::kRightHand));
}
TEST(XboxControllerTests, GetAButton) {
XboxController joy{1};
sim::XboxControllerSim joysim{joy};
joysim.SetAButton(false);
joysim.NotifyNewData();
ASSERT_FALSE(joy.GetAButton());
// need to call pressed and released to clear flags
joy.GetAButtonPressed();
joy.GetAButtonReleased();
joysim.SetAButton(true);
joysim.NotifyNewData();
ASSERT_TRUE(joy.GetAButton());
ASSERT_TRUE(joy.GetAButtonPressed());
ASSERT_FALSE(joy.GetAButtonReleased());
joysim.SetAButton(false);
joysim.NotifyNewData();
ASSERT_FALSE(joy.GetAButton());
ASSERT_FALSE(joy.GetAButtonPressed());
ASSERT_TRUE(joy.GetAButtonReleased());
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */
/* Copyright (c) 2008-2020 FIRST. 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. */
@@ -18,11 +18,11 @@ import edu.wpi.first.hal.HAL;
* and the mapping of ports to hardware buttons depends on the code in the Driver Station.
*/
public class Joystick extends GenericHID {
static final byte kDefaultXChannel = 0;
static final byte kDefaultYChannel = 1;
static final byte kDefaultZChannel = 2;
static final byte kDefaultTwistChannel = 2;
static final byte kDefaultThrottleChannel = 3;
public static final byte kDefaultXChannel = 0;
public static final byte kDefaultYChannel = 1;
public static final byte kDefaultZChannel = 2;
public static final byte kDefaultTwistChannel = 2;
public static final byte kDefaultThrottleChannel = 3;
/**
* Represents an analog axis on a joystick.

View File

@@ -7,13 +7,15 @@
package edu.wpi.first.wpilibj.simulation;
import edu.wpi.first.hal.AllianceStationID;
import edu.wpi.first.hal.simulation.DriverStationDataJNI;
import edu.wpi.first.hal.simulation.NotifyCallback;
import edu.wpi.first.wpilibj.DriverStation;
/**
* Class to control a simulated driver station.
*/
@SuppressWarnings("PMD.UseUtilityClass")
@SuppressWarnings({"PMD.UseUtilityClass", "PMD.GodClass", "PMD.ExcessivePublicCount"})
public class DriverStationSim {
public static CallbackStore registerEnabledCallback(NotifyCallback callback, boolean initialNotify) {
int uid = DriverStationDataJNI.registerEnabledCallback(callback, initialNotify);
@@ -80,19 +82,291 @@ public class DriverStationSim {
public static void setDsAttached(boolean dsAttached) {
DriverStationDataJNI.setDsAttached(dsAttached);
}
public static void notifyNewData() {
DriverStationDataJNI.notifyNewData();
public static CallbackStore registerAllianceStationIdCallback(NotifyCallback callback, boolean initialNotify) {
int uid = DriverStationDataJNI.registerAllianceStationIdCallback(callback, initialNotify);
return new CallbackStore(uid, DriverStationDataJNI::cancelAllianceStationIdCallback);
}
public static AllianceStationID getAllianceStationId() {
switch (DriverStationDataJNI.getAllianceStationId()) {
case 0:
return AllianceStationID.Red1;
case 1:
return AllianceStationID.Red2;
case 2:
return AllianceStationID.Red3;
case 3:
return AllianceStationID.Blue1;
case 4:
return AllianceStationID.Blue2;
case 5:
return AllianceStationID.Blue3;
default:
return null;
}
}
public static void setAllianceStationId(AllianceStationID allianceStationId) {
int allianceStation;
switch (allianceStationId) {
case Red1:
allianceStation = 0;
break;
case Red2:
allianceStation = 1;
break;
case Red3:
allianceStation = 2;
break;
case Blue1:
allianceStation = 3;
break;
case Blue2:
allianceStation = 4;
break;
case Blue3:
allianceStation = 5;
break;
default:
return;
}
DriverStationDataJNI.setAllianceStationId(allianceStation);
}
public static CallbackStore registerMatchTimeCallback(NotifyCallback callback, boolean initialNotify) {
int uid = DriverStationDataJNI.registerMatchTimeCallback(callback, initialNotify);
return new CallbackStore(uid, DriverStationDataJNI::cancelMatchTimeCallback);
}
public static double getMatchTime() {
return DriverStationDataJNI.getMatchTime();
}
public static void setMatchTime(double matchTime) {
DriverStationDataJNI.setMatchTime(matchTime);
}
/**
* Toggles suppression of DriverStation.reportError and reportWarning messages.
* Updates DriverStation data so that new values are visible to the user
* program.
*/
public static void notifyNewData() {
DriverStationDataJNI.notifyNewData();
DriverStation.getInstance().waitForData();
}
/**
* Sets suppression of DriverStation.reportError and reportWarning messages.
*
* @param shouldSend If false then messages will will be suppressed.
* @param shouldSend If false then messages will be suppressed.
*/
public static void setSendError(boolean shouldSend) {
DriverStationDataJNI.setSendError(shouldSend);
}
/**
* Sets suppression of DriverStation.sendConsoleLine messages.
*
* @param shouldSend If false then messages will be suppressed.
*/
public static void setSendConsoleLine(boolean shouldSend) {
DriverStationDataJNI.setSendConsoleLine(shouldSend);
}
/**
* Gets the joystick outputs.
*
* @param stick The joystick number
* @return The joystick outputs
*/
public static long getJoystickOutputs(int stick) {
return DriverStationDataJNI.getJoystickOutputs(stick);
}
/**
* Gets the joystick rumble.
*
* @param stick The joystick number
* @param rumbleNum Rumble to get (0=left, 1=right)
* @return The joystick rumble value
*/
public static int getJoystickRumble(int stick, int rumbleNum) {
return DriverStationDataJNI.getJoystickRumble(stick, rumbleNum);
}
/**
* Sets the state of one joystick button. Button indexes begin at 1.
*
* @param stick The joystick number
* @param button The button index, beginning at 1
* @param state The state of the joystick button
*/
public static void setJoystickButton(int stick, int button, boolean state) {
DriverStationDataJNI.setJoystickButton(stick, button, state);
}
/**
* Gets the value of the axis on a joystick.
*
* @param stick The joystick number
* @param axis The analog axis number
* @param value The value of the axis on the joystick
*/
public static void setJoystickAxis(int stick, int axis, double value) {
DriverStationDataJNI.setJoystickAxis(stick, axis, value);
}
/**
* Gets the state of a POV on a joystick.
*
* @param stick The joystick number
* @param pov The POV number
* @param value the angle of the POV in degrees, or -1 for not pressed
*/
public static void setJoystickPOV(int stick, int pov, int value) {
DriverStationDataJNI.setJoystickPOV(stick, pov, value);
}
/**
* Sets the state of all the buttons on a joystick.
*
* @param stick The joystick number
* @param buttons The bitmap state of the buttons on the joystick
*/
public static void setJoystickButtons(int stick, int buttons) {
DriverStationDataJNI.setJoystickButtonsValue(stick, buttons);
}
/**
* Sets the number of axes for a joystick.
*
* @param stick The joystick number
* @param count The number of axes on the indicated joystick
*/
public static void setJoystickAxisCount(int stick, int count) {
DriverStationDataJNI.setJoystickAxisCount(stick, count);
}
/**
* Sets the number of POVs for a joystick.
*
* @param stick The joystick number
* @param count The number of POVs on the indicated joystick
*/
public static void setJoystickPOVCount(int stick, int count) {
DriverStationDataJNI.setJoystickPOVCount(stick, count);
}
/**
* Sets the number of buttons for a joystick.
*
* @param stick The joystick number
* @param count The number of buttons on the indicated joystick
*/
public static void setJoystickButtonCount(int stick, int count) {
DriverStationDataJNI.setJoystickButtonCount(stick, count);
}
/**
* Sets the value of isXbox for a joystick.
*
* @param stick The joystick number
* @param isXbox The value of isXbox
*/
public static void setJoystickIsXbox(int stick, boolean isXbox) {
DriverStationDataJNI.setJoystickIsXbox(stick, isXbox);
}
/**
* Sets the value of type for a joystick.
*
* @param stick The joystick number
* @param type The value of type
*/
public static void setJoystickType(int stick, int type) {
DriverStationDataJNI.setJoystickType(stick, type);
}
/**
* Sets the name of a joystick.
*
* @param stick The joystick number
* @param name The value of name
*/
public static void setJoystickName(int stick, String name) {
DriverStationDataJNI.setJoystickName(stick, name);
}
/**
* Sets the types of Axes for a joystick.
*
* @param stick The joystick number
* @param axis The target axis
* @param type The type of axis
*/
public static void setJoystickAxisType(int stick, int axis, int type) {
DriverStationDataJNI.setJoystickAxisType(stick, axis, type);
}
/**
* Sets the game specific message.
*
* @param message the game specific message
*/
public static void setGameSpecificMessage(String message) {
DriverStationDataJNI.setGameSpecificMessage(message);
}
/**
* Sets the event name.
*
* @param name the event name
*/
public static void setEventName(String name) {
DriverStationDataJNI.setEventName(name);
}
/**
* Sets the match type.
*
* @param type the match type
*/
public static void setMatchType(DriverStation.MatchType type) {
int matchType;
switch (type) {
case Practice:
matchType = 1;
break;
case Qualification:
matchType = 2;
break;
case Elimination:
matchType = 3;
break;
case None:
matchType = 0;
break;
default:
return;
}
DriverStationDataJNI.setMatchType(matchType);
}
/**
* Sets the match number.
*
* @param matchNumber the match number
*/
public static void setMatchNumber(int matchNumber) {
DriverStationDataJNI.setMatchNumber(matchNumber);
}
/**
* Sets the replay number.
*
* @param replayNumber the replay number
*/
public static void setReplayNumber(int replayNumber) {
DriverStationDataJNI.setReplayNumber(replayNumber);
}
public static void resetData() {
DriverStationDataJNI.resetData();
}

View File

@@ -0,0 +1,97 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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.simulation;
import edu.wpi.first.wpilibj.GenericHID;
/**
* Class to control a simulated generic joystick.
*/
public class GenericHIDSim {
protected final int m_port;
/**
* Constructs from a GenericHID object.
*
* @param joystick joystick to simulate
*/
public GenericHIDSim(GenericHID joystick) {
m_port = joystick.getPort();
}
/**
* Constructs from a joystick port number.
*
* @param port port number
*/
public GenericHIDSim(int port) {
m_port = port;
}
/**
* Updates joystick data so that new values are visible to the user program.
*/
public void notifyNewData() {
DriverStationSim.notifyNewData();
}
public void setRawButton(int button, boolean value) {
DriverStationSim.setJoystickButton(m_port, button, value);
}
public void setRawAxis(int axis, double value) {
DriverStationSim.setJoystickAxis(m_port, axis, value);
}
public void setPOV(int pov, int value) {
DriverStationSim.setJoystickPOV(m_port, pov, value);
}
public void setPOV(int value) {
setPOV(0, value);
}
public void setAxisCount(int count) {
DriverStationSim.setJoystickAxisCount(m_port, count);
}
public void setPOVCount(int count) {
DriverStationSim.setJoystickPOVCount(m_port, count);
}
public void setButtonCount(int count) {
DriverStationSim.setJoystickButtonCount(m_port, count);
}
public void setType(GenericHID.HIDType type) {
DriverStationSim.setJoystickType(m_port, type.value);
}
public void setName(String name) {
DriverStationSim.setJoystickName(m_port, name);
}
public void setAxisType(int axis, int type) {
DriverStationSim.setJoystickAxisType(m_port, axis, type);
}
public boolean getOutput(int outputNumber) {
long outputs = getOutputs();
return (outputs & (1 << (outputNumber - 1))) != 0;
}
public long getOutputs() {
return DriverStationSim.getJoystickOutputs(m_port);
}
public double getRumble(GenericHID.RumbleType type) {
int value = DriverStationSim.getJoystickRumble(
m_port, type == GenericHID.RumbleType.kLeftRumble ? 0 : 1);
return value / 65535.0;
}
}

View File

@@ -0,0 +1,76 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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.simulation;
import edu.wpi.first.wpilibj.Joystick;
/**
* Class to control a simulated joystick.
*/
public class JoystickSim extends GenericHIDSim {
private Joystick m_joystick;
/**
* Constructs from a Joystick object.
*
* @param joystick joystick to simulate
*/
public JoystickSim(Joystick joystick) {
super(joystick);
m_joystick = joystick;
// default to a reasonable joystick configuration
setAxisCount(5);
setButtonCount(12);
setPOVCount(1);
}
/**
* Constructs from a joystick port number.
*
* @param port port number
*/
public JoystickSim(int port) {
super(port);
// default to a reasonable joystick configuration
setAxisCount(5);
setButtonCount(12);
setPOVCount(1);
}
public void setX(double value) {
setRawAxis(m_joystick != null ? m_joystick.getXChannel() : Joystick.kDefaultXChannel, value);
}
public void setY(double value) {
setRawAxis(m_joystick != null ? m_joystick.getYChannel() : Joystick.kDefaultYChannel, value);
}
public void setZ(double value) {
setRawAxis(m_joystick != null ? m_joystick.getZChannel() : Joystick.kDefaultZChannel, value);
}
public void setTwist(double value) {
setRawAxis(
m_joystick != null ? m_joystick.getTwistChannel() : Joystick.kDefaultTwistChannel,
value);
}
public void setThrottle(double value) {
setRawAxis(
m_joystick != null ? m_joystick.getThrottleChannel() : Joystick.kDefaultThrottleChannel,
value);
}
public void setTrigger(boolean state) {
setRawButton(1, state);
}
public void setTop(boolean state) {
setRawButton(2, state);
}
}

View File

@@ -0,0 +1,102 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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.simulation;
import edu.wpi.first.wpilibj.GenericHID;
import edu.wpi.first.wpilibj.XboxController;
/**
* Class to control a simulated Xbox 360 or Xbox One controller.
*/
public class XboxControllerSim extends GenericHIDSim {
/**
* Constructs from a XboxController object.
*
* @param joystick controller to simulate
*/
public XboxControllerSim(XboxController joystick) {
super(joystick);
setAxisCount(6);
setButtonCount(10);
}
/**
* Constructs from a joystick port number.
*
* @param port port number
*/
public XboxControllerSim(int port) {
super(port);
setAxisCount(6);
setButtonCount(10);
}
public void setX(GenericHID.Hand hand, double value) {
if (hand.equals(GenericHID.Hand.kLeft)) {
setRawAxis(XboxController.Axis.kLeftX.value, value);
} else {
setRawAxis(XboxController.Axis.kRightX.value, value);
}
}
public void setY(GenericHID.Hand hand, double value) {
if (hand.equals(GenericHID.Hand.kLeft)) {
setRawAxis(XboxController.Axis.kLeftY.value, value);
} else {
setRawAxis(XboxController.Axis.kRightY.value, value);
}
}
public void setTriggerAxis(GenericHID.Hand hand, double value) {
if (hand.equals(GenericHID.Hand.kLeft)) {
setRawAxis(XboxController.Axis.kLeftTrigger.value, value);
} else {
setRawAxis(XboxController.Axis.kRightTrigger.value, value);
}
}
public void setBumper(GenericHID.Hand hand, boolean state) {
if (hand.equals(GenericHID.Hand.kLeft)) {
setRawButton(XboxController.Button.kBumperLeft.value, state);
} else {
setRawButton(XboxController.Button.kBumperRight.value, state);
}
}
public void setStickButton(GenericHID.Hand hand, boolean state) {
if (hand.equals(GenericHID.Hand.kLeft)) {
setRawButton(XboxController.Button.kStickLeft.value, state);
} else {
setRawButton(XboxController.Button.kStickRight.value, state);
}
}
public void setAButton(boolean state) {
setRawButton(XboxController.Button.kA.value, state);
}
public void setBButton(boolean state) {
setRawButton(XboxController.Button.kB.value, state);
}
public void setXButton(boolean state) {
setRawButton(XboxController.Button.kX.value, state);
}
public void setYButton(boolean state) {
setRawButton(XboxController.Button.kY.value, state);
}
public void setBackButton(boolean state) {
setRawButton(XboxController.Button.kBack.value, state);
}
public void setStartButton(boolean state) {
setRawButton(XboxController.Button.kStart.value, state);
}
}

View File

@@ -0,0 +1,47 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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 org.junit.jupiter.api.Test;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.simulation.JoystickSim;
import static org.junit.jupiter.api.Assertions.assertEquals;
class JoystickTest {
@Test
void testGetX() {
HAL.initialize(500, 0);
Joystick joy = new Joystick(1);
JoystickSim joysim = new JoystickSim(joy);
joysim.setX(0.25);
joysim.notifyNewData();
assertEquals(0.25, joy.getX(), 0.001);
joysim.setX(0);
joysim.notifyNewData();
assertEquals(0.0, joy.getX(), 0.001);
}
@Test
void testGetY() {
HAL.initialize(500, 0);
Joystick joy = new Joystick(1);
JoystickSim joysim = new JoystickSim(joy);
joysim.setY(0.25);
joysim.notifyNewData();
assertEquals(0.25, joy.getY(), 0.001);
joysim.setY(0);
joysim.notifyNewData();
assertEquals(0.0, joy.getY(), 0.001);
}
}

View File

@@ -0,0 +1,86 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. 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 org.junit.jupiter.api.Test;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.simulation.XboxControllerSim;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class XboxControllerTest {
@Test
void testGetX() {
HAL.initialize(500, 0);
XboxController joy = new XboxController(2);
XboxControllerSim joysim = new XboxControllerSim(joy);
joysim.setX(XboxController.Hand.kLeft, 0.35);
joysim.setX(XboxController.Hand.kRight, 0.45);
joysim.notifyNewData();
assertEquals(0.35, joy.getX(XboxController.Hand.kLeft), 0.001);
assertEquals(0.45, joy.getX(XboxController.Hand.kRight), 0.001);
}
@Test
void testGetBumper() {
HAL.initialize(500, 0);
XboxController joy = new XboxController(2);
XboxControllerSim joysim = new XboxControllerSim(joy);
joysim.setBumper(XboxController.Hand.kLeft, false);
joysim.setBumper(XboxController.Hand.kRight, true);
joysim.notifyNewData();
assertFalse(joy.getBumper(XboxController.Hand.kLeft));
assertTrue(joy.getBumper(XboxController.Hand.kRight));
// need to call pressed and released to clear flags
joy.getBumperPressed(XboxController.Hand.kLeft);
joy.getBumperReleased(XboxController.Hand.kLeft);
joy.getBumperPressed(XboxController.Hand.kRight);
joy.getBumperReleased(XboxController.Hand.kRight);
joysim.setBumper(XboxController.Hand.kLeft, true);
joysim.setBumper(XboxController.Hand.kRight, false);
joysim.notifyNewData();
assertTrue(joy.getBumper(XboxController.Hand.kLeft));
assertTrue(joy.getBumperPressed(XboxController.Hand.kLeft));
assertFalse(joy.getBumperReleased(XboxController.Hand.kLeft));
assertFalse(joy.getBumper(XboxController.Hand.kRight));
assertFalse(joy.getBumperPressed(XboxController.Hand.kRight));
assertTrue(joy.getBumperReleased(XboxController.Hand.kRight));
}
@Test
void testGetAButton() {
HAL.initialize(500, 0);
XboxController joy = new XboxController(2);
XboxControllerSim joysim = new XboxControllerSim(joy);
joysim.setAButton(false);
joysim.notifyNewData();
assertFalse(joy.getAButton());
// need to call pressed and released to clear flags
joy.getAButtonPressed();
joy.getAButtonReleased();
joysim.setAButton(true);
joysim.notifyNewData();
assertTrue(joy.getAButton());
assertTrue(joy.getAButtonPressed());
assertFalse(joy.getAButtonReleased());
joysim.setAButton(false);
joysim.notifyNewData();
assertFalse(joy.getAButton());
assertFalse(joy.getAButtonPressed());
assertTrue(joy.getAButtonReleased());
}
}