2020-12-26 14:12:05 -08:00
|
|
|
// 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.
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
package edu.wpi.first.wpilibj;
|
|
|
|
|
|
2018-09-23 21:20:12 -07:00
|
|
|
import edu.wpi.first.cameraserver.CameraServerShared;
|
|
|
|
|
import edu.wpi.first.cameraserver.CameraServerSharedStore;
|
2021-04-10 11:42:41 -07:00
|
|
|
import edu.wpi.first.cscore.CameraServerJNI;
|
2018-09-20 21:59:46 -07:00
|
|
|
import edu.wpi.first.hal.FRCNetComm.tInstances;
|
|
|
|
|
import edu.wpi.first.hal.FRCNetComm.tResourceType;
|
|
|
|
|
import edu.wpi.first.hal.HAL;
|
|
|
|
|
import edu.wpi.first.hal.HALUtil;
|
2020-08-06 23:57:39 -07:00
|
|
|
import edu.wpi.first.math.MathShared;
|
|
|
|
|
import edu.wpi.first.math.MathSharedStore;
|
|
|
|
|
import edu.wpi.first.math.MathUsageId;
|
2017-08-28 00:32:53 -07:00
|
|
|
import edu.wpi.first.networktables.NetworkTableInstance;
|
2017-07-08 10:50:56 -04:00
|
|
|
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
2018-09-28 04:18:18 -04:00
|
|
|
import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard;
|
2016-10-20 23:54:04 -07:00
|
|
|
import edu.wpi.first.wpilibj.util.WPILibVersion;
|
2020-12-29 22:45:16 -08:00
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.io.OutputStream;
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
|
import java.nio.file.Files;
|
|
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
|
import java.util.function.Supplier;
|
2013-12-15 18:30:16 -05:00
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Implement a Robot Program framework. The RobotBase class is intended to be subclassed by a user
|
|
|
|
|
* creating a robot program. Overridden autonomous() and operatorControl() methods are called at the
|
|
|
|
|
* appropriate time as the match proceeds. In the current implementation, the Autonomous code will
|
|
|
|
|
* run to completion before the OperatorControl code could start. In the future the Autonomous code
|
|
|
|
|
* might be spawned as a task, then killed at the end of the Autonomous period.
|
2013-12-15 18:30:16 -05:00
|
|
|
*/
|
2018-05-22 23:33:17 -07:00
|
|
|
public abstract class RobotBase implements AutoCloseable {
|
2020-12-29 22:45:16 -08:00
|
|
|
/** The ID of the main Java thread. */
|
2016-12-23 11:48:56 -05:00
|
|
|
// This is usually 1, but it is best to make sure
|
2019-10-07 20:45:33 -07:00
|
|
|
private static long m_threadId = -1;
|
2016-12-23 11:48:56 -05:00
|
|
|
|
2018-04-29 13:29:07 -07:00
|
|
|
private static void setupCameraServerShared() {
|
2020-12-29 22:45:16 -08:00
|
|
|
CameraServerShared shared =
|
|
|
|
|
new CameraServerShared() {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void reportVideoServer(int id) {
|
|
|
|
|
HAL.report(tResourceType.kResourceType_PCVideoServer, id + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void reportUsbCamera(int id) {
|
|
|
|
|
HAL.report(tResourceType.kResourceType_UsbCamera, id + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void reportDriverStationError(String error) {
|
|
|
|
|
DriverStation.reportError(error, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void reportAxisCamera(int id) {
|
|
|
|
|
HAL.report(tResourceType.kResourceType_AxisCamera, id + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Long getRobotMainThreadId() {
|
|
|
|
|
return RobotBase.getMainThreadId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean isRoboRIO() {
|
|
|
|
|
return RobotBase.isReal();
|
|
|
|
|
}
|
|
|
|
|
};
|
2018-04-29 13:29:07 -07:00
|
|
|
|
|
|
|
|
CameraServerSharedStore.setCameraServerShared(shared);
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-06 23:57:39 -07:00
|
|
|
private static void setupMathShared() {
|
2020-12-29 22:45:16 -08:00
|
|
|
MathSharedStore.setMathShared(
|
|
|
|
|
new MathShared() {
|
|
|
|
|
@Override
|
|
|
|
|
public void reportError(String error, StackTraceElement[] stackTrace) {
|
|
|
|
|
DriverStation.reportError(error, stackTrace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void reportUsage(MathUsageId id, int count) {
|
|
|
|
|
switch (id) {
|
|
|
|
|
case kKinematics_DifferentialDrive:
|
|
|
|
|
HAL.report(
|
|
|
|
|
tResourceType.kResourceType_Kinematics,
|
|
|
|
|
tInstances.kKinematics_DifferentialDrive);
|
|
|
|
|
break;
|
|
|
|
|
case kKinematics_MecanumDrive:
|
|
|
|
|
HAL.report(
|
|
|
|
|
tResourceType.kResourceType_Kinematics, tInstances.kKinematics_MecanumDrive);
|
|
|
|
|
break;
|
|
|
|
|
case kKinematics_SwerveDrive:
|
|
|
|
|
HAL.report(
|
|
|
|
|
tResourceType.kResourceType_Kinematics, tInstances.kKinematics_SwerveDrive);
|
|
|
|
|
break;
|
|
|
|
|
case kTrajectory_TrapezoidProfile:
|
|
|
|
|
HAL.report(tResourceType.kResourceType_TrapezoidProfile, count);
|
|
|
|
|
break;
|
|
|
|
|
case kFilter_Linear:
|
|
|
|
|
HAL.report(tResourceType.kResourceType_LinearFilter, count);
|
|
|
|
|
break;
|
|
|
|
|
case kOdometry_DifferentialDrive:
|
|
|
|
|
HAL.report(
|
|
|
|
|
tResourceType.kResourceType_Odometry, tInstances.kOdometry_DifferentialDrive);
|
|
|
|
|
break;
|
|
|
|
|
case kOdometry_SwerveDrive:
|
|
|
|
|
HAL.report(tResourceType.kResourceType_Odometry, tInstances.kOdometry_SwerveDrive);
|
|
|
|
|
break;
|
|
|
|
|
case kOdometry_MecanumDrive:
|
|
|
|
|
HAL.report(tResourceType.kResourceType_Odometry, tInstances.kOdometry_MecanumDrive);
|
|
|
|
|
break;
|
2021-06-16 17:45:51 +03:00
|
|
|
case kController_PIDController2:
|
|
|
|
|
HAL.report(tResourceType.kResourceType_PIDController2, count);
|
|
|
|
|
break;
|
|
|
|
|
case kController_ProfiledPIDController:
|
|
|
|
|
HAL.report(tResourceType.kResourceType_ProfiledPIDController, count);
|
|
|
|
|
break;
|
2020-12-29 22:45:16 -08:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2020-08-06 23:57:39 -07:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Constructor for a generic robot program. User code should be placed in the constructor that
|
|
|
|
|
* runs before the Autonomous or Operator Control period starts. The constructor will run to
|
|
|
|
|
* completion before Autonomous is entered.
|
2015-06-25 15:07:55 -04:00
|
|
|
*
|
2016-05-20 12:07:40 -04:00
|
|
|
* <p>This must be used to ensure that the communications code starts. In the future it would be
|
2020-12-29 22:45:16 -08:00
|
|
|
* nice to put this code into it's own task that loads on boot so ensure that it runs.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
|
|
|
|
protected RobotBase() {
|
2020-08-06 23:57:39 -07:00
|
|
|
final NetworkTableInstance inst = NetworkTableInstance.getDefault();
|
2019-10-07 20:45:33 -07:00
|
|
|
m_threadId = Thread.currentThread().getId();
|
2018-04-29 13:29:07 -07:00
|
|
|
setupCameraServerShared();
|
2020-08-06 23:57:39 -07:00
|
|
|
setupMathShared();
|
2017-08-28 00:32:53 -07:00
|
|
|
inst.setNetworkIdentity("Robot");
|
2019-12-29 18:55:02 -06:00
|
|
|
if (isReal()) {
|
|
|
|
|
inst.startServer("/home/lvuser/networktables.ini");
|
|
|
|
|
} else {
|
|
|
|
|
inst.startServer();
|
|
|
|
|
}
|
2017-10-11 23:27:49 -04:00
|
|
|
inst.getTable("LiveWindow").getSubTable(".status").getEntry("LW Enabled").setBoolean(false);
|
2017-07-08 10:50:56 -04:00
|
|
|
|
|
|
|
|
LiveWindow.setEnabled(false);
|
2018-09-28 04:18:18 -04:00
|
|
|
Shuffleboard.disableActuatorWidgets();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2019-10-07 20:45:33 -07:00
|
|
|
public static long getMainThreadId() {
|
|
|
|
|
return m_threadId;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 23:33:17 -07:00
|
|
|
@Override
|
2020-12-29 22:45:16 -08:00
|
|
|
public void close() {}
|
2015-06-25 15:07:55 -04:00
|
|
|
|
|
|
|
|
/**
|
2017-07-28 22:24:05 -07:00
|
|
|
* Get if the robot is a simulation.
|
|
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return If the robot is running in simulation.
|
|
|
|
|
*/
|
|
|
|
|
public static boolean isSimulation() {
|
2017-09-23 10:56:53 -04:00
|
|
|
return !isReal();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-07-28 22:24:05 -07:00
|
|
|
* Get if the robot is real.
|
|
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return If the robot is running in the real world.
|
|
|
|
|
*/
|
|
|
|
|
public static boolean isReal() {
|
2017-09-23 10:56:53 -04:00
|
|
|
return HALUtil.getHALRuntimeType() == 0;
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Determine if the Robot is currently disabled.
|
2016-05-20 12:07:40 -04:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return True if the Robot is currently disabled by the field controls.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isDisabled() {
|
2021-06-15 23:06:03 -07:00
|
|
|
return DriverStation.isDisabled();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Determine if the Robot is currently enabled.
|
2016-05-20 12:07:40 -04:00
|
|
|
*
|
2015-06-25 15:07:55 -04:00
|
|
|
* @return True if the Robot is currently enabled by the field controls.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isEnabled() {
|
2021-06-15 23:06:03 -07:00
|
|
|
return DriverStation.isEnabled();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Determine if the robot is currently in Autonomous mode as determined by the field controls.
|
2016-05-20 12:07:40 -04:00
|
|
|
*
|
|
|
|
|
* @return True if the robot is currently operating Autonomously.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
|
|
|
|
public boolean isAutonomous() {
|
2021-06-15 23:06:03 -07:00
|
|
|
return DriverStation.isAutonomous();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2020-08-29 16:32:19 -04:00
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Determine if the robot is current in Autonomous mode and enabled as determined by the field
|
|
|
|
|
* controls.
|
2020-08-29 16:32:19 -04:00
|
|
|
*
|
|
|
|
|
* @return True if the robot is currently operating autonomously while enabled.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isAutonomousEnabled() {
|
2021-06-15 23:06:03 -07:00
|
|
|
return DriverStation.isAutonomousEnabled();
|
2020-08-29 16:32:19 -04:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Determine if the robot is currently in Test mode as determined by the driver station.
|
2016-05-20 12:07:40 -04:00
|
|
|
*
|
|
|
|
|
* @return True if the robot is currently operating in Test mode.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
|
|
|
|
public boolean isTest() {
|
2021-06-15 23:06:03 -07:00
|
|
|
return DriverStation.isTest();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2016-05-20 12:07:40 -04:00
|
|
|
* Determine if the robot is currently in Operator Control mode as determined by the field
|
|
|
|
|
* controls.
|
|
|
|
|
*
|
|
|
|
|
* @return True if the robot is currently operating in Tele-Op mode.
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
|
|
|
|
public boolean isOperatorControl() {
|
2021-06-15 23:06:03 -07:00
|
|
|
return DriverStation.isOperatorControl();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2020-08-29 16:32:19 -04:00
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Determine if the robot is current in Operator Control mode and enabled as determined by the
|
|
|
|
|
* field controls.
|
2020-08-29 16:32:19 -04:00
|
|
|
*
|
|
|
|
|
* @return True if the robot is currently operating in Tele-Op mode while enabled.
|
|
|
|
|
*/
|
|
|
|
|
public boolean isOperatorControlEnabled() {
|
2021-06-15 23:06:03 -07:00
|
|
|
return DriverStation.isOperatorControlEnabled();
|
2020-08-29 16:32:19 -04:00
|
|
|
}
|
|
|
|
|
|
2015-06-25 15:07:55 -04:00
|
|
|
/**
|
|
|
|
|
* Indicates if new data is available from the driver station.
|
2016-05-20 12:07:40 -04:00
|
|
|
*
|
|
|
|
|
* @return Has new data arrived over the network since the last time this function was called?
|
2015-06-25 15:07:55 -04:00
|
|
|
*/
|
|
|
|
|
public boolean isNewDataAvailable() {
|
2021-06-15 23:06:03 -07:00
|
|
|
return DriverStation.isNewControlData();
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
/** Provide an alternate "main loop" via startCompetition(). */
|
2015-06-25 15:07:55 -04:00
|
|
|
public abstract void startCompetition();
|
|
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
/** Ends the main loop in startCompetition(). */
|
2019-11-05 21:33:09 -08:00
|
|
|
public abstract void endCompetition();
|
|
|
|
|
|
2020-12-29 09:27:48 -08:00
|
|
|
@SuppressWarnings("MissingJavadocMethod")
|
2015-06-25 15:07:55 -04:00
|
|
|
public static boolean getBooleanProperty(String name, boolean defaultValue) {
|
|
|
|
|
String propVal = System.getProperty(name);
|
|
|
|
|
if (propVal == null) {
|
|
|
|
|
return defaultValue;
|
|
|
|
|
}
|
2018-06-03 10:00:53 -07:00
|
|
|
if ("false".equalsIgnoreCase(propVal)) {
|
2015-06-25 15:07:55 -04:00
|
|
|
return false;
|
2018-06-03 10:00:53 -07:00
|
|
|
} else if ("true".equalsIgnoreCase(propVal)) {
|
2015-06-25 15:07:55 -04:00
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
throw new IllegalStateException(propVal);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 21:33:09 -08:00
|
|
|
private static final ReentrantLock m_runMutex = new ReentrantLock();
|
|
|
|
|
private static RobotBase m_robotCopy;
|
|
|
|
|
private static boolean m_suppressExitWarning;
|
|
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
/** Run the robot main loop. */
|
2021-06-09 07:01:00 -07:00
|
|
|
@SuppressWarnings("PMD.AvoidCatchingThrowable")
|
2019-09-28 15:43:24 -07:00
|
|
|
private static <T extends RobotBase> void runRobot(Supplier<T> robotSupplier) {
|
2017-07-08 10:50:56 -04:00
|
|
|
System.out.println("********** Robot program starting **********");
|
|
|
|
|
|
2018-07-18 22:01:19 -07:00
|
|
|
T robot;
|
2015-06-25 15:07:55 -04:00
|
|
|
try {
|
2018-07-18 22:01:19 -07:00
|
|
|
robot = robotSupplier.get();
|
2016-05-20 12:07:40 -04:00
|
|
|
} catch (Throwable throwable) {
|
2017-10-30 21:50:14 -07:00
|
|
|
Throwable cause = throwable.getCause();
|
|
|
|
|
if (cause != null) {
|
|
|
|
|
throwable = cause;
|
|
|
|
|
}
|
2018-07-18 22:01:19 -07:00
|
|
|
String robotName = "Unknown";
|
|
|
|
|
StackTraceElement[] elements = throwable.getStackTrace();
|
|
|
|
|
if (elements.length > 0) {
|
|
|
|
|
robotName = elements[0].getClassName();
|
|
|
|
|
}
|
2020-12-29 22:45:16 -08:00
|
|
|
DriverStation.reportError(
|
|
|
|
|
"Unhandled exception instantiating robot " + robotName + " " + throwable.toString(),
|
|
|
|
|
elements);
|
2017-10-30 21:50:14 -07:00
|
|
|
DriverStation.reportWarning("Robots should not quit, but yours did!", false);
|
|
|
|
|
DriverStation.reportError("Could not instantiate robot " + robotName + "!", false);
|
2015-06-25 15:07:55 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 21:33:09 -08:00
|
|
|
m_runMutex.lock();
|
|
|
|
|
m_robotCopy = robot;
|
|
|
|
|
m_runMutex.unlock();
|
|
|
|
|
|
2018-12-26 22:59:49 -08:00
|
|
|
if (isReal()) {
|
|
|
|
|
try {
|
|
|
|
|
final File file = new File("/tmp/frc_versions/FRC_Lib_Version.ini");
|
2015-06-25 15:07:55 -04:00
|
|
|
|
2018-12-26 22:59:49 -08:00
|
|
|
if (file.exists()) {
|
|
|
|
|
file.delete();
|
|
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
|
2018-12-26 22:59:49 -08:00
|
|
|
file.createNewFile();
|
2015-06-25 15:07:55 -04:00
|
|
|
|
2018-12-26 22:59:49 -08:00
|
|
|
try (OutputStream output = Files.newOutputStream(file.toPath())) {
|
|
|
|
|
output.write("Java ".getBytes(StandardCharsets.UTF_8));
|
|
|
|
|
output.write(WPILibVersion.Version.getBytes(StandardCharsets.UTF_8));
|
|
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
|
2018-12-26 22:59:49 -08:00
|
|
|
} catch (IOException ex) {
|
2020-12-29 22:45:16 -08:00
|
|
|
DriverStation.reportError(
|
|
|
|
|
"Could not write FRC_Lib_Version.ini: " + ex.toString(), ex.getStackTrace());
|
2018-12-26 22:59:49 -08:00
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean errorOnExit = false;
|
|
|
|
|
try {
|
|
|
|
|
robot.startCompetition();
|
2016-05-20 12:07:40 -04:00
|
|
|
} catch (Throwable throwable) {
|
2017-10-30 21:50:14 -07:00
|
|
|
Throwable cause = throwable.getCause();
|
|
|
|
|
if (cause != null) {
|
|
|
|
|
throwable = cause;
|
|
|
|
|
}
|
2020-12-29 22:45:16 -08:00
|
|
|
DriverStation.reportError(
|
|
|
|
|
"Unhandled exception: " + throwable.toString(), throwable.getStackTrace());
|
2015-06-25 15:07:55 -04:00
|
|
|
errorOnExit = true;
|
|
|
|
|
} finally {
|
2019-11-05 21:33:09 -08:00
|
|
|
m_runMutex.lock();
|
|
|
|
|
boolean suppressExitWarning = m_suppressExitWarning;
|
|
|
|
|
m_runMutex.unlock();
|
|
|
|
|
if (!suppressExitWarning) {
|
|
|
|
|
// startCompetition never returns unless exception occurs....
|
|
|
|
|
DriverStation.reportWarning("Robots should not quit, but yours did!", false);
|
|
|
|
|
if (errorOnExit) {
|
|
|
|
|
DriverStation.reportError(
|
|
|
|
|
"The startCompetition() method (or methods called by it) should have "
|
2020-12-29 22:45:16 -08:00
|
|
|
+ "handled the exception above.",
|
|
|
|
|
false);
|
2019-11-05 21:33:09 -08:00
|
|
|
} else {
|
|
|
|
|
DriverStation.reportError("Unexpected return from startCompetition() method.", false);
|
|
|
|
|
}
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
|
|
|
|
}
|
2019-09-28 15:43:24 -07:00
|
|
|
}
|
|
|
|
|
|
2021-06-10 20:46:47 -07:00
|
|
|
/**
|
|
|
|
|
* Suppress the "Robots should not quit" message.
|
|
|
|
|
*
|
|
|
|
|
* @param value True if exit warning should be suppressed.
|
|
|
|
|
*/
|
2019-11-05 21:33:09 -08:00
|
|
|
public static void suppressExitWarning(boolean value) {
|
|
|
|
|
m_runMutex.lock();
|
|
|
|
|
m_suppressExitWarning = value;
|
|
|
|
|
m_runMutex.unlock();
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-10 20:46:47 -07:00
|
|
|
/**
|
|
|
|
|
* Starting point for the applications.
|
|
|
|
|
*
|
|
|
|
|
* @param <T> Robot subclass.
|
|
|
|
|
* @param robotSupplier Function that returns an instance of the robot subclass.
|
|
|
|
|
*/
|
2019-09-28 15:43:24 -07:00
|
|
|
public static <T extends RobotBase> void startRobot(Supplier<T> robotSupplier) {
|
|
|
|
|
if (!HAL.initialize(500, 0)) {
|
|
|
|
|
throw new IllegalStateException("Failed to initialize. Terminating");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Call a CameraServer JNI function to force OpenCV native library loading
|
|
|
|
|
// Needed because all the OpenCV JNI functions don't have built in loading
|
|
|
|
|
CameraServerJNI.enumerateSinks();
|
|
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
HAL.report(
|
|
|
|
|
tResourceType.kResourceType_Language, tInstances.kLanguage_Java, 0, WPILibVersion.Version);
|
2019-09-28 15:43:24 -07:00
|
|
|
|
|
|
|
|
if (HAL.hasMain()) {
|
2020-12-29 22:45:16 -08:00
|
|
|
Thread thread =
|
|
|
|
|
new Thread(
|
|
|
|
|
() -> {
|
|
|
|
|
runRobot(robotSupplier);
|
|
|
|
|
HAL.exitMain();
|
|
|
|
|
},
|
|
|
|
|
"robot main");
|
2019-09-28 15:43:24 -07:00
|
|
|
thread.setDaemon(true);
|
|
|
|
|
thread.start();
|
|
|
|
|
HAL.runMain();
|
2019-11-05 21:33:09 -08:00
|
|
|
suppressExitWarning(true);
|
|
|
|
|
m_runMutex.lock();
|
|
|
|
|
RobotBase robot = m_robotCopy;
|
|
|
|
|
m_runMutex.unlock();
|
|
|
|
|
if (robot != null) {
|
|
|
|
|
robot.endCompetition();
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
thread.join(1000);
|
|
|
|
|
} catch (InterruptedException ex) {
|
|
|
|
|
Thread.currentThread().interrupt();
|
|
|
|
|
}
|
2019-09-28 15:43:24 -07:00
|
|
|
} else {
|
|
|
|
|
runRobot(robotSupplier);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-04 08:59:26 -07:00
|
|
|
HAL.shutdown();
|
|
|
|
|
|
2020-08-31 00:34:34 -07:00
|
|
|
System.exit(0);
|
2015-06-25 15:07:55 -04:00
|
|
|
}
|
2013-12-15 18:30:16 -05:00
|
|
|
}
|