[wpilib] Add PS4Controller, remove Hand from GenericHID/XboxController (#3345)

- GenericHID is now concrete, and has only getRawAxis/Button(int) functionality
- getXxx() has been moved into Joystick as that's the only place where it makes sense
- Hand (and therefore getXxx(Hand)) has been removed, replaced by specific getLeft/RightXxx() methods in XboxController and the new PS4Controller class
- C++ ::Button:: and ::Axis:: enums have been converted to identically-namespaced static constexpr ints
This commit is contained in:
Starlight220
2021-08-14 20:00:46 +03:00
committed by GitHub
parent 25f6f478a5
commit 031962608b
82 changed files with 2548 additions and 934 deletions

View File

@@ -0,0 +1,81 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.wpilibj;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.simulation.PS4ControllerSim;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
class PS4ControllerTest {
@ParameterizedTest
@EnumSource(value = PS4Controller.Button.class)
@SuppressWarnings({"VariableDeclarationUsageDistance"})
public void testButtons(PS4Controller.Button button)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
HAL.initialize(500, 0);
PS4Controller joy = new PS4Controller(2);
PS4ControllerSim joysim = new PS4ControllerSim(joy);
var buttonName = button.toString();
String simSetMethodName = "set" + buttonName;
String joyGetMethodName = "get" + buttonName;
String joyPressedMethodName = "get" + buttonName + "Pressed";
String joyReleasedMethodName = "get" + buttonName + "Released";
Method simSetMethod = joysim.getClass().getMethod(simSetMethodName, boolean.class);
Method joyGetMethod = joy.getClass().getMethod(joyGetMethodName);
Method joyPressedMethod = joy.getClass().getMethod(joyPressedMethodName);
Method joyReleasedMethod = joy.getClass().getMethod(joyReleasedMethodName);
simSetMethod.invoke(joysim, false);
joysim.notifyNewData();
assertFalse((Boolean) joyGetMethod.invoke(joy));
// need to call pressed and released to clear flags
joyPressedMethod.invoke(joy);
joyReleasedMethod.invoke(joy);
simSetMethod.invoke(joysim, true);
joysim.notifyNewData();
assertTrue((Boolean) joyGetMethod.invoke(joy));
assertTrue((Boolean) joyPressedMethod.invoke(joy));
assertFalse((Boolean) joyReleasedMethod.invoke(joy));
simSetMethod.invoke(joysim, false);
joysim.notifyNewData();
assertFalse((Boolean) joyGetMethod.invoke(joy));
assertFalse((Boolean) joyPressedMethod.invoke(joy));
assertTrue((Boolean) joyReleasedMethod.invoke(joy));
}
@ParameterizedTest
@EnumSource(value = PS4Controller.Axis.class)
@SuppressWarnings({"VariableDeclarationUsageDistance"})
public void testAxes(PS4Controller.Axis axis)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
HAL.initialize(500, 0);
PS4Controller joy = new PS4Controller(2);
PS4ControllerSim joysim = new PS4ControllerSim(joy);
var axisName = axis.toString();
String simSetMethodName = "set" + axisName;
String joyGetMethodName = "get" + axisName;
Method simSetMethod = joysim.getClass().getMethod(simSetMethodName, double.class);
Method joyGetMethod = joy.getClass().getMethod(joyGetMethodName);
simSetMethod.invoke(joysim, 0.35);
joysim.notifyNewData();
assertEquals(0.35, (Double) joyGetMethod.invoke(joy), 0.001);
}
}

View File

