diff --git a/FtcRobotController/libs/FtcCommon-release.aar b/FtcRobotController/libs/FtcCommon-release.aar index 14bce7c2c84..275f93aa806 100644 Binary files a/FtcRobotController/libs/FtcCommon-release.aar and b/FtcRobotController/libs/FtcCommon-release.aar differ diff --git a/FtcRobotController/libs/Hardware-release.aar b/FtcRobotController/libs/Hardware-release.aar index 39e4e258d47..af2c1317dda 100644 Binary files a/FtcRobotController/libs/Hardware-release.aar and b/FtcRobotController/libs/Hardware-release.aar differ diff --git a/FtcRobotController/libs/RobotCore-release.aar b/FtcRobotController/libs/RobotCore-release.aar index 850a4be7cae..1e74367e43c 100644 Binary files a/FtcRobotController/libs/RobotCore-release.aar and b/FtcRobotController/libs/RobotCore-release.aar differ diff --git a/FtcRobotController/src/main/java/com/qualcomm/ftcrobotcontroller/FtcRobotControllerActivity.java b/FtcRobotController/src/main/java/com/qualcomm/ftcrobotcontroller/FtcRobotControllerActivity.java index bf4892d7cdc..5622950ac88 100644 --- a/FtcRobotController/src/main/java/com/qualcomm/ftcrobotcontroller/FtcRobotControllerActivity.java +++ b/FtcRobotController/src/main/java/com/qualcomm/ftcrobotcontroller/FtcRobotControllerActivity.java @@ -115,7 +115,6 @@ public class FtcRobotControllerActivity extends Activity { protected ImmersiveMode immersion; protected SwerveUpdateUIHook updateUI; - protected SwervePhoneNameVerifier nameVerifier; protected Dimmer dimmer; protected LinearLayout entireScreenLayout; @@ -218,7 +217,6 @@ public void onClick(View v) { updateUI.setTextViews(textWifiDirectStatus, textRobotStatus, textGamepad, textOpMode, textErrorMessage, textDeviceName); callback = updateUI.new CallbackHook(); - nameVerifier = new SwervePhoneNameVerifier(); PreferenceManager.setDefaultValues(this, R.xml.preferences, false); preferences = PreferenceManager.getDefaultSharedPreferences(this); @@ -546,11 +544,7 @@ public synchronized static void installIfNecessary(FtcRobotControllerService ser public void onStateChange(RobotState newState) { this.prevMonitor.onStateChange(newState); - RobotStateTransitionNotifier.onRobotStateChange(newState); - - if (newState == RobotState.RUNNING) - this.activity.nameVerifier.verifyLegalPhoneNames(); } @Override @@ -560,84 +554,6 @@ public void onErrorOrWarning() } } - class SwervePhoneNameVerifier - { - //------------------------------------------------------------------------------------------ - // State - //------------------------------------------------------------------------------------------ - - /* The rule about how robot controllers and driver stations are to be named is the following: - Each Team MUST “name” their Robot Controller with their official FTC Team - number and –RC (e.g. “1234-RC”). Each Team MUST “name” their Driver Station with - their official FTC Team number and –DS (e.g. 1234-DS). Spare Android devices - should be named with the Team number followed by a hyphen then a letter designation - beginning with “B” (e.g. “1234-B-RC”, “1234-C-RC”). - We're going to enforce that here. - */ - Pattern legalRCNamePattern = Pattern.compile("^\\d{1,5}(-[B-Z])?-RC", Pattern.CASE_INSENSITIVE); - Pattern legalDSNamePattern = Pattern.compile("^\\d{1,5}(-[B-Z])?-DS", Pattern.CASE_INSENSITIVE); - - // We match for all 'telephone's per the Wifi Simple Configuration Technical Specification v2.0.4. - // See Table 41 in that document. Example: "10-0050F204-5". - Pattern telephonePeerPattern = Pattern.compile("10-0050F204-\\d+", Pattern.CASE_INSENSITIVE); - - //------------------------------------------------------------------------------------------ - // Verification - //------------------------------------------------------------------------------------------ - - void verifyLegalPhoneNames() - { - if (controllerService != null) - { - WifiDirectAssistant assistant = controllerService.getWifiDirectAssistant(); - - // Check the robot controller name for legality. Sometimes, during startup, we get - // called back here before we can access the real RC name, so we check for the empty string. - String robotControllerName = assistant.getDeviceName(); - if (robotControllerName != "") - { - if (!legalRCNamePattern.matcher(robotControllerName).matches()) - { - reportWifiDirectError("\"%s\" is not a legal robot controller name (see )", robotControllerName); - } - } - - // We'd like to check all the peers as well, but some of them may not be actually - // the driver station but instead, e.g., development laptops. So we need to be a - // little careful. - for (WifiP2pDevice peer : assistant.getPeers()) - { - if (isDriverStation(peer)) - { - if (!legalDSNamePattern.matcher(peer.deviceName).matches()) - { - reportWifiDirectError("\"%s\" is not a legal driver station name (see )", peer.deviceName); - } - } - } - } - } - - //------------------------------------------------------------------------------------------ - // Utility - //------------------------------------------------------------------------------------------ - - /** Is this peer a driver station? If in doubt, answer 'no'*/ - boolean isDriverStation(WifiP2pDevice peer) - { - return this.telephonePeerPattern.matcher(peer.primaryDeviceType).matches(); - } - - void reportWifiDirectError(String format, Object... args) - { - String message = String.format(format, args); - // Show the message in the log - Log.w(LOGGING_TAG, String.format("wifi direct error: %s", message)); - // Make the message appear on the driver station (only the first one will actually appear) - RobotLog.setGlobalErrorMsg(message); - } - } - class SwerveUpdateUIHook extends UpdateUI // Hook used to augment the user interface { diff --git a/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/RobotStateTransitionNotifier.java b/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/RobotStateTransitionNotifier.java index a550feb2371..fe68e7e7307 100644 --- a/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/RobotStateTransitionNotifier.java +++ b/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/RobotStateTransitionNotifier.java @@ -2,9 +2,8 @@ import android.content.Context; import android.util.Log; -import com.qualcomm.robotcore.eventloop.EventLoopManager; + import com.qualcomm.robotcore.eventloop.opmode.OpMode; -import com.qualcomm.robotcore.hardware.*; import com.qualcomm.robotcore.robot.RobotState; import org.swerverobotics.library.SynchronousOpMode; @@ -46,19 +45,18 @@ * So we build this weird beast that is both a motor and its own controller as that's the * most efficient way to accomplish the test. */ -public class RobotStateTransitionNotifier extends DcMotor implements DcMotorController +public class RobotStateTransitionNotifier { //---------------------------------------------------------------------------------------------- // State //---------------------------------------------------------------------------------------------- - static final String shutdownHookName = " |Swerve|ShutdownHook| "; - static Context applicationContext = null; - static List onRobotRunningMethods = new LinkedList(); - static List onRobotStartupFailureMethods = new LinkedList(); - static List onRobotUpdateActions = new LinkedList(); + static Context applicationContext = null; + static List onRobotRunningMethods = new LinkedList(); + static List onRobotStartupFailureMethods = new LinkedList(); + static List onRobotUpdateActions = new LinkedList(); + static RobotStateTransitionNotifier theInstance = new RobotStateTransitionNotifier(); - public final HardwareMap hardwareMap; private final List registrants; boolean shutdownProcessed; @@ -66,40 +64,28 @@ public class RobotStateTransitionNotifier extends DcMotor implements DcMotorCont // Construction //---------------------------------------------------------------------------------------------- - RobotStateTransitionNotifier(HardwareMap hardwareMap) + RobotStateTransitionNotifier() { - super(null, 0); - this.controller = this; - this.hardwareMap = hardwareMap; this.registrants = new LinkedList(); this.shutdownProcessed = false; } - public static void register(OpMode context, IOpModeStateTransitionEvents registrant) + public static void register(OpMode opModeContext, IOpModeStateTransitionEvents registrant) { - if (context != null) - { - create(context.hardwareMap).register(registrant); - } + // The opmode context in which the registration happens is currently not used. + getInstance().registerRegistrant(registrant); } - private static RobotStateTransitionNotifier create(HardwareMap map) + public static RobotStateTransitionNotifier getInstance() { - // Only need to create one instance per hardwareMap. - if (!Util.contains(map.dcMotorController, shutdownHookName)) - { - RobotStateTransitionNotifier hook = new RobotStateTransitionNotifier(map); - map.dcMotorController.put(shutdownHookName, hook); - map.dcMotor.put(shutdownHookName, hook); - } - return (RobotStateTransitionNotifier)map.dcMotorController.get(shutdownHookName); + return theInstance; } //---------------------------------------------------------------------------------------------- // Registration //---------------------------------------------------------------------------------------------- - synchronized void register(IOpModeStateTransitionEvents him) + synchronized void registerRegistrant(IOpModeStateTransitionEvents him) { this.registrants.add(him); } @@ -138,6 +124,7 @@ public synchronized static void unregisterRobotUpdateAction(Runnable runnable) //---------------------------------------------------------------------------------------------- synchronized void onUserOpModeStop() + // WAS: called by our DcMotorController.setPower() implementation { if (this.registrants.size() > 0) { @@ -156,6 +143,7 @@ synchronized void onUserOpModeStop() } synchronized void onRobotShutdown() + // WAS: called by our HardwareDevice.close() implementation { Log.d(SynchronousOpMode.LOGGING_TAG, "state xtion: robot shutdown ... ----------------------"); if (!this.shutdownProcessed) @@ -218,89 +206,4 @@ public static synchronized void onRobotStateChange(RobotState newState) break; } } - - //---------------------------------------------------------------------------------------------- - // HardwareDevice - //---------------------------------------------------------------------------------------------- - - @Override public synchronized void close() - { - this.onRobotShutdown(); - } - - @Override public synchronized int getVersion() - { - return 1; - } - - @Override public synchronized String getConnectionInfo() - { - return "unconnected"; - } - - @Override public synchronized String getDeviceName() - { - return "Swerve Shutdown Hook Monitor"; - } - - - //---------------------------------------------------------------------------------------------- - // DCMotorController - //---------------------------------------------------------------------------------------------- - - @Override public synchronized void setMotorPower(final int channel, final double power) - { - this.onUserOpModeStop(); - } - - @Override public synchronized void setMotorControllerDeviceMode(final DeviceMode mode) - { - } - - @Override public synchronized DeviceMode getMotorControllerDeviceMode() - { - return DeviceMode.READ_WRITE; - } - - @Override public synchronized void setMotorChannelMode(final int channel, final DcMotorController.RunMode mode) - { - } - - @Override public synchronized DcMotorController.RunMode getMotorChannelMode(final int channel) - { - return RunMode.RUN_WITHOUT_ENCODERS; - } - - @Override public synchronized double getMotorPower(final int channel) - { - return 0; - } - - @Override public synchronized boolean isBusy(final int channel) - { - return false; - } - - @Override public synchronized void setMotorPowerFloat(final int channel) - { - } - - @Override public synchronized boolean getMotorPowerFloat(final int channel) - { - return false; - } - - @Override public synchronized void setMotorTargetPosition(final int channel, final int position) - { - } - - @Override public synchronized int getMotorTargetPosition(final int channel) - { - return 0; - } - - @Override public synchronized int getMotorCurrentPosition(final int channel) - { - return 0; - } } diff --git a/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/SwerveFtcEventLoop.java b/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/SwerveFtcEventLoop.java index 237b43c1e49..02e77e7da4f 100644 --- a/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/SwerveFtcEventLoop.java +++ b/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/SwerveFtcEventLoop.java @@ -6,9 +6,12 @@ import com.qualcomm.ftccommon.UpdateUI; import com.qualcomm.hardware.HardwareFactory; import com.qualcomm.robotcore.eventloop.EventLoopManager; +import com.qualcomm.robotcore.eventloop.opmode.OpModeManager; import com.qualcomm.robotcore.eventloop.opmode.OpModeRegister; import com.qualcomm.robotcore.exception.RobotCoreException; +import com.qualcomm.robotcore.hardware.HardwareMap; import com.qualcomm.robotcore.robocol.Command; +import com.qualcomm.robotcore.util.RobotLog; import java.util.concurrent.Semaphore; @@ -22,7 +25,8 @@ public class SwerveFtcEventLoop extends FtcEventLoop // State //---------------------------------------------------------------------------------------------- - private EventLoopManager eventLoopManager; + protected SwerveOpModeManager swerveOpModeManager; + protected EventLoopManager eventLoopManager; //---------------------------------------------------------------------------------------------- // Construction @@ -34,6 +38,13 @@ public SwerveFtcEventLoop(HardwareFactory hardwareFactory, OpModeRegister regist setEventLoopManager(); } + @Override + protected OpModeManager createOpModeManager() + { + this.swerveOpModeManager = new SwerveOpModeManager(new HardwareMap(this.robotControllerContext)); + return this.swerveOpModeManager; + } + void setEventLoopManager() { if (null == this.eventLoopManager) @@ -59,4 +70,13 @@ public EventLoopManager getEventLoopManager() // super.loop(); } + + @Override + public synchronized void teardown() throws RobotCoreException + { + // Do our shutdown first so that the system 'teardown' log messages are + // really at the end. + this.swerveOpModeManager.onRobotShutdown(); + super.teardown(); + } } diff --git a/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/SwerveOpModeManager.java b/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/SwerveOpModeManager.java new file mode 100644 index 00000000000..5dfa041aaf6 --- /dev/null +++ b/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/SwerveOpModeManager.java @@ -0,0 +1,63 @@ +package org.swerverobotics.library.internal; + +import com.qualcomm.robotcore.eventloop.opmode.OpModeManager; +import com.qualcomm.robotcore.hardware.HardwareMap; +import com.qualcomm.robotcore.util.RobotLog; + +public class SwerveOpModeManager extends OpModeManager + { + //---------------------------------------------------------------------------------------------- + // Construction + //---------------------------------------------------------------------------------------------- + + public SwerveOpModeManager(HardwareMap map) + { + super(map); + } + + //---------------------------------------------------------------------------------------------- + // Operations + //---------------------------------------------------------------------------------------------- + + @Override + protected void callActiveOpModeStop() + { + RobotLog.v("Swerve: OpModeManager: %s: stop ...", activeOpModeName); + super.callActiveOpModeStop(); + if (this.activeOpMode != OpModeManager.DEFAULT_OP_MODE) + { + RobotStateTransitionNotifier.getInstance().onUserOpModeStop(); + } + RobotLog.v("Swerve: OpModeManager: %s: ... stop complete", activeOpModeName); + } + + @Override + protected void callActiveOpModeInit() + { + RobotLog.v("Swerve: OpModeManager: %s: init...", activeOpModeName); + super.callActiveOpModeInit(); + RobotLog.v("Swerve: OpModeManager: %s: ... init complete", activeOpModeName); + } + + @Override + protected void callActiveOpModeStart() + { + RobotLog.v("Swerve: OpModeManager: %s: start...", activeOpModeName); + super.callActiveOpModeStart(); + RobotLog.v("Swerve: OpModeManager: %s: ... start complete", activeOpModeName); + } + + public void onRobotShutdown() + { + RobotLog.v("Swerve: OpModeManager: onRobotShutdown ..."); + // We need to shutdown the opmode if we really need to. But if we don't, don't bother, + // since that will add additional log messages when FtcEventLoop.teardown() itself calls + // stopActiveOpMode(). + if (this.activeOpMode != OpModeManager.DEFAULT_OP_MODE) + { + this.stopActiveOpMode(); + } + RobotStateTransitionNotifier.getInstance().onRobotShutdown(); + RobotLog.v("Swerve: OpModeManager: ... onRobotShutdown complete"); + } + } diff --git a/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/tests/DerivedMotorTest.java b/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/tests/DerivedMotorTest.java new file mode 100644 index 00000000000..2b7c17c976b --- /dev/null +++ b/SwerveRoboticsLibrary/src/main/java/org/swerverobotics/library/internal/tests/DerivedMotorTest.java @@ -0,0 +1,45 @@ +package org.swerverobotics.library.internal.tests; + +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.OpMode; +import com.qualcomm.robotcore.hardware.DcMotor; +import com.qualcomm.robotcore.hardware.DcMotorController; +import com.qualcomm.robotcore.robot.Robot; + +import org.swerverobotics.library.ClassFactory; +import org.swerverobotics.library.interfaces.Disabled; +import org.swerverobotics.library.interfaces.TeleOp; + +@TeleOp(name="Derived Motor Test (Raw)", group="Swerve Tests") +@Disabled +public class DerivedMotorTest extends OpMode + { + public static class DerivedMotor extends DcMotor + { + public DerivedMotor(DcMotorController controller, int portNumber) + { + super(controller, portNumber); + } + } + + DerivedMotor leftMotor; + DerivedMotor rightMotor; + DcMotorController easyMotorController; + + @Override + public void init() + { + DcMotor lTmp = hardwareMap.dcMotor.get("motorLeft"); + DcMotor rTmp = hardwareMap.dcMotor.get("motorRight"); + + leftMotor = new DerivedMotor(lTmp.getController(), 1); + rightMotor = new DerivedMotor(rTmp.getController(), 2); + + easyMotorController = ClassFactory.createEasyMotorController(this, leftMotor, rightMotor); + } + + @Override + public void loop() + { + } + }