2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2018-01-02 09:20:21 -08:00
|
|
|
/* Copyright (c) 2008-2018 FIRST. All Rights Reserved. */
|
2016-01-02 03:02:34 -08:00
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
2013-12-15 18:30:16 -05:00
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
2016-01-02 03:02:34 -08:00
|
|
|
/* the project. */
|
2013-12-15 18:30:16 -05:00
|
|
|
/*----------------------------------------------------------------------------*/
|
2016-01-02 03:02:34 -08:00
|
|
|
|
2013-12-15 18:30:16 -05:00
|
|
|
package edu.wpi.first.wpilibj;
|
|
|
|
|
|
2014-01-06 10:12:21 -05:00
|
|
|
import java.nio.ByteBuffer;
|
2018-01-18 21:54:33 -08:00
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
import java.util.concurrent.locks.Condition;
|
|
|
|
|
import java.util.concurrent.locks.Lock;
|
|
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
2016-10-24 20:32:43 -07:00
|
|
|
|
2018-01-18 23:17:28 -08:00
|
|
|
import edu.wpi.first.networktables.NetworkTable;
|
|
|
|
|
import edu.wpi.first.networktables.NetworkTableEntry;
|
|
|
|
|
import edu.wpi.first.networktables.NetworkTableInstance;
|
2016-07-10 16:24:57 -07:00
|
|
|
import edu.wpi.first.wpilibj.hal.AllianceStationID;
|
|
|
|
|
import edu.wpi.first.wpilibj.hal.ControlWord;
|
|
|
|
|
import edu.wpi.first.wpilibj.hal.HAL;
|
2017-11-09 19:59:29 -08:00
|
|
|
import edu.wpi.first.wpilibj.hal.MatchInfoData;
|
2014-08-08 14:56:22 -04:00
|
|
|
import edu.wpi.first.wpilibj.hal.PowerJNI;
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Provide access to the network communication data to / from the Driver Station.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2018-06-03 10:00:53 -07:00
|
|
|
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.ExcessiveClassLength",
|
|
|
|
|
"PMD.ExcessivePublicCount", "PMD.GodClass", "PMD.TooManyFields",
|
|
|
|
|
"PMD.TooManyMethods"})
|
2018-07-08 15:41:31 -07:00
|
|
|
public class DriverStation {
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Number of Joystick Ports.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
|
|
|
|
public static final int kJoystickPorts = 6;
|
|
|
|
|
|
|
|
|
|
private class HALJoystickButtons {
|
2016-05-20 12:07:40 -04:00
|
|
|
public int m_buttons;
|
|
|
|
|
public byte m_count;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
private class HALJoystickAxes {
|
2016-05-21 01:42:16 -07:00
|
|
|
public float[] m_axes;
|
2016-07-10 16:24:57 -07:00
|
|
|
public short m_count;
|
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
|
|
|
|
2017-10-17 21:47:55 -07:00
|
|
|
HALJoystickAxes(int count) {
|
2016-05-21 01:42:16 -07:00
|
|
|
m_axes = new float[count];
|
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
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class HALJoystickPOVs {
|
|
|
|
|
public short[] m_povs;
|
2016-07-10 16:24:57 -07:00
|
|
|
public short m_count;
|
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
|
|
|
|
2017-10-17 21:47:55 -07:00
|
|
|
HALJoystickPOVs(int count) {
|
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
|
|
|
m_povs = new short[count];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* The robot alliance that the robot is a part of.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
|
|
|
|
public enum Alliance {
|
|
|
|
|
Red, Blue, Invalid
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-09 19:59:29 -08:00
|
|
|
public enum MatchType {
|
|
|
|
|
None, Practice, Qualification, Elimination
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
private static final double JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL = 1.0;
|
2018-06-03 10:00:53 -07:00
|
|
|
private double m_nextMessageTime;
|
2015-06-25 15:07:55 -04:00
|
|
|
|
|
|
|
|
private static class DriverStationTask implements Runnable {
|
2018-06-03 10:00:53 -07:00
|
|
|
private final DriverStation m_ds;
|
2015-06-25 15:07:55 -04:00
|
|
|
|
|
|
|
|
DriverStationTask(DriverStation ds) {
|
|
|
|
|
m_ds = ds;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-03 10:00:53 -07:00
|
|
|
@Override
|
2015-06-25 15:07:55 -04:00
|
|
|
public void run() {
|
2016-07-14 20:50:38 -07:00
|
|
|
m_ds.run();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
} /* DriverStationTask */
|
|
|
|
|
|
2018-01-18 23:17:28 -08:00
|
|
|
private static class MatchDataSender {
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTable table;
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTableEntry typeMetadata;
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTableEntry gameSpecificMessage;
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTableEntry eventName;
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTableEntry matchNumber;
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTableEntry replayNumber;
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTableEntry matchType;
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTableEntry alliance;
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTableEntry station;
|
|
|
|
|
@SuppressWarnings("MemberName")
|
|
|
|
|
NetworkTableEntry controlWord;
|
|
|
|
|
|
|
|
|
|
MatchDataSender() {
|
|
|
|
|
table = 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
private static DriverStation instance = new DriverStation();
|
|
|
|
|
|
2016-10-24 20:32:43 -07:00
|
|
|
// Joystick User Data
|
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
|
|
|
private HALJoystickAxes[] m_joystickAxes = new HALJoystickAxes[kJoystickPorts];
|
|
|
|
|
private HALJoystickPOVs[] m_joystickPOVs = new HALJoystickPOVs[kJoystickPorts];
|
2015-06-25 15:07:55 -04:00
|
|
|
private HALJoystickButtons[] m_joystickButtons = new HALJoystickButtons[kJoystickPorts];
|
2017-11-09 19:59:29 -08:00
|
|
|
private MatchInfoData m_matchInfo = new MatchInfoData();
|
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
|
|
|
|
2016-10-24 20:32:43 -07:00
|
|
|
// Joystick Cached Data
|
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
|
|
|
private HALJoystickAxes[] m_joystickAxesCache = new HALJoystickAxes[kJoystickPorts];
|
|
|
|
|
private HALJoystickPOVs[] m_joystickPOVsCache = new HALJoystickPOVs[kJoystickPorts];
|
|
|
|
|
private HALJoystickButtons[] m_joystickButtonsCache = new HALJoystickButtons[kJoystickPorts];
|
2017-11-09 19:59:29 -08:00
|
|
|
private MatchInfoData m_matchInfoCache = new MatchInfoData();
|
2017-10-27 21:45:56 -07:00
|
|
|
|
|
|
|
|
// Joystick button rising/falling edge flags
|
2018-05-17 13:00:48 +10:00
|
|
|
private int[] m_joystickButtonsPressed = new int[kJoystickPorts];
|
|
|
|
|
private int[] m_joystickButtonsReleased = new int[kJoystickPorts];
|
2017-10-27 21:45:56 -07:00
|
|
|
|
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
|
|
|
// preallocated byte buffer for button count
|
2018-06-03 10:00:53 -07:00
|
|
|
private final ByteBuffer m_buttonCountBuffer = ByteBuffer.allocateDirect(1);
|
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
|
|
|
|
2018-06-03 10:00:53 -07:00
|
|
|
private final MatchDataSender m_matchDataSender;
|
2018-01-18 23:17:28 -08:00
|
|
|
|
2016-10-24 20:32:43 -07:00
|
|
|
// Internal Driver Station thread
|
2018-06-03 10:00:53 -07:00
|
|
|
@SuppressWarnings("PMD.SingularField")
|
|
|
|
|
private final Thread m_thread;
|
2016-05-20 12:07:40 -04:00
|
|
|
private volatile boolean m_threadKeepAlive = true;
|
2016-07-10 08:33:27 -07:00
|
|
|
|
2018-05-16 00:13:52 -07:00
|
|
|
private final ReentrantLock m_cacheDataMutex = new ReentrantLock();
|
2016-10-24 20:32:43 -07:00
|
|
|
|
2018-01-18 21:54:33 -08:00
|
|
|
private final Lock m_waitForDataMutex;
|
|
|
|
|
private final Condition m_waitForDataCond;
|
|
|
|
|
private int m_waitForDataCount;
|
|
|
|
|
|
2016-10-24 20:32:43 -07:00
|
|
|
// Robot state status variables
|
2018-06-03 10:00:53 -07:00
|
|
|
private boolean m_userInDisabled;
|
|
|
|
|
private boolean m_userInAutonomous;
|
|
|
|
|
private boolean m_userInTeleop;
|
|
|
|
|
private boolean m_userInTest;
|
2016-10-24 20:32:43 -07:00
|
|
|
|
|
|
|
|
// Control word variables
|
|
|
|
|
private final Object m_controlWordMutex;
|
2018-06-03 10:00:53 -07:00
|
|
|
private final ControlWord m_controlWordCache;
|
2016-10-24 20:32:43 -07:00
|
|
|
private long m_lastControlWordUpdate;
|
2015-06-25 15:07:55 -04:00
|
|
|
|
|
|
|
|
/**
|
2017-07-28 22:24:05 -07:00
|
|
|
* Gets an instance of the DriverStation.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @return The DriverStation.
|
|
|
|
|
*/
|
|
|
|
|
public static DriverStation getInstance() {
|
|
|
|
|
return DriverStation.instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* DriverStation constructor.
|
|
|
|
|
*
|
2016-05-20 12:07:40 -04:00
|
|
|
* <p>The single DriverStation instance is created statically with the instance static member
|
|
|
|
|
* variable.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2018-06-03 10:00:53 -07:00
|
|
|
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
|
2016-07-14 20:50:38 -07:00
|
|
|
private DriverStation() {
|
2018-05-24 17:03:19 -07:00
|
|
|
HAL.initialize(500, 0);
|
2018-01-18 21:54:33 -08:00
|
|
|
m_waitForDataCount = 0;
|
|
|
|
|
m_waitForDataMutex = new ReentrantLock();
|
|
|
|
|
m_waitForDataCond = m_waitForDataMutex.newCondition();
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
for (int i = 0; i < kJoystickPorts; i++) {
|
|
|
|
|
m_joystickButtons[i] = new HALJoystickButtons();
|
2016-07-10 16:24:57 -07:00
|
|
|
m_joystickAxes[i] = new HALJoystickAxes(HAL.kMaxJoystickAxes);
|
|
|
|
|
m_joystickPOVs[i] = new HALJoystickPOVs(HAL.kMaxJoystickPOVs);
|
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
|
|
|
|
|
|
|
|
m_joystickButtonsCache[i] = new HALJoystickButtons();
|
2016-07-10 16:24:57 -07:00
|
|
|
m_joystickAxesCache[i] = new HALJoystickAxes(HAL.kMaxJoystickAxes);
|
|
|
|
|
m_joystickPOVsCache[i] = new HALJoystickPOVs(HAL.kMaxJoystickPOVs);
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2016-07-15 13:39:26 -07:00
|
|
|
m_controlWordMutex = new Object();
|
|
|
|
|
m_controlWordCache = new ControlWord();
|
|
|
|
|
m_lastControlWordUpdate = 0;
|
|
|
|
|
|
2018-01-18 23:17:28 -08:00
|
|
|
m_matchDataSender = new MatchDataSender();
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
m_thread = new Thread(new DriverStationTask(this), "FRCDriverStation");
|
|
|
|
|
m_thread.setPriority((Thread.NORM_PRIORITY + Thread.MAX_PRIORITY) / 2);
|
|
|
|
|
|
|
|
|
|
m_thread.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Kill the thread.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
|
|
|
|
public void release() {
|
2016-05-20 12:07:40 -04:00
|
|
|
m_threadKeepAlive = false;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-10-30 21:50:14 -07:00
|
|
|
* Report error to Driver Station. Optionally appends Stack trace
|
2016-07-14 20:50:38 -07:00
|
|
|
* to error message.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
2016-07-14 20:50:38 -07:00
|
|
|
* @param printTrace If true, append stack trace to error string
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2016-07-14 20:50:38 -07:00
|
|
|
public static void reportError(String error, boolean printTrace) {
|
|
|
|
|
reportErrorImpl(true, 1, error, printTrace);
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-10-30 21:50:14 -07:00
|
|
|
* Report error to Driver Station. Appends provided stack trace
|
|
|
|
|
* to error message.
|
|
|
|
|
*
|
|
|
|
|
* @param stackTrace The stack trace to append
|
|
|
|
|
*/
|
|
|
|
|
public static void reportError(String error, StackTraceElement[] stackTrace) {
|
|
|
|
|
reportErrorImpl(true, 1, error, stackTrace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Report warning to Driver Station. Optionally appends Stack
|
2016-07-14 20:50:38 -07:00
|
|
|
* trace to warning message.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
2016-07-14 20:50:38 -07:00
|
|
|
* @param printTrace If true, append stack trace to warning string
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2016-07-14 20:50:38 -07:00
|
|
|
public static void reportWarning(String error, boolean printTrace) {
|
|
|
|
|
reportErrorImpl(false, 1, error, printTrace);
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2017-10-30 21:50:14 -07:00
|
|
|
/**
|
|
|
|
|
* Report warning to Driver Station. Appends provided stack
|
|
|
|
|
* trace to warning message.
|
|
|
|
|
*
|
|
|
|
|
* @param stackTrace The stack trace to append
|
|
|
|
|
*/
|
|
|
|
|
public static void reportWarning(String error, StackTraceElement[] stackTrace) {
|
|
|
|
|
reportErrorImpl(false, 1, error, stackTrace);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
private static void reportErrorImpl(boolean isError, int code, String error, boolean
|
|
|
|
|
printTrace) {
|
2017-10-30 21:50:14 -07:00
|
|
|
reportErrorImpl(isError, code, error, printTrace, Thread.currentThread().getStackTrace(), 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void reportErrorImpl(boolean isError, int code, String error,
|
|
|
|
|
StackTraceElement[] stackTrace) {
|
|
|
|
|
reportErrorImpl(isError, code, error, true, stackTrace, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void reportErrorImpl(boolean isError, int code, String error,
|
|
|
|
|
boolean printTrace, StackTraceElement[] stackTrace, int stackTraceFirst) {
|
2016-07-14 20:50:38 -07:00
|
|
|
String locString;
|
2017-10-30 21:50:14 -07:00
|
|
|
if (stackTrace.length >= stackTraceFirst + 1) {
|
|
|
|
|
locString = stackTrace[stackTraceFirst].toString();
|
2016-07-14 20:50:38 -07:00
|
|
|
} else {
|
2016-12-08 00:24:44 -05:00
|
|
|
locString = "";
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-06-03 10:00:53 -07:00
|
|
|
StringBuilder traceString = new StringBuilder("");
|
2017-11-08 23:44:03 -08:00
|
|
|
if (printTrace) {
|
|
|
|
|
boolean haveLoc = false;
|
|
|
|
|
for (int i = stackTraceFirst; i < stackTrace.length; i++) {
|
|
|
|
|
String loc = stackTrace[i].toString();
|
2018-06-03 10:00:53 -07:00
|
|
|
traceString.append("\tat ").append(loc).append('\n');
|
2017-11-08 23:44:03 -08:00
|
|
|
// get first user function
|
|
|
|
|
if (!haveLoc && !loc.startsWith("edu.wpi.first")) {
|
|
|
|
|
locString = loc;
|
|
|
|
|
haveLoc = true;
|
|
|
|
|
}
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
2016-02-04 22:29:11 -08:00
|
|
|
}
|
2018-06-03 10:00:53 -07:00
|
|
|
HAL.sendError(isError, code, false, error, locString, traceString.toString(), true);
|
2016-02-04 22:29:11 -08:00
|
|
|
}
|
|
|
|
|
|
2017-10-27 21:45:56 -07:00
|
|
|
/**
|
|
|
|
|
* The state of one joystick button. Button indexes begin at 1.
|
|
|
|
|
*
|
|
|
|
|
* @param stick The joystick to read.
|
|
|
|
|
* @param button The button index, beginning at 1.
|
|
|
|
|
* @return The state of the joystick button.
|
|
|
|
|
*/
|
|
|
|
|
public boolean getStickButton(final int stick, final int button) {
|
2018-05-16 00:13:52 -07:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-3");
|
2018-05-16 00:13:52 -07:00
|
|
|
}
|
2017-10-27 21:45:56 -07:00
|
|
|
if (button <= 0) {
|
|
|
|
|
reportJoystickUnpluggedError("Button indexes begin at 1 in WPILib for C++ and Java\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
2017-10-27 21:45:56 -07:00
|
|
|
if (button > m_joystickButtons[stick].m_count) {
|
2018-05-16 00:13:52 -07:00
|
|
|
// Unlock early so error printing isn't locked.
|
|
|
|
|
m_cacheDataMutex.unlock();
|
|
|
|
|
reportJoystickUnpluggedWarning("Joystick Button " + button + " on port " + stick
|
|
|
|
|
+ " not available, check if controller is plugged in");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (m_joystickButtons[stick].m_buttons & 1 << (button - 1)) != 0;
|
|
|
|
|
} finally {
|
|
|
|
|
if (m_cacheDataMutex.isHeldByCurrentThread()) {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Whether one joystick button was pressed since the last check. Button indexes begin at 1.
|
|
|
|
|
*
|
|
|
|
|
* @param stick The joystick to read.
|
|
|
|
|
* @param button The button index, beginning at 1.
|
|
|
|
|
* @return Whether the joystick button was pressed since the last check.
|
|
|
|
|
*/
|
|
|
|
|
boolean getStickButtonPressed(final int stick, final int button) {
|
|
|
|
|
if (button <= 0) {
|
|
|
|
|
reportJoystickUnpluggedError("Button indexes begin at 1 in WPILib for C++ and Java\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-3");
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
2018-05-17 13:00:48 +10:00
|
|
|
boolean error = false;
|
|
|
|
|
boolean retVal = false;
|
|
|
|
|
synchronized (m_cacheDataMutex) {
|
|
|
|
|
if (button > m_joystickButtons[stick].m_count) {
|
|
|
|
|
error = true;
|
|
|
|
|
retVal = false;
|
|
|
|
|
} else {
|
|
|
|
|
// If button was pressed, clear flag and return true
|
|
|
|
|
if ((m_joystickButtonsPressed[stick] & 1 << (button - 1)) != 0) {
|
|
|
|
|
m_joystickButtonsPressed[stick] &= ~(1 << (button - 1));
|
|
|
|
|
retVal = true;
|
|
|
|
|
} else {
|
|
|
|
|
retVal = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (error) {
|
|
|
|
|
reportJoystickUnpluggedWarning("Joystick Button " + button + " on port " + stick
|
|
|
|
|
+ " not available, check if controller is plugged in");
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
2018-05-17 13:00:48 +10:00
|
|
|
return retVal;
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Whether one joystick button was released since the last check. Button indexes
|
|
|
|
|
* begin at 1.
|
|
|
|
|
*
|
|
|
|
|
* @param stick The joystick to read.
|
|
|
|
|
* @param button The button index, beginning at 1.
|
|
|
|
|
* @return Whether the joystick button was released since the last check.
|
|
|
|
|
*/
|
|
|
|
|
boolean getStickButtonReleased(final int stick, final int button) {
|
|
|
|
|
if (button <= 0) {
|
|
|
|
|
reportJoystickUnpluggedError("Button indexes begin at 1 in WPILib for C++ and Java\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-3");
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
2018-05-17 13:00:48 +10:00
|
|
|
boolean error = false;
|
|
|
|
|
boolean retVal = false;
|
|
|
|
|
synchronized (m_cacheDataMutex) {
|
|
|
|
|
if (button > m_joystickButtons[stick].m_count) {
|
|
|
|
|
error = true;
|
|
|
|
|
retVal = false;
|
|
|
|
|
} else {
|
|
|
|
|
// If button was released, clear flag and return true
|
|
|
|
|
if ((m_joystickButtonsReleased[stick] & 1 << (button - 1)) != 0) {
|
|
|
|
|
m_joystickButtonsReleased[stick] &= ~(1 << (button - 1));
|
|
|
|
|
retVal = true;
|
|
|
|
|
} else {
|
|
|
|
|
retVal = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (error) {
|
|
|
|
|
reportJoystickUnpluggedWarning("Joystick Button " + button + " on port " + stick
|
|
|
|
|
+ " not available, check if controller is plugged in");
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
2018-05-17 13:00:48 +10:00
|
|
|
return retVal;
|
2017-10-27 21:45:56 -07:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Get the value of the axis on a joystick. This depends on the mapping of the joystick connected
|
|
|
|
|
* to the specified port.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @param stick The joystick to read.
|
2016-05-20 12:07:40 -04:00
|
|
|
* @param axis The analog axis value to read from the joystick.
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return The value of the axis on the joystick.
|
|
|
|
|
*/
|
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
|
|
|
public double getStickAxis(int stick, int axis) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-5");
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
if (axis >= HAL.kMaxJoystickAxes) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick axis is out of range");
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2016-07-10 08:33:27 -07:00
|
|
|
|
2018-05-16 00:13:52 -07:00
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
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
|
|
|
if (axis >= m_joystickAxes[stick].m_count) {
|
2018-05-16 00:13:52 -07:00
|
|
|
// Unlock early so error printing isn't locked.
|
|
|
|
|
m_cacheDataMutex.unlock();
|
|
|
|
|
reportJoystickUnpluggedWarning("Joystick axis " + axis + " on port " + stick
|
|
|
|
|
+ " not available, check if controller is plugged in");
|
|
|
|
|
return 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return m_joystickAxes[stick].m_axes[axis];
|
|
|
|
|
} finally {
|
|
|
|
|
if (m_cacheDataMutex.isHeldByCurrentThread()) {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
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
|
|
|
}
|
2016-07-10 08:33:27 -07:00
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the state of a POV on the joystick.
|
|
|
|
|
*
|
|
|
|
|
* @return the angle of the POV in degrees, or -1 if the POV is not pressed.
|
|
|
|
|
*/
|
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
|
|
|
public int getStickPOV(int stick, int pov) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-5");
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
if (pov >= HAL.kMaxJoystickPOVs) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick POV is out of range");
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
|
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
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
|
|
|
if (pov >= m_joystickPOVs[stick].m_count) {
|
2018-05-16 00:13:52 -07:00
|
|
|
// Unlock early so error printing isn't locked.
|
|
|
|
|
m_cacheDataMutex.unlock();
|
|
|
|
|
reportJoystickUnpluggedWarning("Joystick POV " + pov + " on port " + stick
|
|
|
|
|
+ " not available, check if controller is plugged in");
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
if (m_cacheDataMutex.isHeldByCurrentThread()) {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
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
|
|
|
}
|
|
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
|
|
|
|
return m_joystickPOVs[stick].m_povs[pov];
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The state of the buttons on the joystick.
|
|
|
|
|
*
|
|
|
|
|
* @param stick The joystick to read.
|
|
|
|
|
* @return The state of the buttons on the joystick.
|
|
|
|
|
*/
|
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
|
|
|
public int getStickButtons(final int stick) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-3");
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
|
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
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].m_buttons;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
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
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
/**
|
|
|
|
|
* Returns the number of axes on a given joystick port.
|
|
|
|
|
*
|
|
|
|
|
* @param stick The joystick port number
|
|
|
|
|
* @return The number of axes on the indicated joystick
|
|
|
|
|
*/
|
|
|
|
|
public int getStickAxisCount(int stick) {
|
|
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-5");
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
|
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
2016-07-14 20:50:38 -07:00
|
|
|
return m_joystickAxes[stick].m_count;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the number of POVs on a given joystick port.
|
|
|
|
|
*
|
|
|
|
|
* @param stick The joystick port number
|
|
|
|
|
* @return The number of POVs on the indicated joystick
|
|
|
|
|
*/
|
|
|
|
|
public int getStickPOVCount(int stick) {
|
|
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-5");
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
|
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
2016-07-14 20:50:38 -07:00
|
|
|
return m_joystickPOVs[stick].m_count;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Gets the number of buttons on a joystick.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @param stick The joystick port number
|
|
|
|
|
* @return The number of buttons on the indicated joystick
|
|
|
|
|
*/
|
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
|
|
|
public int getStickButtonCount(int stick) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-5");
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
|
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
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].m_count;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
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
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Gets the value of isXbox on a joystick.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @param stick The joystick port number
|
|
|
|
|
* @return A boolean that returns the value of isXbox
|
|
|
|
|
*/
|
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
|
|
|
public boolean getJoystickIsXbox(int stick) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-5");
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
|
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
|
|
|
|
return HAL.getJoystickIsXbox((byte) stick) == 1;
|
|
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Gets the value of type on a joystick.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @param stick The joystick port number
|
|
|
|
|
* @return The value of type
|
|
|
|
|
*/
|
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
|
|
|
public int getJoystickType(int stick) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-5");
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
|
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
|
|
|
|
return HAL.getJoystickType((byte) stick);
|
|
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Gets the name of the joystick at a port.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @param stick The joystick port number
|
|
|
|
|
* @return The value of name
|
|
|
|
|
*/
|
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
|
|
|
public String getJoystickName(int stick) {
|
2015-06-25 15:07:55 -04:00
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-5");
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2018-05-16 00:13:52 -07:00
|
|
|
|
|
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
|
|
|
|
return HAL.getJoystickName((byte) stick);
|
|
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-07 08:19:19 -07:00
|
|
|
/**
|
|
|
|
|
* Returns the types of Axes on a given joystick port.
|
|
|
|
|
*
|
|
|
|
|
* @param stick The joystick port number
|
|
|
|
|
* @param axis The target axis
|
|
|
|
|
* @return What type of axis the axis is reporting to be
|
|
|
|
|
*/
|
|
|
|
|
public int getJoystickAxisType(int stick, int axis) {
|
|
|
|
|
if (stick < 0 || stick >= kJoystickPorts) {
|
2018-06-03 10:00:53 -07:00
|
|
|
throw new IllegalArgumentException("Joystick index is out of range, should be 0-5");
|
2016-08-07 08:19:19 -07:00
|
|
|
}
|
|
|
|
|
|
2018-05-16 00:13:52 -07:00
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
|
|
|
|
return HAL.getJoystickAxisType((byte) stick, (byte) axis);
|
|
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2016-08-07 08:19:19 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Gets a value indicating whether the Driver Station requires the robot to be enabled.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @return True if the robot is enabled, false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isEnabled() {
|
2016-07-15 13:39:26 -07:00
|
|
|
synchronized (m_controlWordMutex) {
|
|
|
|
|
updateControlWord(false);
|
|
|
|
|
return m_controlWordCache.getEnabled() && m_controlWordCache.getDSAttached();
|
|
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Gets a value indicating whether the Driver Station requires the robot to be disabled.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @return True if the robot should be disabled, false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isDisabled() {
|
|
|
|
|
return !isEnabled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Gets a value indicating whether the Driver Station requires the robot to be running in
|
|
|
|
|
* autonomous mode.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @return True if autonomous mode should be enabled, false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isAutonomous() {
|
2016-07-15 13:39:26 -07:00
|
|
|
synchronized (m_controlWordMutex) {
|
|
|
|
|
updateControlWord(false);
|
|
|
|
|
return m_controlWordCache.getAutonomous();
|
|
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
/**
|
|
|
|
|
* Gets a value indicating whether the Driver Station requires the robot to be running in
|
|
|
|
|
* operator-controlled mode.
|
|
|
|
|
*
|
|
|
|
|
* @return True if operator-controlled mode should be enabled, false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isOperatorControl() {
|
|
|
|
|
return !(isAutonomous() || isTest());
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Gets a value indicating whether the Driver Station requires the robot to be running in test
|
|
|
|
|
* mode.
|
|
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return True if test mode should be enabled, false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isTest() {
|
2016-07-15 13:39:26 -07:00
|
|
|
synchronized (m_controlWordMutex) {
|
|
|
|
|
updateControlWord(false);
|
|
|
|
|
return m_controlWordCache.getTest();
|
|
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-07-14 20:50:38 -07:00
|
|
|
* Gets a value indicating whether the Driver Station is attached.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
2016-07-14 20:50:38 -07:00
|
|
|
* @return True if Driver Station is attached, false otherwise.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2016-07-14 20:50:38 -07:00
|
|
|
public boolean isDSAttached() {
|
2016-07-15 13:39:26 -07:00
|
|
|
synchronized (m_controlWordMutex) {
|
|
|
|
|
updateControlWord(false);
|
|
|
|
|
return m_controlWordCache.getDSAttached();
|
|
|
|
|
}
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-07-28 22:24:05 -07:00
|
|
|
* Gets if a new control packet from the driver station arrived since the last time this function
|
|
|
|
|
* was called.
|
2016-07-14 20:50:38 -07:00
|
|
|
*
|
|
|
|
|
* @return True if the control data has been updated since the last call.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isNewControlData() {
|
2017-05-08 20:21:47 -07:00
|
|
|
return HAL.isNewControlData();
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-07-28 22:24:05 -07:00
|
|
|
* Gets if the driver station attached to a Field Management System.
|
2016-07-14 20:50:38 -07:00
|
|
|
*
|
2017-07-28 22:24:05 -07:00
|
|
|
* @return true if the robot is competing on a field being controlled by a Field Management System
|
2016-07-14 20:50:38 -07:00
|
|
|
*/
|
|
|
|
|
public boolean isFMSAttached() {
|
2016-07-15 13:39:26 -07:00
|
|
|
synchronized (m_controlWordMutex) {
|
|
|
|
|
updateControlWord(false);
|
|
|
|
|
return m_controlWordCache.getFMSAttached();
|
|
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Gets a value indicating whether the FPGA outputs are enabled. The outputs may be disabled if
|
2017-10-27 03:44:51 -04:00
|
|
|
* the robot is disabled or e-stopped, the watchdog has expired, or if the roboRIO browns out.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
|
|
|
|
* @return True if the FPGA outputs are enabled.
|
2017-12-10 21:52:49 -08:00
|
|
|
* @deprecated Use RobotController.isSysActive()
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2017-12-10 21:52:49 -08:00
|
|
|
@Deprecated
|
2015-06-25 15:07:55 -04:00
|
|
|
public boolean isSysActive() {
|
2016-07-10 16:24:57 -07:00
|
|
|
return HAL.getSystemActive();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Check if the system is browned out.
|
2016-05-20 12:07:40 -04:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return True if the system is browned out
|
2017-12-10 21:52:49 -08:00
|
|
|
* @deprecated Use RobotController.isBrownedOut()
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2017-12-10 21:52:49 -08:00
|
|
|
@Deprecated
|
2015-06-25 15:07:55 -04:00
|
|
|
public boolean isBrownedOut() {
|
2016-07-10 16:24:57 -07:00
|
|
|
return HAL.getBrownedOut();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2017-11-09 19:59:29 -08:00
|
|
|
/**
|
|
|
|
|
* Get the game specific message.
|
|
|
|
|
*
|
|
|
|
|
* @return the game specific message
|
|
|
|
|
*/
|
|
|
|
|
public String getGameSpecificMessage() {
|
2018-05-16 00:13:52 -07:00
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
2017-11-09 19:59:29 -08:00
|
|
|
return m_matchInfo.gameSpecificMessage;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the event name.
|
|
|
|
|
*
|
|
|
|
|
* @return the event name
|
|
|
|
|
*/
|
|
|
|
|
public String getEventName() {
|
2018-05-16 00:13:52 -07:00
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
2017-11-09 19:59:29 -08:00
|
|
|
return m_matchInfo.eventName;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the match type.
|
|
|
|
|
*
|
|
|
|
|
* @return the match type
|
|
|
|
|
*/
|
|
|
|
|
public MatchType getMatchType() {
|
|
|
|
|
int matchType;
|
2018-05-16 00:13:52 -07:00
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
2017-11-09 19:59:29 -08:00
|
|
|
matchType = m_matchInfo.matchType;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
switch (matchType) {
|
|
|
|
|
case 1:
|
|
|
|
|
return MatchType.Practice;
|
|
|
|
|
case 2:
|
|
|
|
|
return MatchType.Qualification;
|
|
|
|
|
case 3:
|
|
|
|
|
return MatchType.Elimination;
|
|
|
|
|
default:
|
|
|
|
|
return MatchType.None;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the match number.
|
|
|
|
|
*
|
|
|
|
|
* @return the match number
|
|
|
|
|
*/
|
|
|
|
|
public int getMatchNumber() {
|
2018-05-16 00:13:52 -07:00
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
2017-11-09 19:59:29 -08:00
|
|
|
return m_matchInfo.matchNumber;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the replay number.
|
|
|
|
|
*
|
|
|
|
|
* @return the replay number
|
|
|
|
|
*/
|
|
|
|
|
public int getReplayNumber() {
|
2018-05-16 00:13:52 -07:00
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
2017-11-09 19:59:29 -08:00
|
|
|
return m_matchInfo.replayNumber;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2017-11-09 19:59:29 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Get the current alliance from the FMS.
|
|
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return the current alliance
|
|
|
|
|
*/
|
|
|
|
|
public Alliance getAlliance() {
|
2016-07-10 16:24:57 -07:00
|
|
|
AllianceStationID allianceStationID = HAL.getAllianceStation();
|
2015-06-25 15:07:55 -04:00
|
|
|
if (allianceStationID == null) {
|
|
|
|
|
return Alliance.Invalid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (allianceStationID) {
|
|
|
|
|
case Red1:
|
|
|
|
|
case Red2:
|
|
|
|
|
case Red3:
|
|
|
|
|
return Alliance.Red;
|
|
|
|
|
|
|
|
|
|
case Blue1:
|
|
|
|
|
case Blue2:
|
|
|
|
|
case Blue3:
|
|
|
|
|
return Alliance.Blue;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return Alliance.Invalid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the location of the team's driver station controls.
|
|
|
|
|
*
|
|
|
|
|
* @return the location of the team's driver station controls: 1, 2, or 3
|
|
|
|
|
*/
|
|
|
|
|
public int getLocation() {
|
2016-07-10 16:24:57 -07:00
|
|
|
AllianceStationID allianceStationID = HAL.getAllianceStation();
|
2015-06-25 15:07:55 -04:00
|
|
|
if (allianceStationID == null) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
switch (allianceStationID) {
|
|
|
|
|
case Red1:
|
|
|
|
|
case Blue1:
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
case Red2:
|
|
|
|
|
case Blue2:
|
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
|
|
case Blue3:
|
|
|
|
|
case Red3:
|
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-07-14 20:50:38 -07:00
|
|
|
* Wait for new data from the driver station.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2016-07-14 20:50:38 -07:00
|
|
|
public void waitForData() {
|
|
|
|
|
waitForData(0);
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
/**
|
|
|
|
|
* Wait for new data or for timeout, which ever comes first. If timeout is 0, wait for new data
|
|
|
|
|
* only.
|
|
|
|
|
*
|
2016-10-09 11:46:01 -07:00
|
|
|
* @param timeout The maximum time in seconds to wait.
|
|
|
|
|
* @return true if there is new data, otherwise false
|
2016-07-14 20:50:38 -07:00
|
|
|
*/
|
2016-10-09 11:46:01 -07:00
|
|
|
public boolean waitForData(double timeout) {
|
2018-01-18 21:54:33 -08:00
|
|
|
long startTime = RobotController.getFPGATime();
|
|
|
|
|
long timeoutMicros = (long) (timeout * 1000000);
|
|
|
|
|
m_waitForDataMutex.lock();
|
|
|
|
|
try {
|
|
|
|
|
int currentCount = m_waitForDataCount;
|
|
|
|
|
while (m_waitForDataCount == currentCount) {
|
|
|
|
|
if (timeout > 0) {
|
|
|
|
|
long now = RobotController.getFPGATime();
|
|
|
|
|
if (now < startTime + timeoutMicros) {
|
|
|
|
|
// We still have time to wait
|
|
|
|
|
boolean signaled = m_waitForDataCond.await(startTime + timeoutMicros - now,
|
|
|
|
|
TimeUnit.MICROSECONDS);
|
|
|
|
|
if (!signaled) {
|
|
|
|
|
// Return false if a timeout happened
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Time has elapsed.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
m_waitForDataCond.await();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Return true if we have received a proper signal
|
|
|
|
|
return true;
|
|
|
|
|
} catch (InterruptedException ex) {
|
|
|
|
|
// return false on a thread interrupt
|
|
|
|
|
return false;
|
|
|
|
|
} finally {
|
|
|
|
|
m_waitForDataMutex.unlock();
|
|
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-11-23 00:19:05 -08:00
|
|
|
* Return the approximate match time. The FMS does not send an official match time to the robots,
|
2016-05-20 12:07:40 -04:00
|
|
|
* but does send an approximate match time. The value will count down the time remaining in the
|
|
|
|
|
* current period (auto or teleop). Warning: This is not an official time (so it cannot be used to
|
|
|
|
|
* dispute ref calls or guarantee that a function will trigger before the match ends) The
|
|
|
|
|
* Practice Match function of the DS approximates the behaviour seen on the field.
|
|
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return Time remaining in current match period (auto or teleop) in seconds
|
|
|
|
|
*/
|
|
|
|
|
public double getMatchTime() {
|
2016-07-10 16:24:57 -07:00
|
|
|
return HAL.getMatchTime();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-07-14 20:50:38 -07:00
|
|
|
* Read the battery voltage.
|
2016-05-20 12:07:40 -04:00
|
|
|
*
|
2016-07-14 20:50:38 -07:00
|
|
|
* @return The battery voltage in Volts.
|
2017-12-10 21:52:49 -08:00
|
|
|
* @deprecated Use RobotController.getBatteryVoltage
|
2016-02-04 22:29:11 -08:00
|
|
|
*/
|
2017-12-10 21:52:49 -08:00
|
|
|
@Deprecated
|
2016-07-14 20:50:38 -07:00
|
|
|
public double getBatteryVoltage() {
|
|
|
|
|
return PowerJNI.getVinVoltage();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Only to be used to tell the Driver Station what code you claim to be executing for diagnostic
|
|
|
|
|
* purposes only.
|
|
|
|
|
*
|
|
|
|
|
* @param entering If true, starting disabled code; if false, leaving disabled code
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2016-05-20 12:07:40 -04:00
|
|
|
@SuppressWarnings("MethodName")
|
2015-06-25 15:07:55 -04:00
|
|
|
public void InDisabled(boolean entering) {
|
|
|
|
|
m_userInDisabled = entering;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Only to be used to tell the Driver Station what code you claim to be executing for diagnostic
|
|
|
|
|
* purposes only.
|
|
|
|
|
*
|
|
|
|
|
* @param entering If true, starting autonomous code; if false, leaving autonomous code
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2016-05-20 12:07:40 -04:00
|
|
|
@SuppressWarnings("MethodName")
|
2015-06-25 15:07:55 -04:00
|
|
|
public void InAutonomous(boolean entering) {
|
|
|
|
|
m_userInAutonomous = entering;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Only to be used to tell the Driver Station what code you claim to be executing for diagnostic
|
|
|
|
|
* purposes only.
|
|
|
|
|
*
|
|
|
|
|
* @param entering If true, starting teleop code; if false, leaving teleop code
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
2016-05-20 12:07:40 -04:00
|
|
|
@SuppressWarnings("MethodName")
|
2015-06-25 15:07:55 -04:00
|
|
|
public void InOperatorControl(boolean entering) {
|
|
|
|
|
m_userInTeleop = entering;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Only to be used to tell the Driver Station what code you claim to be executing for diagnostic
|
|
|
|
|
* purposes only.
|
|
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @param entering If true, starting test code; if false, leaving test code
|
|
|
|
|
*/
|
2016-05-20 12:07:40 -04:00
|
|
|
@SuppressWarnings("MethodName")
|
2015-06-25 15:07:55 -04:00
|
|
|
public void InTest(boolean entering) {
|
|
|
|
|
m_userInTest = entering;
|
|
|
|
|
}
|
2016-07-14 20:50:38 -07:00
|
|
|
|
2018-01-18 23:17:28 -08:00
|
|
|
private void sendMatchData() {
|
|
|
|
|
AllianceStationID alliance = HAL.getAllianceStation();
|
|
|
|
|
boolean isRedAlliance = false;
|
|
|
|
|
int stationNumber = 1;
|
|
|
|
|
switch (alliance) {
|
|
|
|
|
case Blue1:
|
|
|
|
|
isRedAlliance = false;
|
|
|
|
|
stationNumber = 1;
|
|
|
|
|
break;
|
|
|
|
|
case Blue2:
|
|
|
|
|
isRedAlliance = false;
|
|
|
|
|
stationNumber = 2;
|
|
|
|
|
break;
|
|
|
|
|
case Blue3:
|
|
|
|
|
isRedAlliance = false;
|
|
|
|
|
stationNumber = 3;
|
|
|
|
|
break;
|
|
|
|
|
case Red1:
|
|
|
|
|
isRedAlliance = true;
|
|
|
|
|
stationNumber = 1;
|
|
|
|
|
break;
|
|
|
|
|
case Red2:
|
|
|
|
|
isRedAlliance = true;
|
|
|
|
|
stationNumber = 2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
isRedAlliance = true;
|
|
|
|
|
stationNumber = 3;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String eventName;
|
|
|
|
|
String gameSpecificMessage;
|
|
|
|
|
int matchNumber;
|
|
|
|
|
int replayNumber;
|
|
|
|
|
int matchType;
|
|
|
|
|
synchronized (m_cacheDataMutex) {
|
|
|
|
|
eventName = m_matchInfo.eventName;
|
|
|
|
|
gameSpecificMessage = m_matchInfo.gameSpecificMessage;
|
|
|
|
|
matchNumber = m_matchInfo.matchNumber;
|
|
|
|
|
replayNumber = m_matchInfo.replayNumber;
|
|
|
|
|
matchType = m_matchInfo.matchType;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_matchDataSender.alliance.setBoolean(isRedAlliance);
|
|
|
|
|
m_matchDataSender.station.setDouble(stationNumber);
|
|
|
|
|
m_matchDataSender.eventName.setString(eventName);
|
|
|
|
|
m_matchDataSender.gameSpecificMessage.setString(gameSpecificMessage);
|
|
|
|
|
m_matchDataSender.matchNumber.setDouble(matchNumber);
|
|
|
|
|
m_matchDataSender.replayNumber.setDouble(replayNumber);
|
|
|
|
|
m_matchDataSender.matchType.setDouble(matchType);
|
|
|
|
|
m_matchDataSender.controlWord.setDouble(HAL.nativeGetControlWord());
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
/**
|
|
|
|
|
* Copy data from the DS task for the user. If no new data exists, it will just be returned,
|
|
|
|
|
* otherwise the data will be copied from the DS polling loop.
|
|
|
|
|
*/
|
|
|
|
|
protected void getData() {
|
|
|
|
|
// Get the status of all of the joysticks
|
|
|
|
|
for (byte stick = 0; stick < kJoystickPorts; stick++) {
|
|
|
|
|
m_joystickAxesCache[stick].m_count =
|
|
|
|
|
HAL.getJoystickAxes(stick, m_joystickAxesCache[stick].m_axes);
|
|
|
|
|
m_joystickPOVsCache[stick].m_count =
|
|
|
|
|
HAL.getJoystickPOVs(stick, m_joystickPOVsCache[stick].m_povs);
|
|
|
|
|
m_joystickButtonsCache[stick].m_buttons = HAL.getJoystickButtons(stick, m_buttonCountBuffer);
|
|
|
|
|
m_joystickButtonsCache[stick].m_count = m_buttonCountBuffer.get(0);
|
|
|
|
|
}
|
2017-11-09 19:59:29 -08:00
|
|
|
|
|
|
|
|
HAL.getMatchInfo(m_matchInfoCache);
|
|
|
|
|
|
2016-07-15 13:39:26 -07:00
|
|
|
// Force a control word update, to make sure the data is the newest.
|
|
|
|
|
updateControlWord(true);
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
// lock joystick mutex to swap cache data
|
2018-05-16 00:13:52 -07:00
|
|
|
m_cacheDataMutex.lock();
|
|
|
|
|
try {
|
2017-10-27 21:45:56 -07:00
|
|
|
for (int i = 0; i < kJoystickPorts; i++) {
|
|
|
|
|
// If buttons weren't pressed and are now, set flags in m_buttonsPressed
|
2018-05-17 13:00:48 +10:00
|
|
|
m_joystickButtonsPressed[i] |=
|
2017-10-27 21:45:56 -07:00
|
|
|
~m_joystickButtons[i].m_buttons & m_joystickButtonsCache[i].m_buttons;
|
|
|
|
|
|
|
|
|
|
// If buttons were pressed and aren't now, set flags in m_buttonsReleased
|
2018-05-17 13:00:48 +10:00
|
|
|
m_joystickButtonsReleased[i] |=
|
2017-10-27 21:45:56 -07:00
|
|
|
m_joystickButtons[i].m_buttons & ~m_joystickButtonsCache[i].m_buttons;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-14 20:50:38 -07:00
|
|
|
// move cache to actual data
|
|
|
|
|
HALJoystickAxes[] currentAxes = m_joystickAxes;
|
|
|
|
|
m_joystickAxes = m_joystickAxesCache;
|
|
|
|
|
m_joystickAxesCache = currentAxes;
|
|
|
|
|
|
|
|
|
|
HALJoystickButtons[] currentButtons = m_joystickButtons;
|
|
|
|
|
m_joystickButtons = m_joystickButtonsCache;
|
|
|
|
|
m_joystickButtonsCache = currentButtons;
|
|
|
|
|
|
|
|
|
|
HALJoystickPOVs[] currentPOVs = m_joystickPOVs;
|
|
|
|
|
m_joystickPOVs = m_joystickPOVsCache;
|
|
|
|
|
m_joystickPOVsCache = currentPOVs;
|
2017-11-09 19:59:29 -08:00
|
|
|
|
|
|
|
|
MatchInfoData currentInfo = m_matchInfo;
|
|
|
|
|
m_matchInfo = m_matchInfoCache;
|
|
|
|
|
m_matchInfoCache = currentInfo;
|
2018-05-16 00:13:52 -07:00
|
|
|
} finally {
|
|
|
|
|
m_cacheDataMutex.unlock();
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
2018-01-18 21:54:33 -08:00
|
|
|
|
|
|
|
|
m_waitForDataMutex.lock();
|
|
|
|
|
m_waitForDataCount++;
|
|
|
|
|
m_waitForDataCond.signalAll();
|
|
|
|
|
m_waitForDataMutex.unlock();
|
2018-01-18 23:17:28 -08:00
|
|
|
|
|
|
|
|
sendMatchData();
|
2016-07-14 20:50:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reports errors related to unplugged joysticks Throttles the errors so that they don't overwhelm
|
|
|
|
|
* the DS.
|
|
|
|
|
*/
|
|
|
|
|
private void reportJoystickUnpluggedError(String message) {
|
|
|
|
|
double currentTime = Timer.getFPGATimestamp();
|
|
|
|
|
if (currentTime > m_nextMessageTime) {
|
|
|
|
|
reportError(message, false);
|
|
|
|
|
m_nextMessageTime = currentTime + JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reports errors related to unplugged joysticks Throttles the errors so that they don't overwhelm
|
|
|
|
|
* the DS.
|
|
|
|
|
*/
|
|
|
|
|
private void reportJoystickUnpluggedWarning(String message) {
|
|
|
|
|
double currentTime = Timer.getFPGATimestamp();
|
|
|
|
|
if (currentTime > m_nextMessageTime) {
|
|
|
|
|
reportWarning(message, false);
|
|
|
|
|
m_nextMessageTime = currentTime + JOYSTICK_UNPLUGGED_MESSAGE_INTERVAL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Provides the service routine for the DS polling m_thread.
|
|
|
|
|
*/
|
|
|
|
|
private void run() {
|
|
|
|
|
int safetyCounter = 0;
|
|
|
|
|
while (m_threadKeepAlive) {
|
|
|
|
|
HAL.waitForDSData();
|
|
|
|
|
getData();
|
2016-10-24 20:32:43 -07:00
|
|
|
|
2017-11-23 00:36:57 -08:00
|
|
|
if (isDisabled()) {
|
|
|
|
|
safetyCounter = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-03 10:00:53 -07:00
|
|
|
safetyCounter++;
|
|
|
|
|
if (safetyCounter >= 4) {
|
2016-07-14 20:50:38 -07:00
|
|
|
MotorSafetyHelper.checkMotors();
|
|
|
|
|
safetyCounter = 0;
|
|
|
|
|
}
|
|
|
|
|
if (m_userInDisabled) {
|
|
|
|
|
HAL.observeUserProgramDisabled();
|
|
|
|
|
}
|
|
|
|
|
if (m_userInAutonomous) {
|
|
|
|
|
HAL.observeUserProgramAutonomous();
|
|
|
|
|
}
|
|
|
|
|
if (m_userInTeleop) {
|
|
|
|
|
HAL.observeUserProgramTeleop();
|
|
|
|
|
}
|
|
|
|
|
if (m_userInTest) {
|
|
|
|
|
HAL.observeUserProgramTest();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-07-15 13:39:26 -07:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Updates the data in the control word cache. Updates if the force parameter is set, or if
|
|
|
|
|
* 50ms have passed since the last update.
|
|
|
|
|
*
|
|
|
|
|
* @param force True to force an update to the cache, otherwise update if 50ms have passed.
|
|
|
|
|
*/
|
|
|
|
|
private void updateControlWord(boolean force) {
|
|
|
|
|
long now = System.currentTimeMillis();
|
|
|
|
|
synchronized (m_controlWordMutex) {
|
2016-12-08 00:24:44 -05:00
|
|
|
if (now - m_lastControlWordUpdate > 50 || force) {
|
2016-07-15 13:39:26 -07:00
|
|
|
HAL.getControlWord(m_controlWordCache);
|
2016-09-13 21:22:25 -07:00
|
|
|
m_lastControlWordUpdate = now;
|
2016-07-15 13:39:26 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|