@@ -12,70 +12,25 @@ import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.simulation.XboxControllerSim;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.EnumSource;
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 testGetY() {
HAL.initialize(500, 0);
XboxControllerSim joysim = new XboxControllerSim(2);
joysim.setY(XboxController.Hand.kLeft, 0.35);
joysim.setY(XboxController.Hand.kRight, 0.45);
joysim.notifyNewData();
XboxController joy = new XboxController(2);
assertEquals(0.35, joy.getY(XboxController.Hand.kLeft), 0.001);
assertEquals(0.45, joy.getY(XboxController.Hand.kRight), 0.001);
}
@Test
void testGetTrigger() {
HAL.initialize(500, 0);
XboxController joy = new XboxController(2);
XboxControllerSim joysim = new XboxControllerSim(joy);
joysim.setTriggerAxis(XboxController.Hand.kLeft, 0.35);
joysim.setTriggerAxis(XboxController.Hand.kRight, 0.45);
joysim.notifyNewData();
assertEquals(0.35, joy.getTriggerAxis(XboxController.Hand.kLeft), 0.001);
assertEquals(0.45, joy.getTriggerAxis(XboxController.Hand.kRight), 0.001);
}
private static Stream<String> getStandardButtonsArguments() {
return Stream.of("A", "B", "X", "Y", "Back", "Start");
}
@ParameterizedTest
@MethodSource("getStandardButtonsArguments")
@EnumSource(value = XboxController.Button.class)
@SuppressWarnings({"VariableDeclarationUsageDistance"})
public void testStandardButtons(String buttonName)
public void testButtons(XboxController.Button button)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
HAL.initialize(500, 0);
XboxController joy = new XboxController(2);
XboxControllerSim joysim = new XboxControllerSim(joy);
String simSetMethodName = "set" + buttonName + "Button";
String joyGetMethodName = "get" + buttonName + "Button";
String joyPressedMethodName = "get" + buttonName + "ButtonPressed";
String joyReleasedMethodName = "get" + buttonName + "ButtonReleased";
var buttonName = button.toString();
String simSetMethodName = "set" + buttonName;
String joyGetMethodName = "get" + buttonName;
String joyPressedMethodName = "get" + buttonName + "Pressed";
String joyReleasedMethodName = "get" + buttonName + "Released";
Method simSetMethod = joysim.getClass().getMethod(simSetMethodName, boolean.class);
Method joyGetMethod = joy.getClass().getMethod(joyGetMethodName);
@@ -102,52 +57,25 @@ class XboxControllerTest {
assertTrue((Boolean) joyReleasedMethod.invoke(joy));
}
private static Stream<Arguments> getStickButtonsArguments() {
return Stream.of(
Arguments.of(GenericHID.Hand.kLeft, "Bumper"),
Arguments.of(GenericHID.Hand.kRight, "Bumper"),
Arguments.of(GenericHID.Hand.kLeft, "StickButton"),
Arguments.of(GenericHID.Hand.kRight, "StickButton"));
}
@ParameterizedTest
@MethodSource("getStickButtonsArguments")
@EnumSource(value = XboxController.Axis.class)
@SuppressWarnings({"VariableDeclarationUsageDistance"})
public void testStickButtons(GenericHID.Hand hand, String buttonName)
public void testAxes(XboxController.Axis axis)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
HAL.initialize(500, 0);
XboxController joy = new XboxController(2);
XboxControllerSim joysim = new XboxControllerSim(joy);
String simSetMethodName = "set" + buttonName;
String joyGetMethodName = "get" + buttonName;
String joyPressedMethodName = "get" + buttonName + "Pressed";
String joyReleasedMethodName = "get" + buttonName + "Released";
var axisName = axis.toString();
Method simSetMethod =
joysim.getClass().getMethod(simSetMethodName, GenericHID.Hand.class, boolean.class);
Method joyGetMethod = joy.getClass().getMethod(joyGetMethodName, GenericHID.Hand.class);
Method joyPressedMethod = joy.getClass().getMethod(joyPressedMethodName, GenericHID.Hand.class);
Method joyReleasedMethod =
joy.getClass().getMethod(joyReleasedMethodName, GenericHID.Hand.class);
String simSetMethodName = "set" + axisName;
String joyGetMethodName = "get" + axisName;
simSetMethod.invoke(joysim, hand, false);
Method simSetMethod = joysim.getClass().getMethod(simSetMethodName, double.class);
Method joyGetMethod = joy.getClass().getMethod(joyGetMethodName);
simSetMethod.invoke(joysim, 0.35);
joysim.notifyNewData();
assertFalse((Boolean) joyGetMethod.invoke(joy, hand));
// need to call pressed and released to clear flags
joyPressedMethod.invoke(joy, hand);
joyReleasedMethod.invoke(joy, hand);
simSetMethod.invoke(joysim, hand, true);
joysim.notifyNewData();
assertTrue((Boolean) joyGetMethod.invoke(joy, hand));
assertTrue((Boolean) joyPressedMethod.invoke(joy, hand));
assertFalse((Boolean) joyReleasedMethod.invoke(joy, hand));
simSetMethod.invoke(joysim, hand, false);
joysim.notifyNewData();
assertFalse((Boolean) joyGetMethod.invoke(joy, hand));
assertFalse((Boolean) joyPressedMethod.invoke(joy, hand));
assertTrue((Boolean) joyReleasedMethod.invoke(joy, hand));
assertEquals(0.35, (Double) joyGetMethod.invoke(joy), 0.001);
}
}