[wpilib,cmd] Cache HID wrappers (#8970)

Store DriverStation-owned GenericHID and Gamepad instances in Java and
C++, and expose the cached objects to Python bindings.

Move hand-written command gamepad and joystick wrappers to compose
cached CommandGenericHID instances plus typed HID wrappers, including a
Python CommandGamepad.

This will let us remove UserControls, while helping ensure that we don't
have state smashing between GenericHID objects.

Another bonus is without inheritance, intellisense will no longer show a
bunch of annoying methods, and instead just what actually exists.

---------

Co-authored-by: Peter Johnson <johnson.peter@gmail.com>
This commit is contained in:
Thad House
2026-06-11 09:42:39 -07:00
committed by GitHub
parent fe499ede4c
commit c647e67de0
105 changed files with 4210 additions and 1336 deletions

View File

@@ -18,8 +18,9 @@ import org.wpilib.event.EventLoop;
* @see {{ ConsoleName }}Controller
*/
@SuppressWarnings("MethodName")
public class Command{{ ConsoleName }}Controller extends CommandGenericHID {
private final {{ ConsoleName }}Controller m_hid;
public class Command{{ ConsoleName }}Controller {
private final CommandGenericHID m_hid;
private final {{ ConsoleName }}Controller m_controller;
/**
* Construct an instance of a controller.
@@ -27,19 +28,27 @@ public class Command{{ ConsoleName }}Controller extends CommandGenericHID {
* @param port The port index on the Driver Station that the controller is plugged into.
*/
public Command{{ ConsoleName }}Controller(int port) {
super(port);
m_hid = new {{ ConsoleName }}Controller(port);
m_hid = CommandGenericHID.getCommandGenericHID(port);
m_controller = new {{ ConsoleName }}Controller(m_hid.getHID());
}
/**
* Get the underlying GenericHID object.
* Get the underlying CommandGenericHID object.
*
* @return the wrapped GenericHID object
* @return the wrapped CommandGenericHID object
*/
@Override
public {{ ConsoleName }}Controller getHID() {
public CommandGenericHID getHID() {
return m_hid;
}
/**
* Get the underlying {{ ConsoleName }}Controller object.
*
* @return the wrapped {{ ConsoleName }}Controller object
*/
public {{ ConsoleName }}Controller get{{ ConsoleName }}Controller() {
return m_controller;
}
{% for button in buttons %}
/**
* Constructs a Trigger instance around the {{ button.DocName|default(button.name) }} button's digital signal.
@@ -60,7 +69,7 @@ public class Command{{ ConsoleName }}Controller extends CommandGenericHID {
* to the given loop.
*/
public Trigger {{ button.name }}(EventLoop loop) {
return button({{ ConsoleName }}Controller.Button.k{{ capitalize_first(button.name) }}.value, loop);
return m_hid.button({{ ConsoleName }}Controller.Button.k{{ capitalize_first(button.name) }}.value, loop);
}
{% endfor -%}
{% for trigger in triggers -%}
@@ -76,7 +85,7 @@ public class Command{{ ConsoleName }}Controller extends CommandGenericHID {
* threshold, attached to the given event loop
*/
public Trigger {{ trigger.name }}(double threshold, EventLoop loop) {
return axisGreaterThan({{ ConsoleName }}Controller.Axis.k{{ capitalize_first(trigger.name) }}.value, threshold, loop);
return m_hid.axisGreaterThan({{ ConsoleName }}Controller.Axis.k{{ capitalize_first(trigger.name) }}.value, threshold, loop);
}
/**
@@ -112,7 +121,7 @@ public class Command{{ ConsoleName }}Controller extends CommandGenericHID {
* @return The axis value.
*/
public double get{{ stick.NameParts|map("capitalize")|join }}() {
return m_hid.get{{ stick.NameParts|map("capitalize")|join }}();
return m_controller.get{{ stick.NameParts|map("capitalize")|join }}();
}
{% endfor -%}
{% for trigger in triggers %}
@@ -123,7 +132,7 @@ public class Command{{ ConsoleName }}Controller extends CommandGenericHID {
* @return The axis value.
*/
public double get{{ capitalize_first(trigger.name) }}Axis() {
return m_hid.get{{ capitalize_first(trigger.name) }}Axis();
return m_controller.get{{ capitalize_first(trigger.name) }}Axis();
}
{% endfor -%}
}

View File

@@ -11,33 +11,39 @@
using namespace wpi::cmd;
Command{{ ConsoleName }}Controller::Command{{ ConsoleName }}Controller(int port)
: CommandGenericHID(port), m_hid{wpi::{{ ConsoleName }}Controller(port)} {}
: m_hid{&CommandGenericHID::GetCommandGenericHID(port)},
m_controller{m_hid->GetHID()} {}
wpi::{{ ConsoleName }}Controller& Command{{ ConsoleName }}Controller::GetHID() {
return m_hid;
CommandGenericHID& Command{{ ConsoleName }}Controller::GetHID() {
return *m_hid;
}
wpi::{{ ConsoleName }}Controller&
Command{{ ConsoleName }}Controller::Get{{ ConsoleName }}Controller() {
return m_controller;
}
{% for button in buttons %}
Trigger Command{{ ConsoleName }}Controller::{{ capitalize_first(button.name) }}(wpi::EventLoop* loop) const {
return Button(wpi::{{ ConsoleName }}Controller::Button::k{{ capitalize_first(button.name) }}, loop);
return m_hid->Button(
wpi::{{ ConsoleName }}Controller::Button::k{{ capitalize_first(button.name) }}, loop);
}
{% endfor -%}
{% for trigger in triggers -%}
{% if trigger.UseThresholdMethods %}
Trigger Command{{ ConsoleName }}Controller::{{ capitalize_first(trigger.name) }}(double threshold,
wpi::EventLoop* loop) const {
return Trigger(loop, [this, threshold] {
return m_hid.Get{{ capitalize_first(trigger.name) }}Axis() > threshold;
});
return m_hid->AxisGreaterThan(
wpi::{{ ConsoleName }}Controller::Axis::k{{ capitalize_first(trigger.name) }}, threshold, loop);
}
{% endif -%}
{% endfor -%}
{% for stick in sticks %}
double Command{{ ConsoleName }}Controller::Get{{ stick.NameParts|map("capitalize")|join }}() const {
return m_hid.Get{{ stick.NameParts|map("capitalize")|join }}();
return m_controller.Get{{ stick.NameParts|map("capitalize")|join }}();
}
{% endfor -%}
{% for trigger in triggers %}
double Command{{ ConsoleName }}Controller::Get{{ capitalize_first(trigger.name) }}Axis() const {
return m_hid.Get{{ capitalize_first(trigger.name) }}Axis();
return m_controller.Get{{ capitalize_first(trigger.name) }}Axis();
}
{% endfor -%}

View File

@@ -8,11 +8,10 @@
{%- endmacro %}
#pragma once
#include "wpi/driverstation/{{ ConsoleName }}Controller.hpp"
#include "wpi/commands2/button/Trigger.hpp"
#include "wpi/commands2/CommandScheduler.hpp"
#include "wpi/commands2/button/Trigger.hpp"
#include "wpi/commands2/button/CommandGenericHID.hpp"
#include "wpi/driverstation/{{ ConsoleName }}Controller.hpp"
namespace wpi::cmd {
/**
@@ -21,7 +20,7 @@ namespace wpi::cmd {
*
* @see wpi::{{ ConsoleName }}Controller
*/
class Command{{ ConsoleName }}Controller : public CommandGenericHID {
class Command{{ ConsoleName }}Controller {
public:
/**
* Construct an instance of a controller.
@@ -32,11 +31,18 @@ class Command{{ ConsoleName }}Controller : public CommandGenericHID {
explicit Command{{ ConsoleName }}Controller(int port);
/**
* Get the underlying GenericHID object.
* Get the underlying CommandGenericHID object.
*
* @return the wrapped GenericHID object
* @return the wrapped CommandGenericHID object
*/
wpi::{{ ConsoleName }}Controller& GetHID();
CommandGenericHID& GetHID();
/**
* Get the underlying {{ ConsoleName }}Controller object.
*
* @return the wrapped {{ ConsoleName }}Controller object
*/
wpi::{{ ConsoleName }}Controller& Get{{ ConsoleName }}Controller();
{% for button in buttons %}
/**
* Constructs a Trigger instance around the {{ button.DocName|default(button.name) }} button's
@@ -88,6 +94,7 @@ class Command{{ ConsoleName }}Controller : public CommandGenericHID {
double Get{{ capitalize_first(trigger.name) }}Axis() const;
{% endfor %}
private:
wpi::{{ ConsoleName }}Controller m_hid;
CommandGenericHID* m_hid;
wpi::{{ ConsoleName }}Controller m_controller;
};
} // namespace wpi::cmd