This is a small utility library that the ESHS P.O.T.A.T.O.E.S. have been using for the past few years to allow robots to be controlled with the keyboard.
It works by capturing keyboard and mouse input in a dedicated JavaFX window
and translating these into boolean values in NetworkTables, a sort of
distributed hashtable provided by WPILib. Robot code can then read known key strings
from the input
NetworkTable in order to figure out what the user has pressed.
Credit goes to @amclees for the original idea.
This code has hard dependencies on NetworkTables and JavaFX. Both must be
present in the $CLASSPATH
in order to build and to run, and JavaFX must
also be present in the $MODULEPATH
. The Gradle build normally takes care
of all this, producing a "fat JAR" with all of the dependencies included
within.
To build this project and download all its dependencies, simply run:
./gradlew build
from the current directory. If all goes well and you have a solid Internet
connection, this should result in a build artifact called
./build/distributions/networkworktablesinput.zip
.
This program must be run from the driver station -- usually a Windows laptop.
-
To run NetworkTablesInput from the ZIP file, unzip it to any location, enter that folder, and run
bin/networktablesinput
(on Unix) orbin/networktablesinput.bat
(on Windows) directly. -
If you happen to have cloned this source tree onto the driver station laptop, you can also enter that directory and execute:
./gradlew run
The NetworkTablesInput program will be executed in-place.
-
Finally, if Gradle isn't working for whatever reason, you can run NetworkTablesInput by hand. It's not easy, though:
-
Download a Gluon SDK build of OpenJFX from https://gluonhq.com/products/javafx.
-
Unzip the build into some folder, like
%USERPROFILE%\Downloads
. -
cd
into the directory wherenetworktablesinput.jar
is located and run the following:java -classpath "%USERPROFILE%/Downloads/javafx-sdk-11.0.2/lib/*;networktablesinput.jar" \ --module-path="%USERPROFILE%/Downloads/javafx-sdk-11.0.2/lib" \ --add-modules=javafx.controls,javafx.fxml \ main.NetworkTablesInput
changing the version number for the JavaFX SDK as appropriate.
You're really better off sticking with Gradle.
-
-
When I try to run, I get a
java.lang.UnsatisifedLinkError
inntcorejni.dll
that says "Can't find dependent libraries."This is a common problem, and it indicates that you need to install the latest Visual C++ redistributable. This seems to only be a problem for people who use the offline WPILib installer.
-
As NetworkTablesInput runs, keypresses and mouse clicks are captured in a blank JavaFX window and passed into the edu.wpi.first.networktables.NetworkTable table called
inputTable
as long as the window has the focus. Every entry placed into the table is a boolean value indicating whether the key is pressed. The keys themselves are just members of the javafx.scene.input.KeyCode enumeration, converted to strings. Examples include:Keyboard key NetworkTables key string Alphabetical Uppercase of the key (i.e. A
,B
,C
, ...)Numbers DIGIT1
,DIGIT2
, ...Mouse buttons Left Mouse
,Right Mouse
Function keys F1
,F2
, ...Shift Shift
Control Ctrl
Alt Alt
Windows Windows
Enter Enter
Escape Esc
-
Minus
=
Equals
[
Open_Bracket
]
Close Bracket
/
Slash
'
Quote
;
Semicolon
Caps Lock Caps Lock
`
Back Quote
Arrow keys UP
,RIGHT
,DOWN
,LEFT
Numeric keypad arrows KP_UP
,KP_RIGHT
,KP_DOWN
,KP_LEFT
Numeric keypad digits NUMPAD0
,NUMPAD1
, ...,NUMPAD9
Home HOME
End END
Page Up PAGE_UP
Page Down PAGE_DOWN
|
Note that capturing the space bar is not possible because the drive station interprets this as an emergency stop.
-
To use this code, you must initialize NetworkTables:
import edu.wpi.first.networktables.NetworkTable; import edu.wpi.first.networktables.NetworkTableEntry; import edu.wpi.first.networktables.NetworkTableInstance; // Initialization NetworkTableInstance networkTableInstance = NetworkTableInstance.getDefault(); if (networkTableInstance.isConnected()) { NetworkTable inputTable = networkTableInstance.getTable("inputTable"); if (this.inputTable != null) { NetworkTableEntry upKey = inputTable.getEntry("Up") NetworkTableEntry downKey = inputTable.getEntry("Down") NetworkTableEntry leftKey = inputTable.getEntry("Left") NetworkTableEntry rightKey = inputTable.getEntry("Right") NetworkTableEntry zKey = inputTable.getEntry("Z") NetworkTableEntry xKey = inputTable.getEntry("x") } }
-
Then during your polling loop, you can do something like this:
if (upKey.getBoolean(false)) { // Drive robot forward } else if (downKey.getBoolean(false)) { // Drive robot backward } else { // Stop robot } if (leftKey.getBoolean(false)) { // Turn robot counterclockwise } else if (rightKey.getBoolean(false)) { // Turn robot clockwise } if (zKey.getBoolean(false)) { // Raise arm } else if (xKey.getBoolean(false)) { // Lower arm } else { // Stop arm motors }
- Add a Gradle build script so that we can pull the latest NetworkTables
JAR the same way FRC robots do:
./gradlew build
. - Bring the batch file back to make this JAR easier to run.
- The distribution created by
./gradlew build
includes a batch file.
- The distribution created by
- Add a section to this README describing how to read the NetworkTablesInput values from the robot code (as soon as we verify that this code works.)
- Don't hard-code the team number; make it -- or, rather, the IP address that uses the team number -- configurable.