diff --git a/FtcRobotController/build.gradle b/FtcRobotController/build.gradle index b73fbe4f1a9..daf4ee2d48a 100644 --- a/FtcRobotController/build.gradle +++ b/FtcRobotController/build.gradle @@ -7,11 +7,10 @@ android { defaultConfig { minSdkVersion 19 - targetSdkVersion 19 + targetSdkVersion 26 } - compileSdkVersion 23 - buildToolsVersion '25.0.3' + compileSdkVersion 28 compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 diff --git a/FtcRobotController/build.release.gradle b/FtcRobotController/build.release.gradle index 4b3fe906d63..afc368f072d 100644 --- a/FtcRobotController/build.release.gradle +++ b/FtcRobotController/build.release.gradle @@ -1,9 +1,11 @@ dependencies { - compile (name:'Inspection-release', ext: 'aar') - compile (name:'Blocks-release', ext: 'aar') - compile (name:'RobotCore-release', ext: 'aar') - compile (name:'Hardware-release', ext: 'aar') - compile (name:'FtcCommon-release', ext: 'aar') - compile (name:'Analytics-release', ext:'aar') - compile (name:'WirelessP2p-release', ext:'aar') + implementation (name:'Inspection-release', ext: 'aar') + implementation (name:'Blocks-release', ext: 'aar') + implementation (name:'RobotCore-release', ext: 'aar') + implementation (name:'RobotServer-release', ext: 'aar') + implementation (name:'OnBotJava-release', ext: 'aar') + implementation (name:'Hardware-release', ext: 'aar') + implementation (name:'FtcCommon-release', ext: 'aar') + implementation (name:'WirelessP2p-release', ext:'aar') + implementation 'com.android.support:support-compat:28.0.0' } diff --git a/FtcRobotController/src/main/AndroidManifest.xml b/FtcRobotController/src/main/AndroidManifest.xml index cfaaf4aebda..8774c501fed 100644 --- a/FtcRobotController/src/main/AndroidManifest.xml +++ b/FtcRobotController/src/main/AndroidManifest.xml @@ -2,8 +2,8 @@ + android:versionCode="32" + android:versionName="5.0"> @@ -14,18 +14,32 @@ android:label="@string/app_name" android:theme="@style/AppThemeRedRC" > + + + - + + + + + @@ -33,6 +47,11 @@ + + + diff --git a/FtcRobotController/src/main/assets/RoverRuckus.dat b/FtcRobotController/src/main/assets/RoverRuckus.dat new file mode 100755 index 00000000000..461add830d0 Binary files /dev/null and b/FtcRobotController/src/main/assets/RoverRuckus.dat differ diff --git a/FtcRobotController/src/main/assets/RoverRuckus.tflite b/FtcRobotController/src/main/assets/RoverRuckus.tflite new file mode 100644 index 00000000000..2c538cbb697 Binary files /dev/null and b/FtcRobotController/src/main/assets/RoverRuckus.tflite differ diff --git a/FtcRobotController/src/main/assets/RoverRuckus.xml b/FtcRobotController/src/main/assets/RoverRuckus.xml new file mode 100755 index 00000000000..05eac7ea3a8 --- /dev/null +++ b/FtcRobotController/src/main/assets/RoverRuckus.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptCompassCalibration.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptCompassCalibration.java index b5920f9839c..cd1da0a85de 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptCompassCalibration.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptCompassCalibration.java @@ -29,9 +29,9 @@ package org.firstinspires.ftc.robotcontroller.external.samples; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.CompassSensor; import com.qualcomm.robotcore.util.ElapsedTime; @@ -52,7 +52,7 @@ * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list */ -@Autonomous(name="Concept: Compass Calibration", group="Concept") +@TeleOp(name="Concept: Compass Calibration", group="Concept") @Disabled public class ConceptCompassCalibration extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptDIMAsIndicator.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptDIMAsIndicator.java index 699d2e5d0a0..75b6ad44583 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptDIMAsIndicator.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptDIMAsIndicator.java @@ -29,9 +29,9 @@ package org.firstinspires.ftc.robotcontroller.external.samples; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.DeviceInterfaceModule; import com.qualcomm.robotcore.util.ElapsedTime; @@ -51,7 +51,7 @@ * Use Android Studios to Copy this Class, and Paste it into your team's code folder with a new name. * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list */ -@Autonomous(name = "Concept: DIM As Indicator", group = "Concept") +@TeleOp(name = "Concept: DIM As Indicator", group = "Concept") @Disabled public class ConceptDIMAsIndicator extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java index ee83ec00d61..2f846959f34 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java @@ -29,9 +29,9 @@ package org.firstinspires.ftc.robotcontroller.external.samples; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.OpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.util.ElapsedTime; import java.text.SimpleDateFormat; @@ -40,7 +40,7 @@ /** * Demonstrates empty OpMode */ -@Autonomous(name = "Concept: NullOp", group = "Concept") +@TeleOp(name = "Concept: NullOp", group = "Concept") @Disabled public class ConceptNullOp extends OpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java index 45085402291..0a8f3dcc28c 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java @@ -29,9 +29,9 @@ package org.firstinspires.ftc.robotcontroller.external.samples; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.DcMotor; /** @@ -46,7 +46,7 @@ * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list */ -@Autonomous(name = "Concept: Ramp Motor Speed", group = "Concept") +@TeleOp(name = "Concept: Ramp Motor Speed", group = "Concept") @Disabled public class ConceptRampMotorSpeed extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRegisterOpModes.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRegisterOpModes.java deleted file mode 100644 index a0046baf361..00000000000 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRegisterOpModes.java +++ /dev/null @@ -1,115 +0,0 @@ -/* -------------------------------------------------------------------------------- - * *** WARNING **** *** WARNING **** *** WARNING **** *** WARNING **** - * This code is only designed to be used in the Android Studio code Environment. - * It will not build if it is imported as a sample into the OnBot Java environment. - * -------------------------------------------------------------------------------*/ - -/* Copyright (c) 2017 FIRST. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted (subject to the limitations in the disclaimer below) provided that - * the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * Neither the name of FIRST nor the names of its contributors may be used to endorse or - * promote products derived from this software without specific prior written permission. - * - * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS - * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.robotcore.eventloop.opmode.OpModeManager; -import com.qualcomm.robotcore.eventloop.opmode.OpModeRegistrar; - -import org.firstinspires.ftc.robotcontroller.external.samples.*; - -/** - * This class demonstrates how to manually register opmodes. - * - * Note: It is NOT required to manually register OpModes, but this method is provided to support teams that - * want to have centralized control over their opmode lists. - * This sample is ALSO handy to use to selectively register the other sample opmodes. - * Just copy/paste this sample to the TeamCode module and then uncomment the opmodes you wish to run. - * - * How it works: - * The registerMyOpmodes method will be called by the system during the automatic registration process - * You can register any of the opmodes in your App. by making manager.register() calls inside registerMyOpmodes(); - * - * Note: - * Even though you are performing a manual Registration, you should set the Annotations on your classes so they - * can be placed into the correct Driver Station OpMode list... eg: - * - * @Autonomous(name="DriveAndScoreRed", group ="Red") - * or - * @TeleOp(name="FastDrive", group ="A-Team") - * - * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. - * Then uncomment and copy the manager.register() call to register as many of your OpModes as you like. - * You can even use it to temporarily register samples directly from the robotController/external/samples folder. - */ -public class ConceptRegisterOpModes -{ - @OpModeRegistrar - public static void registerMyOpModes(OpModeManager manager) { - // Un-comment any line to enable that sample. - // Or add your own lines to register your Team opmodes. - - // Basic Templates - // manager.register("Iterative Opmode", BasicOpMode_Iterative.class); - // manager.register("Linear Opmode", BasicOpMode_Linear.class); - - // Driving Samples - // manager.register("Teleop POV", PushbotTeleopPOV_Linear.class); - // manager.register("Teleop Tank", PushbotTeleopTank_Iterative.class); - // manager.register("Auto Drive Gyro", PushbotAutoDriveByGyro_Linear.class); - // manager.register("Auto Drive Encoder", PushbotAutoDriveByEncoder_Linear.class); - // manager.register("Auto Drive Time", PushbotAutoDriveByTime_Linear.class); - // manager.register("Auto Drive Line", PushbotAutoDriveToLine_Linear.class); - // manager.register("K9 Telop", K9botTeleopTank_Linear.class); - - // Sensor Samples - // manager.register("BNO055 IMU", SensorBNO055IMU.class); - // manager.register("BNO055 IMU Cal", SensorBNO055IMUCalibration.class); - // manager.register("AdaFruit Color", SensorAdafruitRGB.class); - // manager.register("Digital Touch", SensorDigitalTouch.class); - // manager.register("DIM DIO", SensorDIO.class); - // manager.register("HT Color", SensorHTColor.class); - // manager.register("HT Gyro", SensorHTGyro.class); - // manager.register("LEGO Light", SensorLEGOLight.class); - // manager.register("LEGO Touch", SensorLEGOTouch.class); - // manager.register("MR Color", SensorMRColor.class); - // manager.register("MR Compass", SensorMRCompass.class); - // manager.register("MR Gyro", SensorMRGyro.class); - // manager.register("MR IR Seeker", SensorMRIrSeeker.class); - // manager.register("MR ODS", SensorMROpticalDistance.class); - // manager.register("MR Range Sensor", SensorMRRangeSensor.class); - // manager.register("REV Color Distance", SensorREVColorDistance.class); - - // Concept Samples - // manager.register("Null Op", ConceptNullOp.class); - // manager.register("Compass Calibration", ConceptCompassCalibration.class); - // manager.register("DIM as Indicator", ConceptDIMAsIndicator.class); - // manager.register("I2C Address Change", ConceptI2cAddressChange.class); - // manager.register("Ramp Motor Speed", ConceptRampMotorSpeed.class); - // manager.register("Scan Servo", ConceptScanServo.class); - // manager.register("Telemetry", ConceptTelemetry.class); - // manager.register("Vuforia Navigation", ConceptVuforiaNavigation.class); - } -} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevSPARKMini.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevSPARKMini.java new file mode 100644 index 00000000000..b81b7dea72a --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevSPARKMini.java @@ -0,0 +1,112 @@ +/* Copyright (c) 2018 FIRST. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided that + * the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * Neither the name of FIRST nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS + * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.firstinspires.ftc.robotcontroller.external.samples; + +import com.qualcomm.robotcore.eventloop.opmode.Disabled; +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; +import com.qualcomm.robotcore.hardware.DcMotorSimple; +import com.qualcomm.robotcore.util.ElapsedTime; +import com.qualcomm.robotcore.util.Range; + + +/** + * + * This OpMode executes a basic Tank Drive Teleop for a two wheeled robot using two REV SPARK Minis. + * To use this example, connect two REV SPARK Minis into servo ports on the Expansion Hub. On the + * robot configuration, use the drop down list under 'Servos' to select 'REV SPARK Mini Controller' + * and name them 'left_drive' and 'right_drive'. + * + * Use Android Studios to Copy this Class, and Paste it into your team's code folder with a new name. + * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list + */ + +@TeleOp(name="REV SPARK Mini Simple Drive Example", group="Concept") +@Disabled +public class ConceptRevSPARKMini extends LinearOpMode { + + // Declare OpMode members. + private ElapsedTime runtime = new ElapsedTime(); + private DcMotorSimple leftDrive = null; + private DcMotorSimple rightDrive = null; + + @Override + public void runOpMode() { + telemetry.addData("Status", "Initialized"); + telemetry.update(); + + // Initialize the hardware variables. Note that the strings used here as parameters + // to 'get' must correspond to the names assigned during the robot configuration + // step (using the FTC Robot Controller app on the phone). + leftDrive = hardwareMap.get(DcMotorSimple.class, "left_drive"); + rightDrive = hardwareMap.get(DcMotorSimple.class, "right_drive"); + + // Most robots need the motor on one side to be reversed to drive forward + // Reverse the motor that runs backwards when connected directly to the battery + leftDrive.setDirection(DcMotorSimple.Direction.FORWARD); + rightDrive.setDirection(DcMotorSimple.Direction.REVERSE); + + // Wait for the game to start (driver presses PLAY) + waitForStart(); + runtime.reset(); + + // run until the end of the match (driver presses STOP) + while (opModeIsActive()) { + + // Setup a variable for each drive wheel to save power level for telemetry + double leftPower; + double rightPower; + + // Choose to drive using either Tank Mode, or POV Mode + // Comment out the method that's not used. The default below is POV. + + // POV Mode uses left stick to go forward, and right stick to turn. + // - This uses basic math to combine motions and is easier to drive straight. + double drive = -gamepad1.left_stick_y; + double turn = gamepad1.right_stick_x; + leftPower = Range.clip(drive + turn, -1.0, 1.0) ; + rightPower = Range.clip(drive - turn, -1.0, 1.0) ; + + // Tank Mode uses one stick to control each wheel. + // - This requires no math, but it is hard to drive forward slowly and keep straight. + // leftPower = -gamepad1.left_stick_y ; + // rightPower = -gamepad1.right_stick_y ; + + // Send calculated power to wheels + leftDrive.setPower(leftPower); + rightDrive.setPower(rightPower); + + // Show the elapsed game time and wheel power. + telemetry.addData("Status", "Run Time: " + runtime.toString()); + telemetry.addData("Motors", "left (%.2f), right (%.2f)", leftPower, rightPower); + telemetry.update(); + } + } +} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java index 0f4e2355102..8e9c899e40e 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java @@ -29,9 +29,9 @@ package org.firstinspires.ftc.robotcontroller.external.samples; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.Servo; /** @@ -40,7 +40,7 @@ * INCREMENT sets how much to increase/decrease the servo position each cycle * CYCLE_MS sets the update period. * - * This code assumes a Servo configured with the name "left claw" as is found on a pushbot. + * This code assumes a Servo configured with the name "left_hand" as is found on a pushbot. * * NOTE: When any servo position is set, ALL attached servos are activated, so ensure that any other * connected servos are able to move freely before running this test. @@ -48,7 +48,7 @@ * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list */ -@Autonomous(name = "Concept: Scan Servo", group = "Concept") +@TeleOp(name = "Concept: Scan Servo", group = "Concept") @Disabled public class ConceptScanServo extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsASJava.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsASJava.java new file mode 100644 index 00000000000..51d99d208c5 --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsASJava.java @@ -0,0 +1,135 @@ +/* Copyright (c) 2018 FIRST. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided that + * the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * Neither the name of FIRST nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS + * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.firstinspires.ftc.robotcontroller.external.samples; + +import com.qualcomm.ftccommon.SoundPlayer; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; + +import java.io.File; + +/** + * This file demonstrates how to play simple sounds on both the RC and DS phones. + * It illustrates how to build sounds into your application as a resource. + * This technique is best suited for use with Android Studio since it assumes you will be creating a new application + * + * If you are using OnBotJava, please see the ConceptSoundsOnBotJava sample + * + * Use Android Studios to Copy this Class, and Paste it into your team's code folder with a new name. + * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list + * + * Operation: + * + * Gamepad X & B buttons are used to trigger sounds in this example, but any event can be used. + * Note: Time should be allowed for sounds to complete before playing other sounds. + * + * For sound files to be used as a compiled-in resource, they need to be located in a folder called "raw" under your "res" (resources) folder. + * You can create your own "raw" folder from scratch, or you can copy the one from the FtcRobotController module. + * + * Android Studio coders will ultimately need a folder in your path as follows: + * /TeamCode/src/main/res/raw + * + * Copy any .wav files you want to play into this folder. + * Make sure that your files ONLY use lower-case characters, and have no spaces or special characters other than underscore. + * + * The name you give your .wav files will become the resource ID for these sounds. + * eg: gold.wav becomes R.raw.gold + * + * If you wish to use the sounds provided for this sample, they are located in: + * /FtcRobotController/src/main/res/raw + * You can copy and paste the entire 'raw' folder using Android Studio. + * + */ + +@TeleOp(name="Concept: Sound Resources", group="Concept") +@Disabled +public class ConceptSoundsASJava extends LinearOpMode { + + // Declare OpMode members. + private boolean goldFound; // Sound file present flags + private boolean silverFound; + + private boolean isX = false; // Gamepad button state variables + private boolean isB = false; + + private boolean wasX = false; // Gamepad button history variables + private boolean WasB = false; + + @Override + public void runOpMode() { + + // Determine Resource IDs for sounds built into the RC application. + int silverSoundID = hardwareMap.appContext.getResources().getIdentifier("silver", "raw", hardwareMap.appContext.getPackageName()); + int goldSoundID = hardwareMap.appContext.getResources().getIdentifier("gold", "raw", hardwareMap.appContext.getPackageName()); + + // Determine if sound resources are found. + // Note: Preloading is NOT required, but it's a good way to verify all your sounds are available before you run. + if (goldSoundID != 0) + goldFound = SoundPlayer.getInstance().preload(hardwareMap.appContext, goldSoundID); + + if (silverSoundID != 0) + silverFound = SoundPlayer.getInstance().preload(hardwareMap.appContext, silverSoundID); + + // Display sound status + telemetry.addData("gold resource", goldFound ? "Found" : "NOT found\n Add gold.wav to /src/main/res/raw" ); + telemetry.addData("silver resource", silverFound ? "Found" : "Not found\n Add silver.wav to /src/main/res/raw" ); + + // Wait for the game to start (driver presses PLAY) + telemetry.addData(">", "Press Start to continue"); + telemetry.update(); + waitForStart(); + + telemetry.addData(">", "Press X, B to play sounds."); + telemetry.update(); + + // run until the end of the match (driver presses STOP) + while (opModeIsActive()) { + + // say Silver each time gamepad X is pressed (This sound is a resource) + if (silverFound && (isX = gamepad1.x) && !wasX) { + SoundPlayer.getInstance().startPlaying(hardwareMap.appContext, silverSoundID); + telemetry.addData("Playing", "Resource Silver"); + telemetry.update(); + } + + // say Gold each time gamepad B is pressed (This sound is a resource) + if (goldFound && (isB = gamepad1.b) && !WasB) { + SoundPlayer.getInstance().startPlaying(hardwareMap.appContext, goldSoundID); + telemetry.addData("Playing", "Resource Gold"); + telemetry.update(); + } + + // Save last button states + wasX = isX; + WasB = isB; + } + } +} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsOnBotJava.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsOnBotJava.java new file mode 100644 index 00000000000..bacb66e3d41 --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsOnBotJava.java @@ -0,0 +1,119 @@ +/* Copyright (c) 2018 FIRST. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided that + * the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * Neither the name of FIRST nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS + * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.firstinspires.ftc.robotcontroller.external.samples; + +import com.qualcomm.ftccommon.SoundPlayer; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; +import java.io.File; + +/** + * This file demonstrates how to play simple sounds on both the RC and DS phones. + * It illustrates how to play sound files that have been copied to the RC Phone + * This technique is best suited for use with OnBotJava since it does not require the app to be modified. + * + * Operation: + * + * Gamepad X & B buttons are used to trigger sounds in this example, but any event can be used. + * Note: Time should be allowed for sounds to complete before playing other sounds. + * + * To play a new sound, you will need to copy the .wav files to the phone, and then provide the full path to them as part of your OpMode. + * This is done in this sample for the two sound files. silver.wav and gold.wav + * + * You can put the files in a variety of soundPaths, but we recommend you put them in the /FIRST/blocks/sounds folder. + * Your OpModes will have guaranteed access to this folder, and you can transfer files into this folder using the BLOCKS web page. + * -- There is a link called "sounds" on the right hand side of the color bar on the BLOCKS page that can be used to send sound files to this folder by default. + * Or you can use Windows File Manager, or ADB to transfer the sound files + * + * To get full use of THIS sample, you will need to copy two sound file called silver.wav and gold.wav to /FIRST/blocks/sounds on the RC phone. + * They can be located here: + * https://github.com/ftctechnh/ftc_app/tree/master/FtcRobotController/src/main/res/raw/gold.wav + * https://github.com/ftctechnh/ftc_app/tree/master/FtcRobotController/src/main/res/raw/silver.wav + */ + +@TeleOp(name="Concept: Sound Files", group="Concept") +@Disabled +public class ConceptSoundsOnBotJava extends LinearOpMode { + + // Point to sound files on the phone's drive + private String soundPath = "/FIRST/blocks/sounds"; + private File goldFile = new File("/sdcard" + soundPath + "/gold.wav"); + private File silverFile = new File("/sdcard" + soundPath + "/silver.wav"); + + // Declare OpMode members. + private boolean isX = false; // Gamepad button state variables + private boolean isB = false; + + private boolean wasX = false; // Gamepad button history variables + private boolean WasB = false; + + @Override + public void runOpMode() { + + // Make sure that the sound files exist on the phone + boolean goldFound = goldFile.exists(); + boolean silverFound = silverFile.exists(); + + // Display sound status + telemetry.addData("gold sound", goldFound ? "Found" : "NOT Found \nCopy gold.wav to " + soundPath ); + telemetry.addData("silver sound", silverFound ? "Found" : "NOT Found \nCopy silver.wav to " + soundPath ); + + // Wait for the game to start (driver presses PLAY) + telemetry.addData(">", "Press Start to continue"); + telemetry.update(); + waitForStart(); + + telemetry.addData(">", "Press X or B to play sounds."); + telemetry.update(); + + // run until the end of the match (driver presses STOP) + while (opModeIsActive()) { + + // say Silver each time gamepad X is pressed (This sound is a resource) + if (silverFound && (isX = gamepad1.x) && !wasX) { + SoundPlayer.getInstance().startPlaying(hardwareMap.appContext, silverFile); + telemetry.addData("Playing", "Silver File"); + telemetry.update(); + } + + // say Gold each time gamepad B is pressed (This sound is a resource) + if (goldFound && (isB = gamepad1.b) && !WasB) { + SoundPlayer.getInstance().startPlaying(hardwareMap.appContext, goldFile); + telemetry.addData("Playing", "Gold File"); + telemetry.update(); + } + + // Save last button states + wasX = isX; + WasB = isB; + } + } +} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java index 5994561175e..d3b468282d8 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java @@ -29,9 +29,9 @@ package org.firstinspires.ftc.robotcontroller.external.samples; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.VoltageSensor; import com.qualcomm.robotcore.util.ElapsedTime; @@ -47,7 +47,7 @@ * * @see Telemetry */ -@Autonomous(name = "Concept: Telemetry", group = "Concept") +@TeleOp(name = "Concept: Telemetry", group = "Concept") @Disabled public class ConceptTelemetry extends LinearOpMode { /** keeps track of the line of the poem which is to be emitted next */ diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTensorFlowObjectDetection.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTensorFlowObjectDetection.java new file mode 100644 index 00000000000..146886c54a0 --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTensorFlowObjectDetection.java @@ -0,0 +1,177 @@ +/* Copyright (c) 2018 FIRST. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided that + * the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * Neither the name of FIRST nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS + * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.firstinspires.ftc.robotcontroller.external.samples; + +import com.qualcomm.robotcore.eventloop.opmode.Disabled; +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; +import java.util.List; +import org.firstinspires.ftc.robotcore.external.ClassFactory; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer.CameraDirection; +import org.firstinspires.ftc.robotcore.external.tfod.TFObjectDetector; +import org.firstinspires.ftc.robotcore.external.tfod.Recognition; + +/** + * This 2018-2019 OpMode illustrates the basics of using the TensorFlow Object Detection API to + * determine the position of the gold and silver minerals. + * + * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. + * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list. + * + * IMPORTANT: In order to use this OpMode, you need to obtain your own Vuforia license key as + * is explained below. + */ +@TeleOp(name = "Concept: TensorFlow Object Detection", group = "Concept") +@Disabled +public class ConceptTensorFlowObjectDetection extends LinearOpMode { + private static final String TFOD_MODEL_ASSET = "RoverRuckus.tflite"; + private static final String LABEL_GOLD_MINERAL = "Gold Mineral"; + private static final String LABEL_SILVER_MINERAL = "Silver Mineral"; + + /* + * IMPORTANT: You need to obtain your own license key to use Vuforia. The string below with which + * 'parameters.vuforiaLicenseKey' is initialized is for illustration only, and will not function. + * A Vuforia 'Development' license key, can be obtained free of charge from the Vuforia developer + * web site at https://developer.vuforia.com/license-manager. + * + * Vuforia license keys are always 380 characters long, and look as if they contain mostly + * random data. As an example, here is a example of a fragment of a valid key: + * ... yIgIzTqZ4mWjk9wd3cZO9T1axEqzuhxoGlfOOI2dRzKS4T0hQ8kT ... + * Once you've obtained a license key, copy the string from the Vuforia web site + * and paste it in to your code on the next line, between the double quotes. + */ + private static final String VUFORIA_KEY = " -- YOUR NEW VUFORIA KEY GOES HERE --- "; + + /** + * {@link #vuforia} is the variable we will use to store our instance of the Vuforia + * localization engine. + */ + private VuforiaLocalizer vuforia; + + /** + * {@link #tfod} is the variable we will use to store our instance of the TensorFlow Object + * Detection engine. + */ + private TFObjectDetector tfod; + + @Override + public void runOpMode() { + // The TFObjectDetector uses the camera frames from the VuforiaLocalizer, so we create that + // first. + initVuforia(); + + if (ClassFactory.getInstance().canCreateTFObjectDetector()) { + initTfod(); + } else { + telemetry.addData("Sorry!", "This device is not compatible with TFOD"); + } + + /** Wait for the game to begin */ + telemetry.addData(">", "Press Play to start tracking"); + telemetry.update(); + waitForStart(); + + if (opModeIsActive()) { + /** Activate TensorFlow Object Detection. */ + if (tfod != null) { + tfod.activate(); + } + + while (opModeIsActive()) { + if (tfod != null) { + // getUpdatedRecognitions() will return null if no new information is available since + // the last time that call was made. + List updatedRecognitions = tfod.getUpdatedRecognitions(); + if (updatedRecognitions != null) { + telemetry.addData("# Object Detected", updatedRecognitions.size()); + if (updatedRecognitions.size() == 3) { + int goldMineralX = -1; + int silverMineral1X = -1; + int silverMineral2X = -1; + for (Recognition recognition : updatedRecognitions) { + if (recognition.getLabel().equals(LABEL_GOLD_MINERAL)) { + goldMineralX = (int) recognition.getLeft(); + } else if (silverMineral1X == -1) { + silverMineral1X = (int) recognition.getLeft(); + } else { + silverMineral2X = (int) recognition.getLeft(); + } + } + if (goldMineralX != -1 && silverMineral1X != -1 && silverMineral2X != -1) { + if (goldMineralX < silverMineral1X && goldMineralX < silverMineral2X) { + telemetry.addData("Gold Mineral Position", "Left"); + } else if (goldMineralX > silverMineral1X && goldMineralX > silverMineral2X) { + telemetry.addData("Gold Mineral Position", "Right"); + } else { + telemetry.addData("Gold Mineral Position", "Center"); + } + } + } + telemetry.update(); + } + } + } + } + + if (tfod != null) { + tfod.shutdown(); + } + } + + /** + * Initialize the Vuforia localization engine. + */ + private void initVuforia() { + /* + * Configure Vuforia by creating a Parameter object, and passing it to the Vuforia engine. + */ + VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(); + + parameters.vuforiaLicenseKey = VUFORIA_KEY; + parameters.cameraDirection = CameraDirection.BACK; + + // Instantiate the Vuforia engine + vuforia = ClassFactory.getInstance().createVuforia(parameters); + + // Loading trackables is not necessary for the TensorFlow Object Detection engine. + } + + /** + * Initialize the TensorFlow Object Detection engine. + */ + private void initTfod() { + int tfodMonitorViewId = hardwareMap.appContext.getResources().getIdentifier( + "tfodMonitorViewId", "id", hardwareMap.appContext.getPackageName()); + TFObjectDetector.Parameters tfodParameters = new TFObjectDetector.Parameters(tfodMonitorViewId); + tfod = ClassFactory.getInstance().createTFObjectDetector(tfodParameters, vuforia); + tfod.loadModelFromAsset(TFOD_MODEL_ASSET, LABEL_GOLD_MINERAL, LABEL_SILVER_MINERAL); + } +} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTensorFlowObjectDetectionWebcam.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTensorFlowObjectDetectionWebcam.java new file mode 100644 index 00000000000..6bf8cf2380c --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTensorFlowObjectDetectionWebcam.java @@ -0,0 +1,177 @@ +/* Copyright (c) 2018 FIRST. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided that + * the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * Neither the name of FIRST nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS + * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.firstinspires.ftc.robotcontroller.external.samples; + +import com.qualcomm.robotcore.eventloop.opmode.Disabled; +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; +import java.util.List; +import org.firstinspires.ftc.robotcore.external.ClassFactory; +import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer; +import org.firstinspires.ftc.robotcore.external.tfod.TFObjectDetector; +import org.firstinspires.ftc.robotcore.external.tfod.Recognition; + +/** + * This 2018-2019 OpMode illustrates the basics of using the TensorFlow Object Detection API to + * determine the position of the gold and silver minerals. + * + * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. + * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list. + * + * IMPORTANT: In order to use this OpMode, you need to obtain your own Vuforia license key as + * is explained below. + */ +@TeleOp(name = "Concept: TensorFlow Object Detection Webcam", group = "Concept") +@Disabled +public class ConceptTensorFlowObjectDetectionWebcam extends LinearOpMode { + private static final String TFOD_MODEL_ASSET = "RoverRuckus.tflite"; + private static final String LABEL_GOLD_MINERAL = "Gold Mineral"; + private static final String LABEL_SILVER_MINERAL = "Silver Mineral"; + + /* + * IMPORTANT: You need to obtain your own license key to use Vuforia. The string below with which + * 'parameters.vuforiaLicenseKey' is initialized is for illustration only, and will not function. + * A Vuforia 'Development' license key, can be obtained free of charge from the Vuforia developer + * web site at https://developer.vuforia.com/license-manager. + * + * Vuforia license keys are always 380 characters long, and look as if they contain mostly + * random data. As an example, here is a example of a fragment of a valid key: + * ... yIgIzTqZ4mWjk9wd3cZO9T1axEqzuhxoGlfOOI2dRzKS4T0hQ8kT ... + * Once you've obtained a license key, copy the string from the Vuforia web site + * and paste it in to your code on the next line, between the double quotes. + */ + private static final String VUFORIA_KEY = " -- YOUR NEW VUFORIA KEY GOES HERE --- "; + + /** + * {@link #vuforia} is the variable we will use to store our instance of the Vuforia + * localization engine. + */ + private VuforiaLocalizer vuforia; + + /** + * {@link #tfod} is the variable we will use to store our instance of the TensorFlow Object + * Detection engine. + */ + private TFObjectDetector tfod; + + @Override + public void runOpMode() { + // The TFObjectDetector uses the camera frames from the VuforiaLocalizer, so we create that + // first. + initVuforia(); + + if (ClassFactory.getInstance().canCreateTFObjectDetector()) { + initTfod(); + } else { + telemetry.addData("Sorry!", "This device is not compatible with TFOD"); + } + + /** Wait for the game to begin */ + telemetry.addData(">", "Press Play to start tracking"); + telemetry.update(); + waitForStart(); + + if (opModeIsActive()) { + /** Activate TensorFlow Object Detection. */ + if (tfod != null) { + tfod.activate(); + } + + while (opModeIsActive()) { + if (tfod != null) { + // getUpdatedRecognitions() will return null if no new information is available since + // the last time that call was made. + List updatedRecognitions = tfod.getUpdatedRecognitions(); + if (updatedRecognitions != null) { + telemetry.addData("# Object Detected", updatedRecognitions.size()); + if (updatedRecognitions.size() == 3) { + int goldMineralX = -1; + int silverMineral1X = -1; + int silverMineral2X = -1; + for (Recognition recognition : updatedRecognitions) { + if (recognition.getLabel().equals(LABEL_GOLD_MINERAL)) { + goldMineralX = (int) recognition.getLeft(); + } else if (silverMineral1X == -1) { + silverMineral1X = (int) recognition.getLeft(); + } else { + silverMineral2X = (int) recognition.getLeft(); + } + } + if (goldMineralX != -1 && silverMineral1X != -1 && silverMineral2X != -1) { + if (goldMineralX < silverMineral1X && goldMineralX < silverMineral2X) { + telemetry.addData("Gold Mineral Position", "Left"); + } else if (goldMineralX > silverMineral1X && goldMineralX > silverMineral2X) { + telemetry.addData("Gold Mineral Position", "Right"); + } else { + telemetry.addData("Gold Mineral Position", "Center"); + } + } + } + telemetry.update(); + } + } + } + } + + if (tfod != null) { + tfod.shutdown(); + } + } + + /** + * Initialize the Vuforia localization engine. + */ + private void initVuforia() { + /* + * Configure Vuforia by creating a Parameter object, and passing it to the Vuforia engine. + */ + VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(); + + parameters.vuforiaLicenseKey = VUFORIA_KEY; + parameters.cameraName = hardwareMap.get(WebcamName.class, "Webcam 1"); + + // Instantiate the Vuforia engine + vuforia = ClassFactory.getInstance().createVuforia(parameters); + + // Loading trackables is not necessary for the TensorFlow Object Detection engine. + } + + /** + * Initialize the TensorFlow Object Detection engine. + */ + private void initTfod() { + int tfodMonitorViewId = hardwareMap.appContext.getResources().getIdentifier( + "tfodMonitorViewId", "id", hardwareMap.appContext.getPackageName()); + TFObjectDetector.Parameters tfodParameters = new TFObjectDetector.Parameters(tfodMonitorViewId); + tfod = ClassFactory.getInstance().createTFObjectDetector(tfodParameters, vuforia); + tfod.loadModelFromAsset(TFOD_MODEL_ASSET, LABEL_GOLD_MINERAL, LABEL_SILVER_MINERAL); + } +} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuMarkIdentification.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuMarkIdentification.java index 041e2a20a85..f0d735bfb8d 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuMarkIdentification.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuMarkIdentification.java @@ -28,7 +28,7 @@ */ package org.firstinspires.ftc.robotcontroller.external.samples; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; @@ -65,7 +65,7 @@ * is explained in {@link ConceptVuforiaNavigation}. */ -@Autonomous(name="Concept: VuMark Id", group ="Concept") +@TeleOp(name="Concept: VuMark Id", group ="Concept") @Disabled public class ConceptVuMarkIdentification extends LinearOpMode { @@ -83,7 +83,6 @@ public class ConceptVuMarkIdentification extends LinearOpMode { /* * To start up Vuforia, tell it the view that we wish to use for camera monitor (on the RC phone); - * If no camera monitor is desired, use the parameterless constructor instead (commented out below). */ int cameraMonitorViewId = hardwareMap.appContext.getResources().getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()); VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(cameraMonitorViewId); @@ -101,9 +100,9 @@ public class ConceptVuMarkIdentification extends LinearOpMode { * random data. As an example, here is a example of a fragment of a valid key: * ... yIgIzTqZ4mWjk9wd3cZO9T1axEqzuhxoGlfOOI2dRzKS4T0hQ8kT ... * Once you've obtained a license key, copy the string from the Vuforia web site - * and paste it in to your code onthe next line, between the double quotes. + * and paste it in to your code on the next line, between the double quotes. */ - parameters.vuforiaLicenseKey = "ATsODcD/////AAAAAVw2lR...d45oGpdljdOh5LuFB9nDNfckoxb8COxKSFX"; + parameters.vuforiaLicenseKey = " -- YOUR NEW VUFORIA KEY GOES HERE --- "; /* * We also indicate which camera on the RC that we wish to use. @@ -111,7 +110,12 @@ public class ConceptVuMarkIdentification extends LinearOpMode { * for a competition robot, the front camera might be more convenient. */ parameters.cameraDirection = VuforiaLocalizer.CameraDirection.BACK; - this.vuforia = ClassFactory.createVuforiaLocalizer(parameters); + + /** + * Instantiate the Vuforia engine + */ + vuforia = ClassFactory.getInstance().createVuforia(parameters); + /** * Load the data set containing the VuMarks for Relic Recovery. There's only one trackable diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuMarkIdentificationWebcam.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuMarkIdentificationWebcam.java new file mode 100644 index 00000000000..866261f223c --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuMarkIdentificationWebcam.java @@ -0,0 +1,194 @@ +/* Copyright (c) 2017 FIRST. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided that + * the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * Neither the name of FIRST nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS + * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.firstinspires.ftc.robotcontroller.external.samples; + +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; + +import org.firstinspires.ftc.robotcore.external.ClassFactory; +import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; +import org.firstinspires.ftc.robotcore.external.matrices.OpenGLMatrix; +import org.firstinspires.ftc.robotcore.external.matrices.VectorF; +import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; +import org.firstinspires.ftc.robotcore.external.navigation.AxesOrder; +import org.firstinspires.ftc.robotcore.external.navigation.AxesReference; +import org.firstinspires.ftc.robotcore.external.navigation.Orientation; +import org.firstinspires.ftc.robotcore.external.navigation.RelicRecoveryVuMark; +import org.firstinspires.ftc.robotcore.external.navigation.VuMarkInstanceId; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackable; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackableDefaultListener; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackables; + +/** + * This OpMode illustrates the basics of using the Vuforia engine to determine + * the identity of Vuforia VuMarks encountered on the field. The code is structured as + * a LinearOpMode. It shares much structure with {@link ConceptVuforiaNavigationWebcam}; we do not here + * duplicate the core Vuforia documentation found there, but rather instead focus on the + * differences between the use of Vuforia for navigation vs VuMark identification. + * + * @see ConceptVuforiaNavigationWebcam + * @see VuforiaLocalizer + * @see VuforiaTrackableDefaultListener + * see ftc_app/doc/tutorial/FTC_FieldCoordinateSystemDefinition.pdf + * + * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. + * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list. + * + * IMPORTANT: In order to use this OpMode, you need to obtain your own Vuforia license key as + * is explained in {@link ConceptVuforiaNavigationWebcam}. + */ + +@TeleOp(name="Concept: VuMark Id Webcam", group ="Concept") +@Disabled +public class ConceptVuMarkIdentificationWebcam extends LinearOpMode { + + public static final String TAG = "Vuforia VuMark Sample"; + + OpenGLMatrix lastLocation = null; + + /** + * {@link #vuforia} is the variable we will use to store our instance of the Vuforia + * localization engine. + */ + VuforiaLocalizer vuforia; + + /** + * This is the webcam we are to use. As with other hardware devices such as motors and + * servos, this device is identified using the robot configuration tool in the FTC application. + */ + WebcamName webcamName; + + @Override public void runOpMode() { + + /* + * Retrieve the camera we are to use. + */ + webcamName = hardwareMap.get(WebcamName.class, "Webcam 1"); + + /* + * To start up Vuforia, tell it the view that we wish to use for camera monitor (on the RC phone); + * If no camera monitor is desired, use the parameterless constructor instead (commented out below). + */ + int cameraMonitorViewId = hardwareMap.appContext.getResources().getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()); + VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(cameraMonitorViewId); + + // OR... Do Not Activate the Camera Monitor View, to save power + // VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(); + + /* + * IMPORTANT: You need to obtain your own license key to use Vuforia. The string below with which + * 'parameters.vuforiaLicenseKey' is initialized is for illustration only, and will not function. + * A Vuforia 'Development' license key, can be obtained free of charge from the Vuforia developer + * web site at https://developer.vuforia.com/license-manager. + * + * Vuforia license keys are always 380 characters long, and look as if they contain mostly + * random data. As an example, here is a example of a fragment of a valid key: + * ... yIgIzTqZ4mWjk9wd3cZO9T1axEqzuhxoGlfOOI2dRzKS4T0hQ8kT ... + * Once you've obtained a license key, copy the string from the Vuforia web site + * and paste it in to your code on the next line, between the double quotes. + */ + parameters.vuforiaLicenseKey = " -- YOUR NEW VUFORIA KEY GOES HERE --- "; + + + /** + * We also indicate which camera on the RC we wish to use. For pedagogical purposes, + * we use the same logic as in {@link ConceptVuforiaNavigationWebcam}. + */ + parameters.cameraName = webcamName; + this.vuforia = ClassFactory.getInstance().createVuforia(parameters); + + /** + * Load the data set containing the VuMarks for Relic Recovery. There's only one trackable + * in this data set: all three of the VuMarks in the game were created from this one template, + * but differ in their instance id information. + * @see VuMarkInstanceId + */ + VuforiaTrackables relicTrackables = this.vuforia.loadTrackablesFromAsset("RelicVuMark"); + VuforiaTrackable relicTemplate = relicTrackables.get(0); + relicTemplate.setName("relicVuMarkTemplate"); // can help in debugging; otherwise not necessary + + telemetry.addData(">", "Press Play to start"); + telemetry.update(); + waitForStart(); + + relicTrackables.activate(); + + while (opModeIsActive()) { + + /** + * See if any of the instances of {@link relicTemplate} are currently visible. + * {@link RelicRecoveryVuMark} is an enum which can have the following values: + * UNKNOWN, LEFT, CENTER, and RIGHT. When a VuMark is visible, something other than + * UNKNOWN will be returned by {@link RelicRecoveryVuMark#from(VuforiaTrackable)}. + */ + RelicRecoveryVuMark vuMark = RelicRecoveryVuMark.from(relicTemplate); + if (vuMark != RelicRecoveryVuMark.UNKNOWN) { + + /* Found an instance of the template. In the actual game, you will probably + * loop until this condition occurs, then move on to act accordingly depending + * on which VuMark was visible. */ + telemetry.addData("VuMark", "%s visible", vuMark); + + /* For fun, we also exhibit the navigational pose. In the Relic Recovery game, + * it is perhaps unlikely that you will actually need to act on this pose information, but + * we illustrate it nevertheless, for completeness. */ + OpenGLMatrix pose = ((VuforiaTrackableDefaultListener)relicTemplate.getListener()).getFtcCameraFromTarget(); + telemetry.addData("Pose", format(pose)); + + /* We further illustrate how to decompose the pose into useful rotational and + * translational components */ + if (pose != null) { + VectorF trans = pose.getTranslation(); + Orientation rot = Orientation.getOrientation(pose, AxesReference.EXTRINSIC, AxesOrder.XYZ, AngleUnit.DEGREES); + + // Extract the X, Y, and Z components of the offset of the target relative to the robot + double tX = trans.get(0); + double tY = trans.get(1); + double tZ = trans.get(2); + + // Extract the rotational components of the target relative to the robot + double rX = rot.firstAngle; + double rY = rot.secondAngle; + double rZ = rot.thirdAngle; + } + } + else { + telemetry.addData("VuMark", "not visible"); + } + + telemetry.update(); + } + } + + String format(OpenGLMatrix transformationMatrix) { + return (transformationMatrix != null) ? transformationMatrix.formatAsTransform() : "null"; + } +} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavRoverRuckus.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavRoverRuckus.java new file mode 100644 index 00000000000..eb21cf78e9f --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavRoverRuckus.java @@ -0,0 +1,311 @@ +/* Copyright (c) 2018 FIRST. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided that + * the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * Neither the name of FIRST nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS + * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.firstinspires.ftc.robotcontroller.external.samples; + +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; + +import org.firstinspires.ftc.robotcore.external.ClassFactory; +import org.firstinspires.ftc.robotcore.external.matrices.OpenGLMatrix; +import org.firstinspires.ftc.robotcore.external.matrices.VectorF; +import org.firstinspires.ftc.robotcore.external.navigation.Orientation; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackable; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackableDefaultListener; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackables; + +import static org.firstinspires.ftc.robotcore.external.navigation.AngleUnit.DEGREES; +import static org.firstinspires.ftc.robotcore.external.navigation.AxesOrder.XYZ; +import static org.firstinspires.ftc.robotcore.external.navigation.AxesOrder.YZX; +import static org.firstinspires.ftc.robotcore.external.navigation.AxesReference.EXTRINSIC; +import static org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer.CameraDirection.BACK; +import static org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer.CameraDirection.FRONT; + +import java.util.ArrayList; +import java.util.List; + + +/** + * This 2018-2019 OpMode illustrates the basics of using the Vuforia localizer to determine + * positioning and orientation of robot on the FTC field. + * The code is structured as a LinearOpMode + * + * Vuforia uses the phone's camera to inspect it's surroundings, and attempt to locate target images. + * + * When images are located, Vuforia is able to determine the position and orientation of the + * image relative to the camera. This sample code than combines that information with a + * knowledge of where the target images are on the field, to determine the location of the camera. + * + * This example assumes a "square" field configuration where the red and blue alliance stations + * are on opposite walls of each other. + * + * From the Audience perspective, the Red Alliance station is on the right and the + * Blue Alliance Station is on the left. + + * The four vision targets are located in the center of each of the perimeter walls with + * the images facing inwards towards the robots: + * - BlueRover is the Mars Rover image target on the wall closest to the blue alliance + * - RedFootprint is the Lunar Footprint target on the wall closest to the red alliance + * - FrontCraters is the Lunar Craters image target on the wall closest to the audience + * - BackSpace is the Deep Space image target on the wall farthest from the audience + * + * A final calculation then uses the location of the camera on the robot to determine the + * robot's location and orientation on the field. + * + * @see VuforiaLocalizer + * @see VuforiaTrackableDefaultListener + * see ftc_app/doc/tutorial/FTC_FieldCoordinateSystemDefinition.pdf + * + * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. + * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list. + * + * IMPORTANT: In order to use this OpMode, you need to obtain your own Vuforia license key as + * is explained below. + */ + +@TeleOp(name="Concept: Vuforia Rover Nav", group ="Concept") +@Disabled +public class ConceptVuforiaNavRoverRuckus extends LinearOpMode { + + /* + * IMPORTANT: You need to obtain your own license key to use Vuforia. The string below with which + * 'parameters.vuforiaLicenseKey' is initialized is for illustration only, and will not function. + * A Vuforia 'Development' license key, can be obtained free of charge from the Vuforia developer + * web site at https://developer.vuforia.com/license-manager. + * + * Vuforia license keys are always 380 characters long, and look as if they contain mostly + * random data. As an example, here is a example of a fragment of a valid key: + * ... yIgIzTqZ4mWjk9wd3cZO9T1axEqzuhxoGlfOOI2dRzKS4T0hQ8kT ... + * Once you've obtained a license key, copy the string from the Vuforia web site + * and paste it in to your code on the next line, between the double quotes. + */ + private static final String VUFORIA_KEY = " -- YOUR NEW VUFORIA KEY GOES HERE --- "; + + // Since ImageTarget trackables use mm to specifiy their dimensions, we must use mm for all the physical dimension. + // We will define some constants and conversions here + private static final float mmPerInch = 25.4f; + private static final float mmFTCFieldWidth = (12*6) * mmPerInch; // the width of the FTC field (from the center point to the outer panels) + private static final float mmTargetHeight = (6) * mmPerInch; // the height of the center of the target image above the floor + + // Select which camera you want use. The FRONT camera is the one on the same side as the screen. + // Valid choices are: BACK or FRONT + private static final VuforiaLocalizer.CameraDirection CAMERA_CHOICE = BACK; + + private OpenGLMatrix lastLocation = null; + private boolean targetVisible = false; + + /** + * {@link #vuforia} is the variable we will use to store our instance of the Vuforia + * localization engine. + */ + VuforiaLocalizer vuforia; + + @Override public void runOpMode() { + /* + * Configure Vuforia by creating a Parameter object, and passing it to the Vuforia engine. + * We can pass Vuforia the handle to a camera preview resource (on the RC phone); + * If no camera monitor is desired, use the parameterless constructor instead (commented out below). + */ + int cameraMonitorViewId = hardwareMap.appContext.getResources().getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()); + VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(cameraMonitorViewId); + + // VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(); + + parameters.vuforiaLicenseKey = VUFORIA_KEY ; + parameters.cameraDirection = CAMERA_CHOICE; + + // Instantiate the Vuforia engine + vuforia = ClassFactory.getInstance().createVuforia(parameters); + + // Load the data sets that for the trackable objects. These particular data + // sets are stored in the 'assets' part of our application. + VuforiaTrackables targetsRoverRuckus = this.vuforia.loadTrackablesFromAsset("RoverRuckus"); + VuforiaTrackable blueRover = targetsRoverRuckus.get(0); + blueRover.setName("Blue-Rover"); + VuforiaTrackable redFootprint = targetsRoverRuckus.get(1); + redFootprint.setName("Red-Footprint"); + VuforiaTrackable frontCraters = targetsRoverRuckus.get(2); + frontCraters.setName("Front-Craters"); + VuforiaTrackable backSpace = targetsRoverRuckus.get(3); + backSpace.setName("Back-Space"); + + // For convenience, gather together all the trackable objects in one easily-iterable collection */ + List allTrackables = new ArrayList(); + allTrackables.addAll(targetsRoverRuckus); + + /** + * In order for localization to work, we need to tell the system where each target is on the field, and + * where the phone resides on the robot. These specifications are in the form of transformation matrices. + * Transformation matrices are a central, important concept in the math here involved in localization. + * See Transformation Matrix + * for detailed information. Commonly, you'll encounter transformation matrices as instances + * of the {@link OpenGLMatrix} class. + * + * If you are standing in the Red Alliance Station looking towards the center of the field, + * - The X axis runs from your left to the right. (positive from the center to the right) + * - The Y axis runs from the Red Alliance Station towards the other side of the field + * where the Blue Alliance Station is. (Positive is from the center, towards the BlueAlliance station) + * - The Z axis runs from the floor, upwards towards the ceiling. (Positive is above the floor) + * + * This Rover Ruckus sample places a specific target in the middle of each perimeter wall. + * + * Before being transformed, each target image is conceptually located at the origin of the field's + * coordinate system (the center of the field), facing up. + */ + + /** + * To place the BlueRover target in the middle of the blue perimeter wall: + * - First we rotate it 90 around the field's X axis to flip it upright. + * - Then, we translate it along the Y axis to the blue perimeter wall. + */ + OpenGLMatrix blueRoverLocationOnField = OpenGLMatrix + .translation(0, mmFTCFieldWidth, mmTargetHeight) + .multiplied(Orientation.getRotationMatrix(EXTRINSIC, XYZ, DEGREES, 90, 0, 0)); + blueRover.setLocation(blueRoverLocationOnField); + + /** + * To place the RedFootprint target in the middle of the red perimeter wall: + * - First we rotate it 90 around the field's X axis to flip it upright. + * - Second, we rotate it 180 around the field's Z axis so the image is flat against the red perimeter wall + * and facing inwards to the center of the field. + * - Then, we translate it along the negative Y axis to the red perimeter wall. + */ + OpenGLMatrix redFootprintLocationOnField = OpenGLMatrix + .translation(0, -mmFTCFieldWidth, mmTargetHeight) + .multiplied(Orientation.getRotationMatrix(EXTRINSIC, XYZ, DEGREES, 90, 0, 180)); + redFootprint.setLocation(redFootprintLocationOnField); + + /** + * To place the FrontCraters target in the middle of the front perimeter wall: + * - First we rotate it 90 around the field's X axis to flip it upright. + * - Second, we rotate it 90 around the field's Z axis so the image is flat against the front wall + * and facing inwards to the center of the field. + * - Then, we translate it along the negative X axis to the front perimeter wall. + */ + OpenGLMatrix frontCratersLocationOnField = OpenGLMatrix + .translation(-mmFTCFieldWidth, 0, mmTargetHeight) + .multiplied(Orientation.getRotationMatrix(EXTRINSIC, XYZ, DEGREES, 90, 0 , 90)); + frontCraters.setLocation(frontCratersLocationOnField); + + /** + * To place the BackSpace target in the middle of the back perimeter wall: + * - First we rotate it 90 around the field's X axis to flip it upright. + * - Second, we rotate it -90 around the field's Z axis so the image is flat against the back wall + * and facing inwards to the center of the field. + * - Then, we translate it along the X axis to the back perimeter wall. + */ + OpenGLMatrix backSpaceLocationOnField = OpenGLMatrix + .translation(mmFTCFieldWidth, 0, mmTargetHeight) + .multiplied(Orientation.getRotationMatrix(EXTRINSIC, XYZ, DEGREES, 90, 0, -90)); + backSpace.setLocation(backSpaceLocationOnField); + + /** + * Create a transformation matrix describing where the phone is on the robot. + * + * The coordinate frame for the robot looks the same as the field. + * The robot's "forward" direction is facing out along X axis, with the LEFT side facing out along the Y axis. + * Z is UP on the robot. This equates to a bearing angle of Zero degrees. + * + * The phone starts out lying flat, with the screen facing Up and with the physical top of the phone + * pointing to the LEFT side of the Robot. It's very important when you test this code that the top of the + * camera is pointing to the left side of the robot. The rotation angles don't work if you flip the phone. + * + * If using the rear (High Res) camera: + * We need to rotate the camera around it's long axis to bring the rear camera forward. + * This requires a negative 90 degree rotation on the Y axis + * + * If using the Front (Low Res) camera + * We need to rotate the camera around it's long axis to bring the FRONT camera forward. + * This requires a Positive 90 degree rotation on the Y axis + * + * Next, translate the camera lens to where it is on the robot. + * In this example, it is centered (left to right), but 110 mm forward of the middle of the robot, and 200 mm above ground level. + */ + + final int CAMERA_FORWARD_DISPLACEMENT = 110; // eg: Camera is 110 mm in front of robot center + final int CAMERA_VERTICAL_DISPLACEMENT = 200; // eg: Camera is 200 mm above ground + final int CAMERA_LEFT_DISPLACEMENT = 0; // eg: Camera is ON the robot's center line + + OpenGLMatrix phoneLocationOnRobot = OpenGLMatrix + .translation(CAMERA_FORWARD_DISPLACEMENT, CAMERA_LEFT_DISPLACEMENT, CAMERA_VERTICAL_DISPLACEMENT) + .multiplied(Orientation.getRotationMatrix(EXTRINSIC, YZX, DEGREES, + CAMERA_CHOICE == FRONT ? 90 : -90, 0, 0)); + + /** Let all the trackable listeners know where the phone is. */ + for (VuforiaTrackable trackable : allTrackables) + { + ((VuforiaTrackableDefaultListener)trackable.getListener()).setPhoneInformation(phoneLocationOnRobot, parameters.cameraDirection); + } + + /** Wait for the game to begin */ + telemetry.addData(">", "Press Play to start tracking"); + telemetry.update(); + waitForStart(); + + /** Start tracking the data sets we care about. */ + targetsRoverRuckus.activate(); + while (opModeIsActive()) { + + // check all the trackable target to see which one (if any) is visible. + targetVisible = false; + for (VuforiaTrackable trackable : allTrackables) { + if (((VuforiaTrackableDefaultListener)trackable.getListener()).isVisible()) { + telemetry.addData("Visible Target", trackable.getName()); + targetVisible = true; + + // getUpdatedRobotLocation() will return null if no new information is available since + // the last time that call was made, or if the trackable is not currently visible. + OpenGLMatrix robotLocationTransform = ((VuforiaTrackableDefaultListener)trackable.getListener()).getUpdatedRobotLocation(); + if (robotLocationTransform != null) { + lastLocation = robotLocationTransform; + } + break; + } + } + + // Provide feedback as to where the robot is located (if we know). + if (targetVisible) { + // express position (translation) of robot in inches. + VectorF translation = lastLocation.getTranslation(); + telemetry.addData("Pos (in)", "{X, Y, Z} = %.1f, %.1f, %.1f", + translation.get(0) / mmPerInch, translation.get(1) / mmPerInch, translation.get(2) / mmPerInch); + + // express the rotation of the robot in degrees. + Orientation rotation = Orientation.getOrientation(lastLocation, EXTRINSIC, XYZ, DEGREES); + telemetry.addData("Rot (deg)", "{Roll, Pitch, Heading} = %.0f, %.0f, %.0f", rotation.firstAngle, rotation.secondAngle, rotation.thirdAngle); + } + else { + telemetry.addData("Visible Target", "none"); + } + telemetry.update(); + } + } +} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavigation.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavigation.java index 0fb2c42ceb5..81ab6b68331 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavigation.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavigation.java @@ -29,7 +29,7 @@ package org.firstinspires.ftc.robotcontroller.external.samples; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; import com.qualcomm.robotcore.util.RobotLog; @@ -80,7 +80,7 @@ * is explained below. */ -@Autonomous(name="Concept: Vuforia Navigation", group ="Concept") +@TeleOp(name="Concept: Vuforia Navigation", group ="Concept") @Disabled public class ConceptVuforiaNavigation extends LinearOpMode { @@ -115,9 +115,9 @@ public class ConceptVuforiaNavigation extends LinearOpMode { * random data. As an example, here is a example of a fragment of a valid key: * ... yIgIzTqZ4mWjk9wd3cZO9T1axEqzuhxoGlfOOI2dRzKS4T0hQ8kT ... * Once you've obtained a license key, copy the string from the Vuforia web site - * and paste it in to your code onthe next line, between the double quotes. + * and paste it in to your code on the next line, between the double quotes. */ - parameters.vuforiaLicenseKey = "ATsODcD/////AAAAAVw2lR...d45oGpdljdOh5LuFB9nDNfckoxb8COxKSFX"; + parameters.vuforiaLicenseKey = " -- YOUR NEW VUFORIA KEY GOES HERE --- "; /* * We also indicate which camera on the RC that we wish to use. @@ -125,7 +125,11 @@ public class ConceptVuforiaNavigation extends LinearOpMode { * for a competition robot, the front camera might be more convenient. */ parameters.cameraDirection = VuforiaLocalizer.CameraDirection.BACK; - this.vuforia = ClassFactory.createVuforiaLocalizer(parameters); + + /** + * Instantiate the Vuforia engine + */ + vuforia = ClassFactory.getInstance().createVuforia(parameters); /** * Load the data sets that for the trackable objects we wish to track. These particular data diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavigationWebcam.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavigationWebcam.java new file mode 100644 index 00000000000..1b619f3dea5 --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVuforiaNavigationWebcam.java @@ -0,0 +1,461 @@ +/* Copyright (c) 2017 FIRST. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted (subject to the limitations in the disclaimer below) provided that + * the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * Neither the name of FIRST nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS + * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.firstinspires.ftc.robotcontroller.external.samples; + +import android.graphics.Bitmap; + +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.util.RobotLog; +import com.qualcomm.robotcore.util.ThreadPool; +import com.vuforia.Frame; + +import org.firstinspires.ftc.robotcore.external.ClassFactory; +import org.firstinspires.ftc.robotcore.external.function.Consumer; +import org.firstinspires.ftc.robotcore.external.function.Continuation; +import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; +import org.firstinspires.ftc.robotcore.external.matrices.MatrixF; +import org.firstinspires.ftc.robotcore.external.matrices.OpenGLMatrix; +import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; +import org.firstinspires.ftc.robotcore.external.navigation.AxesOrder; +import org.firstinspires.ftc.robotcore.external.navigation.AxesReference; +import org.firstinspires.ftc.robotcore.external.navigation.Orientation; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackable; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackableDefaultListener; +import org.firstinspires.ftc.robotcore.external.navigation.VuforiaTrackables; +import org.firstinspires.ftc.robotcore.internal.system.AppUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** + * This 2016-2017 OpMode illustrates the basics of using the Vuforia localizer to determine + * positioning and orientation of robot on the FTC field. + * The code is structured as a LinearOpMode + * + * Vuforia uses the phone's camera to inspect it's surroundings, and attempt to locate target images. + * + * When images are located, Vuforia is able to determine the position and orientation of the + * image relative to the camera. This sample code than combines that information with a + * knowledge of where the target images are on the field, to determine the location of the camera. + * + * This example assumes a "diamond" field configuration where the red and blue alliance stations + * are adjacent on the corner of the field furthest from the audience. + * From the Audience perspective, the Red driver station is on the right. + * The two vision target are located on the two walls closest to the audience, facing in. + * The Stones are on the RED side of the field, and the Chips are on the Blue side. + * + * A final calculation then uses the location of the camera on the robot to determine the + * robot's location and orientation on the field. + * + * @see VuforiaLocalizer + * @see VuforiaTrackableDefaultListener + * see ftc_app/doc/tutorial/FTC_FieldCoordinateSystemDefinition.pdf + * + * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. + * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list. + * + * IMPORTANT: In order to use this OpMode, you need to obtain your own Vuforia license key as + * is explained below. + */ + +@TeleOp(name="Concept: Vuforia Nav Webcam", group ="Concept") +@Disabled +public class ConceptVuforiaNavigationWebcam extends LinearOpMode { + + public static final String TAG = "Vuforia Navigation Sample"; + + OpenGLMatrix lastLocation = null; + + /** + * @see #captureFrameToFile() + */ + int captureCounter = 0; + File captureDirectory = AppUtil.ROBOT_DATA_DIR; + + /** + * {@link #vuforia} is the variable we will use to store our instance of the Vuforia + * localization engine. + */ + VuforiaLocalizer vuforia; + + /** + * This is the webcam we are to use. As with other hardware devices such as motors and + * servos, this device is identified using the robot configuration tool in the FTC application. + */ + WebcamName webcamName; + + @Override public void runOpMode() { + + /* + * Retrieve the camera we are to use. + */ + webcamName = hardwareMap.get(WebcamName.class, "Webcam 1"); + + /* + * To start up Vuforia, tell it the view that we wish to use for camera monitor (on the RC phone); + * If no camera monitor is desired, use the parameterless constructor instead (commented out below). + */ + int cameraMonitorViewId = hardwareMap.appContext.getResources().getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()); + VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(cameraMonitorViewId); + + // OR... Do Not Activate the Camera Monitor View, to save power + // VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters(); + + /* + * IMPORTANT: You need to obtain your own license key to use Vuforia. The string below with which + * 'parameters.vuforiaLicenseKey' is initialized is for illustration only, and will not function. + * A Vuforia 'Development' license key, can be obtained free of charge from the Vuforia developer + * web site at https://developer.vuforia.com/license-manager. + * + * Vuforia license keys are always 380 characters long, and look as if they contain mostly + * random data. As an example, here is a example of a fragment of a valid key: + * ... yIgIzTqZ4mWjk9wd3cZO9T1axEqzuhxoGlfOOI2dRzKS4T0hQ8kT ... + * Once you've obtained a license key, copy the string from the Vuforia web site + * and paste it in to your code on the next line, between the double quotes. + */ + parameters.vuforiaLicenseKey = " -- YOUR NEW VUFORIA KEY GOES HERE --- "; + + /** + * We also indicate which camera on the RC we wish to use. + */ + parameters.cameraName = webcamName; + + /** + * Instantiate the Vuforia engine + */ + vuforia = ClassFactory.getInstance().createVuforia(parameters); + + /** + * Because this opmode processes frames in order to write them to a file, we tell Vuforia + * that we want to ensure that certain frame formats are available in the {@link Frame}s we + * see. + */ + vuforia.enableConvertFrameToBitmap(); + + /** @see #captureFrameToFile() */ + AppUtil.getInstance().ensureDirectoryExists(captureDirectory); + + + /** + * Load the data sets that for the trackable objects we wish to track. These particular data + * sets are stored in the 'assets' part of our application (you'll see them in the Android + * Studio 'Project' view over there on the left of the screen). You can make your own datasets + * with the Vuforia Target Manager: https://developer.vuforia.com/target-manager. PDFs for the + * example "StonesAndChips", datasets can be found in in this project in the + * documentation directory. + */ + VuforiaTrackables stonesAndChips = vuforia.loadTrackablesFromAsset("StonesAndChips"); + VuforiaTrackable redTarget = stonesAndChips.get(0); + redTarget.setName("RedTarget"); // Stones + + VuforiaTrackable blueTarget = stonesAndChips.get(1); + blueTarget.setName("BlueTarget"); // Chips + + /** For convenience, gather together all the trackable objects in one easily-iterable collection */ + List allTrackables = new ArrayList(); + allTrackables.addAll(stonesAndChips); + + /** + * We use units of mm here because that's the recommended units of measurement for the + * size values specified in the XML for the ImageTarget trackables in data sets. E.g.: + * + * You don't *have to* use mm here, but the units here and the units used in the XML + * target configuration files *must* correspond for the math to work out correctly. + */ + float mmPerInch = 25.4f; + float mmBotWidth = 18 * mmPerInch; // ... or whatever is right for your robot + float mmFTCFieldWidth = (12*12 - 2) * mmPerInch; // the FTC field is ~11'10" center-to-center of the glass panels + + /** + * In order for localization to work, we need to tell the system where each target we + * wish to use for navigation resides on the field, and we need to specify where on the robot + * the camera resides. These specifications are in the form of transformation matrices. + * Transformation matrices are a central, important concept in the math here involved in localization. + * See Transformation Matrix + * for detailed information. Commonly, you'll encounter transformation matrices as instances + * of the {@link OpenGLMatrix} class. + * + * For the most part, you don't need to understand the details of the math of how transformation + * matrices work inside (as fascinating as that is, truly). Just remember these key points: + *
    + * + *
  1. You can put two transformations together to produce a third that combines the effect of + * both of them. If, for example, you have a rotation transform R and a translation transform T, + * then the combined transformation matrix RT which does the rotation first and then the translation + * is given by {@code RT = T.multiplied(R)}. That is, the transforms are multiplied in the + * reverse of the chronological order in which they applied.
  2. + * + *
  3. A common way to create useful transforms is to use methods in the {@link OpenGLMatrix} + * class and the Orientation class. See, for example, {@link OpenGLMatrix#translation(float, + * float, float)}, {@link OpenGLMatrix#rotation(AngleUnit, float, float, float, float)}, and + * {@link Orientation#getRotationMatrix(AxesReference, AxesOrder, AngleUnit, float, float, float)}. + * Related methods in {@link OpenGLMatrix}, such as {@link OpenGLMatrix#rotated(AngleUnit, + * float, float, float, float)}, are syntactic shorthands for creating a new transform and + * then immediately multiplying the receiver by it, which can be convenient at times.
  4. + * + *
  5. If you want to break open the black box of a transformation matrix to understand + * what it's doing inside, use {@link MatrixF#getTranslation()} to fetch how much the + * transform will move you in x, y, and z, and use {@link Orientation#getOrientation(MatrixF, + * AxesReference, AxesOrder, AngleUnit)} to determine the rotational motion that the transform + * will impart. See {@link #format(OpenGLMatrix)} below for an example.
  6. + * + *
+ * + * This example places the "stones" image on the perimeter wall to the Left + * of the Red Driver station wall. Similar to the Red Beacon Location on the Res-Q + * + * This example places the "chips" image on the perimeter wall to the Right + * of the Blue Driver station. Similar to the Blue Beacon Location on the Res-Q + * + * See the doc folder of this project for a description of the Field Coordinate System + * conventions. + * + * Initially the target is conceptually lying at the origin of the Field Coordinate System + * (the center of the field), facing up. + * + * In this configuration, the target's coordinate system aligns with that of the field. + * + * In a real situation we'd also account for the vertical (Z) offset of the target, + * but for simplicity, we ignore that here; for a real robot, you'll want to fix that. + * + * To place the Stones Target on the Red Audience wall: + * - First we rotate it 90 around the field's X axis to flip it upright + * - Then we rotate it 90 around the field's Z access to face it away from the audience. + * - Finally, we translate it back along the X axis towards the red audience wall. + */ + OpenGLMatrix redTargetLocationOnField = OpenGLMatrix + /* Then we translate the target off to the RED WALL. Our translation here + is a negative translation in X.*/ + .translation(-mmFTCFieldWidth/2, 0, 0) + .multiplied(Orientation.getRotationMatrix( + /* First, in the fixed (field) coordinate system, we rotate 90deg in X, then 90 in Z */ + AxesReference.EXTRINSIC, AxesOrder.XZX, + AngleUnit.DEGREES, 90, 90, 0)); + redTarget.setLocationFtcFieldFromTarget(redTargetLocationOnField); + RobotLog.ii(TAG, "Red Target=%s", format(redTargetLocationOnField)); + + /* + * To place the Stones Target on the Blue Audience wall: + * - First we rotate it 90 around the field's X axis to flip it upright + * - Finally, we translate it along the Y axis towards the blue audience wall. + */ + OpenGLMatrix blueTargetLocationOnField = OpenGLMatrix + /* Then we translate the target off to the Blue Audience wall. + Our translation here is a positive translation in Y.*/ + .translation(0, mmFTCFieldWidth/2, 0) + .multiplied(Orientation.getRotationMatrix( + /* First, in the fixed (field) coordinate system, we rotate 90deg in X */ + AxesReference.EXTRINSIC, AxesOrder.XZX, + AngleUnit.DEGREES, 90, 0, 0)); + blueTarget.setLocationFtcFieldFromTarget(blueTargetLocationOnField); + RobotLog.ii(TAG, "Blue Target=%s", format(blueTargetLocationOnField)); + + /** + * We also need to tell Vuforia where the cameras are relative to the robot. + * + * Just as there is a Field Coordinate System, so too there is a Robot Coordinate System. + * The two share many similarities. The origin of the Robot Coordinate System is wherever + * you choose to make it on the robot, but typically you'd choose somewhere in the middle + * of the robot. From that origin, the Y axis is horizontal and positive out towards the + * "front" of the robot (however you choose "front" to be defined), the X axis is horizontal + * and positive out towards the "right" of the robot (i.e.: 90deg horizontally clockwise from + * the positive Y axis), and the Z axis is vertical towards the sky. + * + * Similarly, for each camera there is a Camera Coordinate System. The origin of a Camera + * Coordinate System lies in the middle of the sensor inside of the camera. The Z axis is + * positive coming out of the lens of the camera in a direction perpendicular to the plane + * of the sensor. When looking at the face of the lens of the camera (down the positive Z + * axis), the X axis is positive off to the right in the plane of the sensor, and the Y axis + * is positive out the top of the lens in the plane of the sensor at 90 horizontally + * counter clockwise from the X axis. + * + * Next, there is Phone Coordinate System (for robots that have phones, of course), though + * with the advent of Vuforia support for Webcams, this coordinate system is less significant + * than it was previously. The Phone Coordinate System is defined thusly: with the phone in + * flat front of you in portrait mode (i.e. as it is when running the robot controller app) + * and you are staring straight at the face of the phone, + * * X is positive heading off to your right, + * * Y is positive heading up through the top edge of the phone, and + * * Z is pointing out of the screen, toward you. + * The origin of the Phone Coordinate System is at the origin of the Camera Coordinate System + * of the front-facing camera on the phone. + * + * Finally, it is worth noting that trackable Vuforia Image Targets have their own + * coordinate system (see {@link VuforiaTrackable}. This is sometimes referred to as the + * Target Coordinate System. In keeping with the above, when looking at the target in its + * natural orientation, in the Target Coodinate System + * * X is positive heading off to your right, + * * Y is positive heading up through the top edge of the target, and + * * Z is pointing out of the target, toward you. + * + * One can observe that the Camera Coordinate System of the front-facing camera on a phone + * coincides with the Phone Coordinate System. Further, when a phone is placed on its back + * at the origin of the Robot Coordinate System and aligned appropriately, those coordinate + * systems also coincide with the Robot Coordinate System. Got it? + * + * In this example here, we're going to assume that we put the camera on the right side + * of the robot (facing outwards, of course). To determine the transformation matrix that + * describes that location, first consider the camera as lying on its back at the origin + * of the Robot Coordinate System such that the Camera Coordinate System and Robot Coordinate + * System coincide. Then the transformation we need is + * * first a rotation of the camera by +90deg along the robot X axis, + * * then a rotation of the camera by +90deg along the robot Z axis, and + * * finally a translation of the camera to the side of the robot. + * + * When determining whether a rotation is positive or negative, consider yourself as looking + * down the (positive) axis of rotation from the positive towards the origin. Positive rotations + * are then CCW, and negative rotations CW. An example: consider looking down the positive Z + * axis towards the origin. A positive rotation about Z (ie: a rotation parallel to the the X-Y + * plane) is then CCW, as one would normally expect from the usual classic 2D geometry. + */ + + OpenGLMatrix robotFromCamera = OpenGLMatrix + .translation(mmBotWidth/2,0,0) + .multiplied(Orientation.getRotationMatrix( + AxesReference.EXTRINSIC, AxesOrder.XZY, + AngleUnit.DEGREES, 90, 90, 0)); + RobotLog.ii(TAG, "camera=%s", format(robotFromCamera)); + + /** + * Let the trackable listeners we care about know where the camera is. We know that each + * listener is a {@link VuforiaTrackableDefaultListener} and can so safely cast because + * we have not ourselves installed a listener of a different type. + */ + ((VuforiaTrackableDefaultListener)redTarget.getListener()).setCameraLocationOnRobot(parameters.cameraName, robotFromCamera); + ((VuforiaTrackableDefaultListener)blueTarget.getListener()).setCameraLocationOnRobot(parameters.cameraName, robotFromCamera); + + /** + * A brief tutorial: here's how all the math is going to work: + * + * C = robotFromCamera maps camera coords -> robot coords + * P = tracker.getPose() maps image target coords -> camera coords + * L = redTargetLocationOnField maps image target coords -> field coords + * + * So + * + * C.inverted() maps robot coords -> camera coords + * P.inverted() maps camera coords -> imageTarget coords + * + * Putting that all together, + * + * L x P.inverted() x C.inverted() maps robot coords to field coords. + * + * @see VuforiaTrackableDefaultListener#getRobotLocation() + */ + + /** Wait for the game to begin */ + telemetry.addData(">", "Press Play to start tracking"); + telemetry.update(); + waitForStart(); + + /** Start tracking the data sets we care about. */ + stonesAndChips.activate(); + + boolean buttonPressed = false; + while (opModeIsActive()) { + + if (gamepad1.a && !buttonPressed) { + captureFrameToFile(); + } + buttonPressed = gamepad1.a; + + for (VuforiaTrackable trackable : allTrackables) { + /** + * getUpdatedRobotLocation() will return null if no new information is available since + * the last time that call was made, or if the trackable is not currently visible. + * getRobotLocation() will return null if the trackable is not currently visible. + */ + telemetry.addData(trackable.getName(), ((VuforiaTrackableDefaultListener)trackable.getListener()).isVisible() ? "Visible" : "Not Visible"); // + + OpenGLMatrix robotLocationTransform = ((VuforiaTrackableDefaultListener)trackable.getListener()).getUpdatedRobotLocation(); + if (robotLocationTransform != null) { + lastLocation = robotLocationTransform; + } + } + /** + * Provide feedback as to where the robot was last located (if we know). + */ + if (lastLocation != null) { + // RobotLog.vv(TAG, "robot=%s", format(lastLocation)); + telemetry.addData("Pos", format(lastLocation)); + } else { + telemetry.addData("Pos", "Unknown"); + } + telemetry.update(); + } + } + + /** + * A simple utility that extracts positioning information from a transformation matrix + * and formats it in a form palatable to a human being. + */ + String format(OpenGLMatrix transformationMatrix) { + return transformationMatrix.formatAsTransform(); + } + + /** + * Sample one frame from the Vuforia stream and write it to a .PNG image file on the robot + * controller in the /sdcard/FIRST/data directory. The images can be downloaded using Android + * Studio's Device File Explorer, ADB, or the Media Transfer Protocol (MTP) integration into + * Windows Explorer, among other means. The images can be useful during robot design and calibration + * in order to get a sense of what the camera is actually seeing and so assist in camera + * aiming and alignment. + */ + void captureFrameToFile() { + vuforia.getFrameOnce(Continuation.create(ThreadPool.getDefault(), new Consumer() + { + @Override public void accept(Frame frame) + { + Bitmap bitmap = vuforia.convertFrameToBitmap(frame); + if (bitmap != null) { + File file = new File(captureDirectory, String.format(Locale.getDefault(), "VuforiaFrame-%d.png", captureCounter++)); + try { + FileOutputStream outputStream = new FileOutputStream(file); + try { + bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); + } finally { + outputStream.close(); + telemetry.log().add("captured %s", file.getName()); + } + } catch (IOException e) { + RobotLog.ee(TAG, e, "exception in captureFrameToFile()"); + } + } + } + })); + } +} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/HardwareK9bot.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/HardwareK9bot.java deleted file mode 100644 index bf5aa820be2..00000000000 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/HardwareK9bot.java +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (c) 2017 FIRST. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted (subject to the limitations in the disclaimer below) provided that - * the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * Neither the name of FIRST nor the names of its contributors may be used to endorse or - * promote products derived from this software without specific prior written permission. - * - * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS - * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.hardware.HardwareMap; -import com.qualcomm.robotcore.hardware.Servo; -import com.qualcomm.robotcore.util.ElapsedTime; - -/** - * This is NOT an opmode. - * - * This class can be used to define all the specific hardware for a single robot. - * In this case that robot is a K9 robot. - * - * This hardware class assumes the following device names have been configured on the robot: - * Note: All names are lower case and some have single spaces between words. - * - * Motor channel: Left drive motor: "left_drive" - * Motor channel: Right drive motor: "right_drive" - * Servo channel: Servo to raise/lower arm: "arm" - * Servo channel: Servo to open/close claw: "claw" - * - * Note: the configuration of the servos is such that: - * As the arm servo approaches 0, the arm position moves up (away from the floor). - * As the claw servo approaches 0, the claw opens up (drops the game element). - */ -public class HardwareK9bot -{ - /* Public OpMode members. */ - public DcMotor leftDrive = null; - public DcMotor rightDrive = null; - public Servo arm = null; - public Servo claw = null; - - public final static double ARM_HOME = 0.2; - public final static double CLAW_HOME = 0.2; - public final static double ARM_MIN_RANGE = 0.20; - public final static double ARM_MAX_RANGE = 0.90; - public final static double CLAW_MIN_RANGE = 0.20; - public final static double CLAW_MAX_RANGE = 0.7; - - /* Local OpMode members. */ - HardwareMap hwMap = null; - private ElapsedTime period = new ElapsedTime(); - - /* Constructor */ - public HardwareK9bot() { - } - - /* Initialize standard Hardware interfaces */ - public void init(HardwareMap ahwMap) { - // save reference to HW Map - hwMap = ahwMap; - - // Define and Initialize Motors - leftDrive = hwMap.get(DcMotor.class, "left_drive"); - rightDrive = hwMap.get(DcMotor.class, "right_drive"); - leftDrive.setDirection(DcMotor.Direction.REVERSE); - - // Set all motors to zero power - leftDrive.setPower(0); - rightDrive.setPower(0); - - // Set all motors to run without encoders. - // May want to use RUN_USING_ENCODERS if encoders are installed. - leftDrive.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER); - rightDrive.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER); - - // Define and initialize ALL installed servos. - arm = hwMap.get(Servo.class, "arm"); - claw = hwMap.get(Servo.class, "claw"); - arm.setPosition(ARM_HOME); - claw.setPosition(CLAW_HOME); - } -} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/HardwarePushbotMatrix.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/HardwarePushbotMatrix.java deleted file mode 100644 index 3dafa8f3060..00000000000 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/HardwarePushbotMatrix.java +++ /dev/null @@ -1,103 +0,0 @@ -/* Copyright (c) 2017 FIRST. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted (subject to the limitations in the disclaimer below) provided that - * the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * Neither the name of FIRST nor the names of its contributors may be used to endorse or - * promote products derived from this software without specific prior written permission. - * - * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS - * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.hardware.matrix.MatrixDcMotorController; -import com.qualcomm.robotcore.hardware.HardwareMap; -import com.qualcomm.robotcore.hardware.ServoController; - -/** - * This is NOT an OpMode - * This class can be used to define all the specific hardware for a single robot. - * In this case that robot is a Pushbot, using Matrix Hardware. - * See PushbotTeleopTank_Iterative for a usage examples. - * - * This is coded as an Extension of HardwarePushbot to illustrate that the only additional - * action REQUIRED for a MATRIX controller is enabling the Servos. - * - * This hardware class assumes the following device names have been configured on the robot: - * Note: All names are lower case and some have single spaces between words. - * - * Matrix Controller has been assigned the name: "matrix controller" - * - * Motor channel: Left drive motor: "left_drive" - * Motor channel: Right drive motor: "right_drive" - * Motor channel: Manipulator drive motor: "left_arm" - * Servo channel: Servo to open left claw: "left_hand" - * Servo channel: Servo to open right claw: "right_hand" - * - * In addition, the Matrix Controller has been assigned the name: "matrix controller" - */ -public class HardwarePushbotMatrix extends HardwarePushbot -{ - /* Public OpMode members. */ - private MatrixDcMotorController matrixMotorController = null; - private ServoController matrixServoController = null; - - /* Constructor */ - public HardwarePushbotMatrix(){ - - } - - /* Initialize standard Hardware interfaces */ - public void init(HardwareMap ahwMap) { - - // Initialize base Motor and Servo objects - super.init(ahwMap); - - /* - * Matrix controllers are special. - * - * A Matrix controller is one controller with both motors and servos - * but software wants to treat it as two distinct controllers, one - * DcMotorController, and one ServoController. - * - * We accomplish this by initializing Motor and Servo controller with the same name - * given in the configuration. In the example below the name of the controller is - * "MatrixController" - * - * Normally we don't need to access the controllers themselves, we deal directly with - * the Motor and Servo objects, but the Matrix interface is different. - * - * In order to activate the servos, they need to be enabled on the controller with - * a call to pwmEnable() and disabled with a call to pwmDisable() - * - * Also, the Matrix Motor controller interface provides a call that enables all motors to - * updated simultaneously (with the same value). - */ - - // Initialize Matrix Motor and Servo objects - matrixMotorController = ahwMap.get(MatrixDcMotorController.class, "matrix controller"); - matrixServoController = ahwMap.get(ServoController.class, "matrix controller"); - - // Enable Servos - matrixServoController.pwmEnable(); // Don't forget to enable Matrix Output - } -} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/K9botTeleopTank_Linear.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/K9botTeleopTank_Linear.java deleted file mode 100644 index 41494f792d8..00000000000 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/K9botTeleopTank_Linear.java +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (c) 2017 FIRST. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted (subject to the limitations in the disclaimer below) provided that - * the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * Neither the name of FIRST nor the names of its contributors may be used to endorse or - * promote products derived from this software without specific prior written permission. - * - * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS - * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.util.Range; - -/** - * This OpMode uses the common HardwareK9bot class to define the devices on the robot. - * All device access is managed through the HardwareK9bot class. (See this class for device names) - * The code is structured as a LinearOpMode - * - * This particular OpMode executes a basic Tank Drive Teleop for the K9 bot - * It raises and lowers the arm using the Gampad Y and A buttons respectively. - * It also opens and closes the claw slowly using the X and B buttons. - * - * Note: the configuration of the servos is such that - * as the arm servo approaches 0, the arm position moves up (away from the floor). - * Also, as the claw servo approaches 0, the claw opens up (drops the game element). - * - * Use Android Studios to Copy this Class, and Paste it into your team's code folder with a new name. - * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list - */ - -@TeleOp(name="K9bot: Telop Tank", group="K9bot") -@Disabled -public class K9botTeleopTank_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - HardwareK9bot robot = new HardwareK9bot(); // Use a K9'shardware - double armPosition = robot.ARM_HOME; // Servo safe position - double clawPosition = robot.CLAW_HOME; // Servo safe position - final double CLAW_SPEED = 0.01 ; // sets rate to move servo - final double ARM_SPEED = 0.01 ; // sets rate to move servo - - @Override - public void runOpMode() { - double left; - double right; - - /* Initialize the hardware variables. - * The init() method of the hardware class does all the work here - */ - robot.init(hardwareMap); - - // Send telemetry message to signify robot waiting; - telemetry.addData("Say", "Hello Driver"); // - telemetry.update(); - - // Wait for the game to start (driver presses PLAY) - waitForStart(); - - // run until the end of the match (driver presses STOP) - while (opModeIsActive()) { - - // Run wheels in tank mode (note: The joystick goes negative when pushed forwards, so negate it) - left = -gamepad1.left_stick_y; - right = -gamepad1.right_stick_y; - robot.leftDrive.setPower(left); - robot.rightDrive.setPower(right); - - // Use gamepad Y & A raise and lower the arm - if (gamepad1.a) - armPosition += ARM_SPEED; - else if (gamepad1.y) - armPosition -= ARM_SPEED; - - // Use gamepad X & B to open and close the claw - if (gamepad1.x) - clawPosition += CLAW_SPEED; - else if (gamepad1.b) - clawPosition -= CLAW_SPEED; - - // Move both servos to new position. - armPosition = Range.clip(armPosition, robot.ARM_MIN_RANGE, robot.ARM_MAX_RANGE); - robot.arm.setPosition(armPosition); - clawPosition = Range.clip(clawPosition, robot.CLAW_MIN_RANGE, robot.CLAW_MAX_RANGE); - robot.claw.setPosition(clawPosition); - - // Send telemetry message to signify robot running; - telemetry.addData("arm", "%.2f", armPosition); - telemetry.addData("claw", "%.2f", clawPosition); - telemetry.addData("left", "%.2f", left); - telemetry.addData("right", "%.2f", right); - telemetry.update(); - - // Pause for 40 mS each cycle = update 25 times a second. - sleep(40); - } - } -} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotAutoDriveToLine_Linear.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotAutoDriveToLine_Linear.java index bdabc17787c..2e174b1351d 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotAutoDriveToLine_Linear.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotAutoDriveToLine_Linear.java @@ -60,7 +60,6 @@ public class PushbotAutoDriveToLine_Linear extends LinearOpMode { /* Declare OpMode members. */ HardwarePushbot robot = new HardwarePushbot(); // Use a Pushbot's hardware - // could also use HardwarePushbotMatrix class. LightSensor lightSensor; // Primary LEGO Light sensor, // OpticalDistanceSensor lightSensor; // Alternative MR ODS sensor diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotTeleopPOV_Linear.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotTeleopPOV_Linear.java index cd84d15e49d..cc168d8c61e 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotTeleopPOV_Linear.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotTeleopPOV_Linear.java @@ -54,7 +54,6 @@ public class PushbotTeleopPOV_Linear extends LinearOpMode { /* Declare OpMode members. */ HardwarePushbot robot = new HardwarePushbot(); // Use a Pushbot's hardware - // could also use HardwarePushbotMatrix class. double clawOffset = 0; // Servo mid position final double CLAW_SPEED = 0.02 ; // sets rate to move servo diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotTeleopTank_Iterative.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotTeleopTank_Iterative.java index 1aec890af0e..ec336a84783 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotTeleopTank_Iterative.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/PushbotTeleopTank_Iterative.java @@ -55,7 +55,6 @@ public class PushbotTeleopTank_Iterative extends OpMode{ /* Declare OpMode members. */ HardwarePushbot robot = new HardwarePushbot(); // use the class created to define a Pushbot's hardware - // could also use HardwarePushbotMatrix class. double clawOffset = 0.0 ; // Servo mid position final double CLAW_SPEED = 0.02 ; // sets rate to move servo diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SampleRevBlinkinLedDriver.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SampleRevBlinkinLedDriver.java new file mode 100644 index 00000000000..337b7032152 --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SampleRevBlinkinLedDriver.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2018 Craig MacFarlane + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * (subject to the limitations in the disclaimer below) provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, this list of conditions + * and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Craig MacFarlane nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS + * SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.firstinspires.ftc.robotcontroller.external.samples; + +import com.qualcomm.hardware.rev.RevBlinkinLedDriver; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; +import com.qualcomm.robotcore.eventloop.opmode.OpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; + +import org.firstinspires.ftc.robotcore.external.Telemetry; +import org.firstinspires.ftc.robotcore.internal.system.Deadline; + +import java.util.concurrent.TimeUnit; + +/* + * Display patterns of a REV Robotics Blinkin LED Driver. + * AUTO mode cycles through all of the patterns. + * MANUAL mode allows the user to manually change patterns using the + * left and right bumpers of a gamepad. + * + * Configure the driver on a servo port, and name it "blinkin". + * + * Displays the first pattern upon init. + */ +@TeleOp(name="BlinkinExample") +@Disabled +public class SampleRevBlinkinLedDriver extends OpMode { + + /* + * Change the pattern every 10 seconds in AUTO mode. + */ + private final static int LED_PERIOD = 10; + + /* + * Rate limit gamepad button presses to every 500ms. + */ + private final static int GAMEPAD_LOCKOUT = 500; + + RevBlinkinLedDriver blinkinLedDriver; + RevBlinkinLedDriver.BlinkinPattern pattern; + + Telemetry.Item patternName; + Telemetry.Item display; + DisplayKind displayKind; + Deadline ledCycleDeadline; + Deadline gamepadRateLimit; + + protected enum DisplayKind { + MANUAL, + AUTO + } + + @Override + public void init() + { + displayKind = DisplayKind.AUTO; + + blinkinLedDriver = hardwareMap.get(RevBlinkinLedDriver.class, "blinkin"); + pattern = RevBlinkinLedDriver.BlinkinPattern.RAINBOW_RAINBOW_PALETTE; + blinkinLedDriver.setPattern(pattern); + + display = telemetry.addData("Display Kind: ", displayKind.toString()); + patternName = telemetry.addData("Pattern: ", pattern.toString()); + + ledCycleDeadline = new Deadline(LED_PERIOD, TimeUnit.SECONDS); + gamepadRateLimit = new Deadline(GAMEPAD_LOCKOUT, TimeUnit.MILLISECONDS); + } + + @Override + public void loop() + { + handleGamepad(); + + if (displayKind == DisplayKind.AUTO) { + doAutoDisplay(); + } else { + /* + * MANUAL mode: Nothing to do, setting the pattern as a result of a gamepad event. + */ + } + } + + /* + * handleGamepad + * + * Responds to a gamepad button press. Demonstrates rate limiting for + * button presses. If loop() is called every 10ms and and you don't rate + * limit, then any given button press may register as multiple button presses, + * which in this application is problematic. + * + * A: Manual mode, Right bumper displays the next pattern, left bumper displays the previous pattern. + * B: Auto mode, pattern cycles, changing every LED_PERIOD seconds. + */ + protected void handleGamepad() + { + if (!gamepadRateLimit.hasExpired()) { + return; + } + + if (gamepad1.a) { + setDisplayKind(DisplayKind.MANUAL); + gamepadRateLimit.reset(); + } else if (gamepad1.b) { + setDisplayKind(DisplayKind.AUTO); + gamepadRateLimit.reset(); + } else if ((displayKind == DisplayKind.MANUAL) && (gamepad1.left_bumper)) { + pattern = pattern.previous(); + displayPattern(); + gamepadRateLimit.reset(); + } else if ((displayKind == DisplayKind.MANUAL) && (gamepad1.right_bumper)) { + pattern = pattern.next(); + displayPattern(); + gamepadRateLimit.reset(); + } + } + + protected void setDisplayKind(DisplayKind displayKind) + { + this.displayKind = displayKind; + display.setValue(displayKind.toString()); + } + + protected void doAutoDisplay() + { + if (ledCycleDeadline.hasExpired()) { + pattern = pattern.next(); + displayPattern(); + ledCycleDeadline.reset(); + } + } + + protected void displayPattern() + { + blinkinLedDriver.setPattern(pattern); + patternName.setValue(pattern.toString()); + } +} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorAdafruitRGB.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorAdafruitRGB.java index f3f52764cff..6a94e25fb6a 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorAdafruitRGB.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorAdafruitRGB.java @@ -33,9 +33,9 @@ import android.graphics.Color; import android.view.View; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.ColorSensor; import com.qualcomm.robotcore.hardware.DeviceInterfaceModule; import com.qualcomm.robotcore.hardware.DigitalChannel; @@ -67,7 +67,7 @@ * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list */ -@Autonomous(name = "Sensor: AdafruitRGB", group = "Sensor") +@TeleOp(name = "Sensor: AdafruitRGB", group = "Sensor") @Disabled // Comment this out to add to the opmode list public class SensorAdafruitRGB extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java index b52d6583c4c..9102a108d87 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java @@ -31,9 +31,9 @@ import com.qualcomm.hardware.bosch.BNO055IMU; import com.qualcomm.hardware.bosch.JustLoggingAccelerationIntegrator; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import org.firstinspires.ftc.robotcore.external.Func; import org.firstinspires.ftc.robotcore.external.navigation.Acceleration; @@ -54,7 +54,7 @@ * * @see Adafruit IMU */ -@Autonomous(name = "Sensor: BNO055 IMU", group = "Sensor") +@TeleOp(name = "Sensor: BNO055 IMU", group = "Sensor") @Disabled // Comment this out to add to the opmode list public class SensorBNO055IMU extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java index 4b1811d7613..5f86743762b 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java @@ -43,7 +43,7 @@ /* * This is an example LinearOpMode that shows how to use a color sensor in a generic * way, insensitive which particular make or model of color sensor is used. The opmode - * assumes that the color sensor is configured with a name of "color sensor". + * assumes that the color sensor is configured with a name of "sensor_color". * * If the color sensor has a light which is controllable, you can use the X button on * the gamepad to toggle the light on and off. diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java index 8da2afb774e..b367924e9e5 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java @@ -29,21 +29,21 @@ package org.firstinspires.ftc.robotcontroller.external.samples; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.DigitalChannel; /* * This is an example LinearOpMode that shows how to use * a REV Robotics Touch Sensor. * - * It assumes that the touch sensor is configured with a name of "digitalTouch". + * It assumes that the touch sensor is configured with a name of "sensor_digital". * * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list. */ -@Autonomous(name = "Sensor: Digital touch", group = "Sensor") +@TeleOp(name = "Sensor: Digital touch", group = "Sensor") @Disabled public class SensorDigitalTouch extends LinearOpMode { /** diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHTColor.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHTColor.java deleted file mode 100644 index e0de829b3b4..00000000000 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHTColor.java +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright (c) 2017 FIRST. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted (subject to the limitations in the disclaimer below) provided that - * the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * Neither the name of FIRST nor the names of its contributors may be used to endorse or - * promote products derived from this software without specific prior written permission. - * - * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS - * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import android.app.Activity; -import android.graphics.Color; -import android.view.View; - -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.hardware.ColorSensor; - -/* - * - * This is an example LinearOpMode that shows how to use - * a legacy (NXT-compatible) Hitechnic Color Sensor v2. - * It assumes that the color sensor is configured with a name of "sensor_color". - * - * You can use the X button on gamepad1 to toggle the LED on and off. - * - * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. - * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list - */ -@Autonomous(name = "Sensor: HT color", group = "Sensor") -@Disabled -public class SensorHTColor extends LinearOpMode { - - ColorSensor colorSensor; // Hardware Device Object - - - @Override - public void runOpMode() { - - // hsvValues is an array that will hold the hue, saturation, and value information. - float hsvValues[] = {0F,0F,0F}; - - // values is a reference to the hsvValues array. - final float values[] = hsvValues; - - // get a reference to the RelativeLayout so we can change the background - // color of the Robot Controller app to match the hue detected by the RGB sensor. - int relativeLayoutId = hardwareMap.appContext.getResources().getIdentifier("RelativeLayout", "id", hardwareMap.appContext.getPackageName()); - final View relativeLayout = ((Activity) hardwareMap.appContext).findViewById(relativeLayoutId); - - // bPrevState and bCurrState represent the previous and current state of the button. - boolean bPrevState = false; - boolean bCurrState = false; - - // bLedOn represents the state of the LED. - boolean bLedOn = true; - - // get a reference to our ColorSensor object. - colorSensor = hardwareMap.colorSensor.get("sensor_color"); - - // turn the LED on in the beginning, just so user will know that the sensor is active. - colorSensor.enableLed(bLedOn); - - // wait for the start button to be pressed. - waitForStart(); - - // loop and read the RGB data. - // Note we use opModeIsActive() as our loop condition because it is an interruptible method. - while (opModeIsActive()) { - - // check the status of the x button on gamepad1. - bCurrState = gamepad1.x; - - // check for button state transitions. - if (bCurrState && (bCurrState != bPrevState)) { - - // button is transitioning to a pressed state. Toggle LED. - // on button press, enable the LED. - bLedOn = !bLedOn; - colorSensor.enableLed(bLedOn); - } - - // update previous state variable. - bPrevState = bCurrState; - - // convert the RGB values to HSV values. - Color.RGBToHSV(colorSensor.red(), colorSensor.green(), colorSensor.blue(), hsvValues); - - // send the info back to driver station using telemetry function. - telemetry.addData("LED", bLedOn ? "On" : "Off"); - telemetry.addData("Clear", colorSensor.alpha()); - telemetry.addData("Red ", colorSensor.red()); - telemetry.addData("Green", colorSensor.green()); - telemetry.addData("Blue ", colorSensor.blue()); - telemetry.addData("Hue", hsvValues[0]); - - // change the background color to match the color detected by the RGB sensor. - // pass a reference to the hue, saturation, and value array as an argument - // to the HSVToColor method. - relativeLayout.post(new Runnable() { - public void run() { - relativeLayout.setBackgroundColor(Color.HSVToColor(0xff, values)); - } - }); - - telemetry.update(); - } - - // Set the panel back to the default color - relativeLayout.post(new Runnable() { - public void run() { - relativeLayout.setBackgroundColor(Color.WHITE); - } - }); - - } -} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHTGyro.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHTGyro.java deleted file mode 100644 index d4ad94c7073..00000000000 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHTGyro.java +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (c) 2017 FIRST. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted (subject to the limitations in the disclaimer below) provided that - * the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * Neither the name of FIRST nor the names of its contributors may be used to endorse or - * promote products derived from this software without specific prior written permission. - * - * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS - * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.hardware.hitechnic.HiTechnicNxtGyroSensor; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.hardware.Gyroscope; -import com.qualcomm.robotcore.hardware.IntegratingGyroscope; - -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; - -/* - * This is an example LinearOpMode that shows how to use a legacy (NXT-compatible) - * HiTechnic gyroscope. It assumes that the gyroscope is configured with a name of "gyro". - * - * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. - * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list. - */ -@Autonomous(name = "Sensor: HT Gyro", group = "Sensor") -@Disabled -public class SensorHTGyro extends LinearOpMode { - - /** In this sample, for illustration purposes we use two interfaces on the one gyro object. - * That's likely atypical: you'll probably use one or the other in any given situation, - * depending on what you're trying to do. {@link IntegratingGyroscope} (and it's base interface, - * {@link Gyroscope}) are common interfaces supported by possibly several different gyro - * implementations. {@link HiTechnicNxtGyroSensor}, by contrast, provides functionality that - * is unique to the HiTechnic gyro sensor. - */ - Gyroscope gyroscope; - HiTechnicNxtGyroSensor hiTechnicNxtGyroSensor; - - @Override public void runOpMode() throws InterruptedException { - - // Get a reference to the gyroscope from the hardware map - gyroscope = hardwareMap.get(Gyroscope.class, "gyro"); - - // Get a reference to the *implementation* of the gyroscope on the HiTechnic sensor. - // Usually, you won't need to examine internal implementation details in this way, but - // we do so to illustrate aspects of what is going on inside the sensor. - hiTechnicNxtGyroSensor = hardwareMap.get(HiTechnicNxtGyroSensor.class, "gyro"); - // Alternately, we could have cast: hiTechnicNxtGyroSensor = (HiTechnicNxtGyroSensor)gyro; - - // Optionally, calibrate the gyro to establish a good value for its "zero deg/s" bias - // voltage value. Calibration is not entirely necessary, as the default bias voltage - // usually does a reasonable job. While calibration is performed, the gyro must remain - // motionless. Note that for this gyro sensor, calibration data is not persistently - // written to EEPROM, but rather should be performed each run. - telemetry.log().add("calibrating..."); - hiTechnicNxtGyroSensor.calibrate(3000, 100); - telemetry.log().add("...done...waiting for start..."); - - // wait for the start button to be pressed. - waitForStart(); - telemetry.log().clear(); - - // loop until the opmode has been asked to stop - while (opModeIsActive()) { - - double raw = hiTechnicNxtGyroSensor.readRawVoltage(); - double bias = hiTechnicNxtGyroSensor.getBiasVoltage(); - - telemetry.addData("rate", "%.4f deg/s", gyroscope.getAngularVelocity(AngleUnit.DEGREES).zRotationRate); - telemetry.addData("raw ", "%.4fv", raw); - telemetry.addData("bias", "%.4fv", bias); - telemetry.addData("volts", "%.4fv", raw-bias); - telemetry.addData("deg/s/v", "%.4f deg/s/v", hiTechnicNxtGyroSensor.getDefaultDegreesPerSecondPerVolt()); - - telemetry.update(); - idle(); - } - } -} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java index 40e4a94e5ff..583f52569ad 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java @@ -30,9 +30,9 @@ package org.firstinspires.ftc.robotcontroller.external.samples; import com.qualcomm.hardware.kauailabs.NavxMicroNavigationSensor; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.Gyroscope; import com.qualcomm.robotcore.hardware.IntegratingGyroscope; import com.qualcomm.robotcore.util.ElapsedTime; @@ -50,7 +50,7 @@ * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list */ -@Autonomous(name = "Sensor: KL navX Micro", group = "Sensor") +@TeleOp(name = "Sensor: KL navX Micro", group = "Sensor") @Disabled public class SensorKLNavxMicro extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLEGOLight.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLEGOLight.java deleted file mode 100644 index aeed891e9de..00000000000 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLEGOLight.java +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (c) 2017 FIRST. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted (subject to the limitations in the disclaimer below) provided that - * the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * Neither the name of FIRST nor the names of its contributors may be used to endorse or - * promote products derived from this software without specific prior written permission. - * - * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS - * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.LightSensor; - -/* - * - * This is an example LinearOpMode that shows how to use - * a legacy (NXT-compatible) Light Sensor. - * It assumes that the light sensor is configured with a name of "sensor_light". - * - * You can use the X button on gamepad1 to turn Toggle the LED on and off. - * - * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. - * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list - */ -@TeleOp(name = "Sensor: LEGO light", group = "Sensor") -@Disabled -public class SensorLEGOLight extends LinearOpMode { - - LightSensor lightSensor; // Hardware Device Object - - @Override - public void runOpMode() { - - // bPrevState and bCurrState represent the previous and current state of the button. - boolean bPrevState = false; - boolean bCurrState = false; - - // bLedOn represents the state of the LED. - boolean bLedOn = true; - - // get a reference to our Light Sensor object. - lightSensor = hardwareMap.get(LightSensor.class, "sensor_light"); - - // Set the LED state in the beginning. - lightSensor.enableLed(bLedOn); - - // wait for the start button to be pressed. - waitForStart(); - - // while the op mode is active, loop and read the light levels. - // Note we use opModeIsActive() as our loop condition because it is an interruptible method. - while (opModeIsActive()) { - - // check the status of the x button . - bCurrState = gamepad1.x; - - // check for button state transitions. - if ((bCurrState == true) && (bCurrState != bPrevState)) { - - // button is transitioning to a pressed state. Toggle LED - bLedOn = !bLedOn; - lightSensor.enableLed(bLedOn); - } - - // update previous state variable. - bPrevState = bCurrState; - - // send the info back to driver station using telemetry function. - telemetry.addData("LED", bLedOn ? "On" : "Off"); - telemetry.addData("Raw", lightSensor.getRawLightDetected()); - telemetry.addData("Normal", lightSensor.getLightDetected()); - - telemetry.update(); - } - } -} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLEGOTouch.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLEGOTouch.java deleted file mode 100644 index 59f316a02d1..00000000000 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLEGOTouch.java +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (c) 2017 FIRST. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted (subject to the limitations in the disclaimer below) provided that - * the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * Neither the name of FIRST nor the names of its contributors may be used to endorse or - * promote products derived from this software without specific prior written permission. - * - * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS - * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.TouchSensor; - -/* - * This is an example LinearOpMode that shows how to use - * a legacy (NXT-compatible) Touch Sensor. - * It assumes that the touch sensor is configured with a name of "sensor_touch". - * - * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. - * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list - */ -@TeleOp(name = "Sensor: LEGO touch", group = "Sensor") -@Disabled -public class SensorLEGOTouch extends LinearOpMode { - - TouchSensor touchSensor; // Hardware Device Object - - @Override - public void runOpMode() { - - // get a reference to our Light Sensor object. - touchSensor = hardwareMap.get(TouchSensor.class, "sensor_touch"); - int counter = 0; - - // wait for the start button to be pressed. - waitForStart(); - - // while the op mode is active, loop and read the light levels. - // Note we use opModeIsActive() as our loop condition because it is an interruptible method. - while (opModeIsActive()) { - - // send the info back to driver station using telemetry function. - if (touchSensor.isPressed()) - telemetry.addData("Touch", "Is Pressed"); - else - telemetry.addData("Touch", "Is Not Pressed"); - - telemetry.update(); - } - } -} diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRCompass.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRCompass.java index 90ab7047c1b..583ac1aab3e 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRCompass.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRCompass.java @@ -30,9 +30,9 @@ package org.firstinspires.ftc.robotcontroller.external.samples; import com.qualcomm.hardware.modernrobotics.ModernRoboticsI2cCompassSensor; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.CompassSensor; import com.qualcomm.robotcore.util.ElapsedTime; @@ -49,7 +49,7 @@ * * @see MR Compass Sensor */ -@Autonomous(name = "Sensor: MR compass", group = "Sensor") +@TeleOp(name = "Sensor: MR compass", group = "Sensor") @Disabled // comment out or remove this line to enable this opmode public class SensorMRCompass extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java index 5acbd10e56b..d7de1fff0e8 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java @@ -30,9 +30,9 @@ package org.firstinspires.ftc.robotcontroller.external.samples; import com.qualcomm.hardware.modernrobotics.ModernRoboticsI2cRangeSensor; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; @@ -47,7 +47,7 @@ * * @see MR Range Sensor */ -@Autonomous(name = "Sensor: MR range sensor", group = "Sensor") +@TeleOp(name = "Sensor: MR range sensor", group = "Sensor") @Disabled // comment out or remove this line to enable this opmode public class SensorMRRangeSensor extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREV2mDistance.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREV2mDistance.java new file mode 100644 index 00000000000..30bb377dae1 --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREV2mDistance.java @@ -0,0 +1,89 @@ +/* +Copyright (c) 2018 FIRST + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted (subject to the limitations in the disclaimer below) provided that +the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +Neither the name of FIRST nor the names of its contributors may be used to +endorse or promote products derived from this software without specific prior +written permission. + +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS +LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package org.firstinspires.ftc.robotcontroller.external.samples; + +import com.qualcomm.hardware.rev.Rev2mDistanceSensor; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; +import com.qualcomm.robotcore.eventloop.opmode.Disabled; +import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.hardware.DistanceSensor; + +import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; + +/** + * {@link SensorREV2mDistance} illustrates how to use the REV Robotics + * Time-of-Flight Range Sensor. + * + * The op mode assumes that the range sensor is configured with a name of "sensor_range". + * + * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. + * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list + * + * @see REV Robotics Web Page + */ +@TeleOp(name = "Sensor: REV2mDistance", group = "Sensor") +@Disabled +public class SensorREV2mDistance extends LinearOpMode { + + private DistanceSensor sensorRange; + + @Override + public void runOpMode() { + // you can use this as a regular DistanceSensor. + sensorRange = hardwareMap.get(DistanceSensor.class, "sensor_range"); + + // you can also cast this to a Rev2mDistanceSensor if you want to use added + // methods associated with the Rev2mDistanceSensor class. + Rev2mDistanceSensor sensorTimeOfFlight = (Rev2mDistanceSensor)sensorRange; + + telemetry.addData(">>", "Press start to continue"); + telemetry.update(); + + waitForStart(); + while(opModeIsActive()) { + // generic DistanceSensor methods. + telemetry.addData("deviceName",sensorRange.getDeviceName() ); + telemetry.addData("range", String.format("%.01f mm", sensorRange.getDistance(DistanceUnit.MM))); + telemetry.addData("range", String.format("%.01f cm", sensorRange.getDistance(DistanceUnit.CM))); + telemetry.addData("range", String.format("%.01f m", sensorRange.getDistance(DistanceUnit.METER))); + telemetry.addData("range", String.format("%.01f in", sensorRange.getDistance(DistanceUnit.INCH))); + + // Rev2mDistanceSensor specific methods. + telemetry.addData("ID", String.format("%x", sensorTimeOfFlight.getModelID())); + telemetry.addData("did time out", Boolean.toString(sensorTimeOfFlight.didTimeoutOccur())); + + telemetry.update(); + } + } + +} \ No newline at end of file diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREVColorDistance.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREVColorDistance.java index 11a8880f9e7..37910ca97b5 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREVColorDistance.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREVColorDistance.java @@ -33,9 +33,9 @@ import android.graphics.Color; import android.view.View; -import com.qualcomm.robotcore.eventloop.opmode.Autonomous; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.ColorSensor; import com.qualcomm.robotcore.hardware.DistanceSensor; @@ -52,7 +52,7 @@ * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name. * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list. */ -@Autonomous(name = "Sensor: REVColorDistance", group = "Sensor") +@TeleOp(name = "Sensor: REVColorDistance", group = "Sensor") @Disabled // Comment this out to add to the opmode list public class SensorREVColorDistance extends LinearOpMode { diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md index 8eeb7f01e7c..5b66c4f4b91 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md @@ -49,7 +49,6 @@ After the prefix, other conventions will apply: * Sensor class names are constructed as: Sensor - Company - Type * Hardware class names are constructed as: Hardware - Robot type * Pushbot class names are constructed as: Pushbot - Mode - Action - OpModetype -* K9bot class names are constructed as: K9bot - Mode - Action - OpModetype * Concept class names are constructed as: Concept - Topic - OpModetype * Library class names are constructed as: Library - Topic - OpModetype diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md index a2f65814a34..0f1aa131b5a 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md @@ -42,7 +42,6 @@ After the prefix, other conventions will apply: * Sensor class names should constructed as: Sensor - Company - Type * Hardware class names should be constructed as: Hardware - Robot type * Pushbot class names should be constructed as: Pushbot - Mode - Action - OpModetype -* K9bot class names should be constructed as: K9bot - Mode - Action - OpModetype * Concept class names should be constructed as: Concept - Topic - OpModetype * Library class names should be constructed as: Library - Topic - OpModetype diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java index 4ec32fa4315..791f744e79f 100644 --- a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java @@ -47,6 +47,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE import android.os.IBinder; import android.preference.PreferenceManager; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; @@ -54,6 +56,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE import android.webkit.WebView; import android.widget.ImageButton; import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.PopupMenu; import android.widget.TextView; import com.google.blocks.ftcrobotcontroller.BlocksActivity; @@ -61,8 +65,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE import com.google.blocks.ftcrobotcontroller.ProgrammingModeControllerImpl; import com.google.blocks.ftcrobotcontroller.ProgrammingWebHandlers; import com.google.blocks.ftcrobotcontroller.runtime.BlocksOpMode; -import com.qualcomm.ftccommon.AboutActivity; import com.qualcomm.ftccommon.ClassManagerFactory; +import com.qualcomm.ftccommon.FtcAboutActivity; import com.qualcomm.ftccommon.FtcEventLoop; import com.qualcomm.ftccommon.FtcEventLoopIdle; import com.qualcomm.ftccommon.FtcRobotControllerService; @@ -84,20 +88,30 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE import com.qualcomm.robotcore.eventloop.opmode.OpModeRegister; import com.qualcomm.robotcore.hardware.configuration.LynxConstants; import com.qualcomm.robotcore.hardware.configuration.Utility; +import com.qualcomm.robotcore.util.Device; import com.qualcomm.robotcore.util.Dimmer; import com.qualcomm.robotcore.util.ImmersiveMode; import com.qualcomm.robotcore.util.RobotLog; +import com.qualcomm.robotcore.util.WebServer; +import com.qualcomm.robotcore.wifi.NetworkConnection; import com.qualcomm.robotcore.wifi.NetworkConnectionFactory; import com.qualcomm.robotcore.wifi.NetworkType; -import com.qualcomm.robotcore.wifi.WifiDirectAssistant; import org.firstinspires.ftc.ftccommon.external.SoundPlayingRobotMonitor; import org.firstinspires.ftc.ftccommon.internal.FtcRobotControllerWatchdogService; import org.firstinspires.ftc.ftccommon.internal.ProgramAndManageActivity; -import org.firstinspires.ftc.robotcore.internal.hardware.DragonboardLynxDragonboardIsPresentPin; -import org.firstinspires.ftc.robotcore.internal.network.DeviceNameManager; +import org.firstinspires.ftc.onbotjava.OnBotJavaClassLoader; +import org.firstinspires.ftc.onbotjava.OnBotJavaHelperImpl; +import org.firstinspires.ftc.onbotjava.OnBotJavaProgrammingMode; +import org.firstinspires.ftc.robotcore.external.navigation.MotionDetection; +import org.firstinspires.ftc.robotcore.internal.hardware.android.AndroidBoard; +import org.firstinspires.ftc.robotcore.internal.network.DeviceNameManagerFactory; import org.firstinspires.ftc.robotcore.internal.network.PreferenceRemoterRC; import org.firstinspires.ftc.robotcore.internal.network.StartResult; +import org.firstinspires.ftc.robotcore.internal.network.WifiDirectChannelChanger; +import org.firstinspires.ftc.robotcore.internal.network.WifiMuteEvent; +import org.firstinspires.ftc.robotcore.internal.network.WifiMuteStateMachine; +import org.firstinspires.ftc.robotcore.internal.opmode.ClassManager; import org.firstinspires.ftc.robotcore.internal.system.AppUtil; import org.firstinspires.ftc.robotcore.internal.system.Assert; import org.firstinspires.ftc.robotcore.internal.system.PreferencesHelper; @@ -106,7 +120,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE import org.firstinspires.ftc.robotcore.internal.ui.ThemedActivity; import org.firstinspires.ftc.robotcore.internal.ui.UILocation; import org.firstinspires.ftc.robotcore.internal.webserver.RobotControllerWebInfo; -import org.firstinspires.ftc.robotcore.internal.webserver.WebServer; +import org.firstinspires.ftc.robotserver.internal.programmingmode.ProgrammingModeManager; import org.firstinspires.inspection.RcInspectionActivity; import java.util.Queue; @@ -124,14 +138,14 @@ public class FtcRobotControllerActivity extends Activity protected WifiManager.WifiLock wifiLock; protected RobotConfigFileManager cfgFileMgr; - protected ProgrammingWebHandlers programmingWebHandlers; + protected ProgrammingModeManager programmingModeManager; protected ProgrammingModeController programmingModeController; protected UpdateUI.Callback callback; protected Context context; protected Utility utility; - protected StartResult deviceNameManagerStartResult = new StartResult(); protected StartResult prefRemoterStartResult = new StartResult(); + protected StartResult deviceNameStartResult = new StartResult(); protected PreferencesHelper preferencesHelper; protected final SharedPreferencesListener sharedPreferencesListener = new SharedPreferencesListener(); @@ -154,6 +168,13 @@ public class FtcRobotControllerActivity extends Activity protected FtcEventLoop eventLoop; protected Queue receivedUsbAttachmentNotifications; + protected WifiMuteStateMachine wifiMuteStateMachine; + protected MotionDetection motionDetection; + + private static boolean permissionsValidated = false; + + private WifiDirectChannelChanger wifiDirectChannelChanger; + protected class RobotRestarter implements Restarter { public void requestRestart() { @@ -162,6 +183,7 @@ public void requestRestart() { } + protected boolean serviceShouldUnbind = false; protected ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { @@ -213,34 +235,65 @@ protected void passReceivedUsbAttachmentsToEventLoop() { } } + /** + * There are cases where a permission may be revoked and the system restart will restart the + * FtcRobotControllerActivity, instead of the launch activity. Detect when that happens, and throw + * the device back to the permission validator activity. + */ + protected boolean enforcePermissionValidator() { + if (!permissionsValidated) { + RobotLog.vv(TAG, "Redirecting to permission validator"); + Intent permissionValidatorIntent = new Intent(AppUtil.getDefContext(), PermissionValidatorWrapper.class); + startActivity(permissionValidatorIntent); + finish(); + return true; + } else { + RobotLog.vv(TAG, "Permissions validated already"); + return false; + } + } + + public static void setPermissionsValidated() { + permissionsValidated = true; + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + if (enforcePermissionValidator()) { + return; + } + RobotLog.onApplicationStart(); // robustify against onCreate() following onDestroy() but using the same app instance, which apparently does happen RobotLog.vv(TAG, "onCreate()"); ThemedActivity.appAppThemeToActivity(getTag(), this); // do this way instead of inherit to help AppInventor - Assert.assertTrue(FtcRobotControllerWatchdogService.isFtcRobotControllerActivity(AppUtil.getInstance().getRootActivity())); + // Oddly, sometimes after a crash & restart the root activity will be something unexpected, like from the before crash? We don't yet understand + RobotLog.vv(TAG, "rootActivity is of class %s", AppUtil.getInstance().getRootActivity().getClass().getSimpleName()); + RobotLog.vv(TAG, "launchActivity is of class %s", FtcRobotControllerWatchdogService.launchActivity()); + Assert.assertTrue(FtcRobotControllerWatchdogService.isLaunchActivity(AppUtil.getInstance().getRootActivity())); Assert.assertTrue(AppUtil.getInstance().isRobotController()); // Quick check: should we pretend we're not here, and so allow the Lynx to operate as // a stand-alone USB-connected module? if (LynxConstants.isRevControlHub()) { - if (LynxConstants.disableDragonboard()) { + if (LynxConstants.shouldDisableAndroidBoard()) { // Double-sure check that the Lynx Module can operate over USB, etc, then get out of Dodge RobotLog.vv(TAG, "disabling Dragonboard and exiting robot controller"); - DragonboardLynxDragonboardIsPresentPin.getInstance().setState(false); + AndroidBoard.getInstance().getAndroidBoardIsPresentPin().setState(false); AppUtil.getInstance().finishRootActivityAndExitApp(); - } - else { + } else { // Double-sure check that we can talk to the DB over the serial TTY - DragonboardLynxDragonboardIsPresentPin.getInstance().setState(true); + AndroidBoard.getInstance().getAndroidBoardIsPresentPin().setState(true); } } context = this; utility = new Utility(this); - DeviceNameManager.getInstance().start(deviceNameManagerStartResult); + + DeviceNameManagerFactory.getInstance().start(deviceNameStartResult); + PreferenceRemoterRC.getInstance().start(prefRemoterStartResult); receivedUsbAttachmentNotifications = new ConcurrentLinkedQueue(); @@ -257,14 +310,34 @@ protected void onCreate(Bundle savedInstanceState) { buttonMenu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - AppUtil.getInstance().openOptionsMenuFor(FtcRobotControllerActivity.this); + PopupMenu popupMenu = new PopupMenu(FtcRobotControllerActivity.this, v); + popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + return onOptionsItemSelected(item); // Delegate to the handler for the hardware menu button + } + }); + popupMenu.inflate(R.menu.ftc_robot_controller); + popupMenu.show(); } }); + updateMonitorLayout(getResources().getConfiguration()); + BlocksOpMode.setActivityAndWebView(this, (WebView) findViewById(R.id.webViewBlocksRuntime)); - ClassManagerFactory.registerFilters(); - ClassManagerFactory.processAllClasses(); + /* + * Paranoia as the ClassManagerFactory requires EXTERNAL_STORAGE permissions + * and we've seen on the DS where the finish() call above does not short-circuit + * the onCreate() call for the activity and then we crash here because we don't + * have permissions. So... + */ + if (permissionsValidated) { + ClassManager.getInstance().setOnBotJavaClassHelper(new OnBotJavaHelperImpl()); + ClassManagerFactory.registerFilters(); + ClassManagerFactory.processAllClasses(); + } + cfgFileMgr = new RobotConfigFileManager(this); // Clean up 'dirty' status after a possible crash @@ -285,9 +358,11 @@ public void onClick(View v) { dimmer = new Dimmer(this); dimmer.longBright(); - programmingWebHandlers = new ProgrammingWebHandlers(); + programmingModeManager = new ProgrammingModeManager(); + programmingModeManager.register(new ProgrammingWebHandlers()); + programmingModeManager.register(new OnBotJavaProgrammingMode()); programmingModeController = new ProgrammingModeControllerImpl( - this, (TextView) findViewById(R.id.textRemoteProgrammingMode), programmingWebHandlers); + this, (TextView) findViewById(R.id.textRemoteProgrammingMode), programmingModeManager); updateUI = createUpdateUI(); callback = createUICallback(updateUI); @@ -300,11 +375,18 @@ public void onClick(View v) { hittingMenuButtonBrightensScreen(); wifiLock.acquire(); - callback.networkConnectionUpdate(WifiDirectAssistant.Event.DISCONNECTED); + callback.networkConnectionUpdate(NetworkConnection.NetworkEvent.DISCONNECTED); readNetworkType(); ServiceController.startService(FtcRobotControllerWatchdogService.class); bindToService(); logPackageVersions(); + logDeviceSerialNumber(); + AndroidBoard.getInstance().logAndroidBoardInfo(); + RobotLog.logDeviceInfo(); + + if (preferencesHelper.readBoolean(getString(R.string.pref_wifi_automute), false)) { + initWifiMute(true); + } } protected UpdateUI createUpdateUI() { @@ -334,6 +416,9 @@ protected void onStart() { cfgFileMgr.getActiveConfigAndUpdateUI(); + // check to see if there is a preferred Wi-Fi to use. + checkPreferredChannel(); + entireScreenLayout.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { @@ -374,15 +459,15 @@ protected void onDestroy() { shutdownRobot(); // Ensure the robot is put away to bed if (callback != null) callback.close(); - PreferenceRemoterRC.getInstance().start(prefRemoterStartResult); - DeviceNameManager.getInstance().stop(deviceNameManagerStartResult); + PreferenceRemoterRC.getInstance().stop(prefRemoterStartResult); + DeviceNameManagerFactory.getInstance().stop(deviceNameStartResult); unbindFromService(); // If the app manually (?) is stopped, then we don't need the auto-starting function (?) ServiceController.stopService(FtcRobotControllerWatchdogService.class); - wifiLock.release(); + if (wifiLock != null) wifiLock.release(); + if (preferencesHelper != null) preferencesHelper.getSharedPreferences().unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener); - preferencesHelper.getSharedPreferences().unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener); RobotLog.cancelWriteLogcatToDisk(); } @@ -390,12 +475,13 @@ protected void bindToService() { readNetworkType(); Intent intent = new Intent(this, FtcRobotControllerService.class); intent.putExtra(NetworkConnectionFactory.NETWORK_CONNECTION_TYPE, networkType); - bindService(intent, connection, Context.BIND_AUTO_CREATE); + serviceShouldUnbind = bindService(intent, connection, Context.BIND_AUTO_CREATE); } protected void unbindFromService() { - if (controllerService != null) { + if (serviceShouldUnbind) { unbindService(connection); + serviceShouldUnbind = false; } } @@ -408,6 +494,10 @@ protected void logPackageVersions() { RobotLog.logBuildConfig(org.firstinspires.inspection.BuildConfig.class); } + protected void logDeviceSerialNumber() { + RobotLog.ii(TAG, "Android device serial number: " + Device.getSerialNumberOrUnknown()); + } + protected void readNetworkType() { // The code here used to defer to the value found in a configuration file @@ -418,10 +508,17 @@ protected void readNetworkType() { // Moreover, the non-Wifi-Direct networking is end-of-life, so the simplest and most robust // (e.g.: no one can screw things up by messing with the contents of the config file) fix is // to do away with configuration file entirely. - networkType = NetworkType.WIFIDIRECT; + // + // Control hubs are always running the access point model. Everything else, for the time + // being always runs the wifi direct model. + if (Device.isRevControlHub() == true) { + networkType = NetworkType.RCWIRELESSAP; + } else { + networkType = NetworkType.fromString(preferencesHelper.readString(context.getString(R.string.pref_pairing_kind), NetworkType.globalDefaultAsString())); + } // update the app_settings - preferencesHelper.writeStringPrefIfDifferent(context.getString(R.string.pref_network_connection_type), networkType.toString()); + preferencesHelper.writeStringPrefIfDifferent(context.getString(R.string.pref_pairing_kind), networkType.toString()); } @Override @@ -455,18 +552,18 @@ public boolean onOptionsItemSelected(MenuItem item) { if (cfgFileMgr.getActiveConfig().isNoConfig()) { // Tell the user they must configure the robot before starting programming mode. // TODO: as we are no longer truly 'modal' this warning should be adapted - AppUtil.getInstance().showToast(UILocation.BOTH, context, context.getString(R.string.toastConfigureRobotBeforeProgrammingMode)); + AppUtil.getInstance().showToast(UILocation.BOTH, context.getString(R.string.toastConfigureRobotBeforeProgrammingMode)); } else { Intent programmingModeIntent = new Intent(AppUtil.getDefContext(), ProgrammingModeActivity.class); programmingModeIntent.putExtra( LaunchActivityConstantsList.PROGRAMMING_MODE_ACTIVITY_PROGRAMMING_WEB_HANDLERS, - new LocalByRefIntentExtraHolder(programmingWebHandlers)); + new LocalByRefIntentExtraHolder(programmingModeManager)); startActivity(programmingModeIntent); } return true; } else if (id == R.id.action_program_and_manage) { Intent programmingModeIntent = new Intent(AppUtil.getDefContext(), ProgramAndManageActivity.class); - RobotControllerWebInfo webInfo = programmingWebHandlers.getWebServer().getConnectionInformation(); + RobotControllerWebInfo webInfo = programmingModeManager.getWebServer().getConnectionInformation(); programmingModeIntent.putExtra(LaunchActivityConstantsList.RC_WEB_INFO, webInfo.toJson()); startActivity(programmingModeIntent); } else if (id == R.id.action_inspection_mode) { @@ -481,7 +578,7 @@ else if (id == R.id.action_blocks) { } else if (id == R.id.action_restart_robot) { dimmer.handleDimTimer(); - AppUtil.getInstance().showToast(UILocation.BOTH, context, context.getString(R.string.toastRestartingRobot)); + AppUtil.getInstance().showToast(UILocation.BOTH, context.getString(R.string.toastRestartingRobot)); requestRobotRestart(); return true; } @@ -498,8 +595,7 @@ else if (id == R.id.action_settings) { return true; } else if (id == R.id.action_about) { - Intent intent = new Intent(AppUtil.getDefContext(), AboutActivity.class); - intent.putExtra(LaunchActivityConstantsList.ABOUT_ACTIVITY_CONNECTION_TYPE, networkType); + Intent intent = new Intent(AppUtil.getDefContext(), FtcAboutActivity.class); startActivity(intent); return true; } @@ -515,13 +611,38 @@ else if (id == R.id.action_exit_app) { public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // don't destroy assets on screen rotation + updateMonitorLayout(newConfig); + } + + /** + * Updates the orientation of monitorContainer (which contains cameraMonitorView and + * tfodMonitorView) based on the given configuration. Makes the children split the space. + */ + private void updateMonitorLayout(Configuration configuration) { + LinearLayout monitorContainer = (LinearLayout) findViewById(R.id.monitorContainer); + if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { + // When the phone is landscape, lay out the monitor views horizontally. + monitorContainer.setOrientation(LinearLayout.HORIZONTAL); + for (int i = 0; i < monitorContainer.getChildCount(); i++) { + View view = monitorContainer.getChildAt(i); + view.setLayoutParams(new LayoutParams(0, LayoutParams.MATCH_PARENT, 1 /* weight */)); + } + } else { + // When the phone is portrait, lay out the monitor views vertically. + monitorContainer.setOrientation(LinearLayout.VERTICAL); + for (int i = 0; i < monitorContainer.getChildCount(); i++) { + View view = monitorContainer.getChildAt(i); + view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 0, 1 /* weight */)); + } + } + monitorContainer.requestLayout(); } @Override protected void onActivityResult(int request, int result, Intent intent) { if (request == REQUEST_CONFIG_WIFI_CHANNEL) { if (result == RESULT_OK) { - AppUtil.getInstance().showToast(UILocation.BOTH, context, context.getString(R.string.toastWifiConfigurationComplete)); + AppUtil.getInstance().showToast(UILocation.BOTH, context.getString(R.string.toastWifiConfigurationComplete)); } } // was some historical confusion about launch codes here, so we err safely @@ -537,7 +658,7 @@ public void onServiceBind(final FtcRobotControllerService service) { updateUI.setControllerService(controllerService); updateUIAndRequestRobotSetup(); - programmingWebHandlers.setState(new FtcRobotControllerServiceState() { + programmingModeManager.setState(new FtcRobotControllerServiceState() { @NonNull @Override public WebServer getWebServer() { @@ -555,14 +676,20 @@ private void updateUIAndRequestRobotSetup() { if (controllerService != null) { callback.networkConnectionUpdate(controllerService.getNetworkConnectionStatus()); callback.updateRobotStatus(controllerService.getRobotStatus()); - requestRobotSetup(); + // Only show this first-time toast on headless systems: what we have now on non-headless suffices + requestRobotSetup(LynxConstants.isRevControlHub() + ? new Runnable() { + @Override public void run() { + showRestartRobotCompleteToast(R.string.toastRobotSetupComplete); + } + } + : null); } } - private void requestRobotSetup() { + private void requestRobotSetup(@Nullable Runnable runOnComplete) { if (controllerService == null) return; - HardwareFactory factory; RobotConfigFile file = cfgFileMgr.getActiveConfigAndUpdateUI(); HardwareFactory hardwareFactory = new HardwareFactory(context); try { @@ -572,16 +699,16 @@ private void requestRobotSetup() { hardwareFactory.setXmlPullParser(file.getXml()); cfgFileMgr.setActiveConfigAndUpdateUI(false, file); } - factory = hardwareFactory; OpModeRegister userOpModeRegister = createOpModeRegister(); - eventLoop = new FtcEventLoop(factory, userOpModeRegister, callback, this, programmingModeController); - FtcEventLoopIdle idleLoop = new FtcEventLoopIdle(factory, userOpModeRegister, callback, this, programmingModeController); + eventLoop = new FtcEventLoop(hardwareFactory, userOpModeRegister, callback, this, programmingModeController); + FtcEventLoopIdle idleLoop = new FtcEventLoopIdle(hardwareFactory, userOpModeRegister, callback, this, programmingModeController); controllerService.setCallback(callback); - controllerService.setupRobot(eventLoop, idleLoop); + controllerService.setupRobot(eventLoop, idleLoop, runOnComplete); passReceivedUsbAttachmentsToEventLoop(); + AndroidBoard.showErrorIfUnknownControlHub(); } protected OpModeRegister createOpModeRegister() { @@ -595,10 +722,36 @@ private void shutdownRobot() { private void requestRobotRestart() { AppUtil.getInstance().showToast(UILocation.BOTH, AppUtil.getDefContext().getString(R.string.toastRestartingRobot)); // + RobotLog.clearGlobalErrorMsg(); + RobotLog.clearGlobalWarningMsg(); shutdownRobot(); - requestRobotSetup(); - // - AppUtil.getInstance().showToast(UILocation.BOTH, AppUtil.getDefContext().getString(R.string.toastRestartRobotComplete)); + requestRobotSetup(new Runnable() { + @Override public void run() { + showRestartRobotCompleteToast(R.string.toastRestartRobotComplete); + } + }); + } + + private void showRestartRobotCompleteToast(@StringRes int resid) { + AppUtil.getInstance().showToast(UILocation.BOTH, AppUtil.getDefContext().getString(resid)); + } + + private void checkPreferredChannel() { + // For P2P network, check to see what preferred channel is. + if (networkType == NetworkType.WIFIDIRECT) { + int prefChannel = preferencesHelper.readInt(getString(com.qualcomm.ftccommon.R.string.pref_wifip2p_channel), -1); + if (prefChannel == -1) { + prefChannel = 0; + RobotLog.vv(TAG, "pref_wifip2p_channel: No preferred channel defined. Will use a default value of %d", prefChannel); + } else { + RobotLog.vv(TAG, "pref_wifip2p_channel: Found existing preferred channel (%d).", prefChannel); + } + + // attempt to set the preferred channel. + RobotLog.vv(TAG, "pref_wifip2p_channel: attempting to set preferred channel..."); + wifiDirectChannelChanger = new WifiDirectChannelChanger(); + wifiDirectChannelChanger.changeToChannel(prefChannel); + } } protected void hittingMenuButtonBrightensScreen() { @@ -619,7 +772,44 @@ protected class SharedPreferencesListener implements SharedPreferences.OnSharedP @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(context.getString(R.string.pref_app_theme))) { ThemedActivity.restartForAppThemeChange(getTag(), getString(R.string.appThemeChangeRestartNotifyRC)); + } else if (key.equals(context.getString(R.string.pref_wifi_automute))) { + if (preferencesHelper.readBoolean(context.getString(R.string.pref_wifi_automute), false)) { + initWifiMute(true); + } else { + initWifiMute(false); + } } } } + + protected void initWifiMute(boolean enable) { + if (enable) { + wifiMuteStateMachine = new WifiMuteStateMachine(); + wifiMuteStateMachine.initialize(); + wifiMuteStateMachine.start(); + + motionDetection = new MotionDetection(2.0, 10); + motionDetection.startListening(); + motionDetection.registerListener(new MotionDetection.MotionDetectionListener() { + @Override + public void onMotionDetected(double vector) + { + wifiMuteStateMachine.consumeEvent(WifiMuteEvent.USER_ACTIVITY); + } + }); + } else { + wifiMuteStateMachine.stop(); + wifiMuteStateMachine = null; + motionDetection.stopListening(); + motionDetection.purgeListeners(); + motionDetection = null; + } + } + + @Override + public void onUserInteraction() { + if (wifiMuteStateMachine != null) { + wifiMuteStateMachine.consumeEvent(WifiMuteEvent.USER_ACTIVITY); + } + } } diff --git a/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/PermissionValidatorWrapper.java b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/PermissionValidatorWrapper.java new file mode 100644 index 00000000000..1ae71b08ade --- /dev/null +++ b/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/PermissionValidatorWrapper.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018 Craig MacFarlane + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted + * (subject to the limitations in the disclaimer below) provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, this list of conditions + * and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions + * and the following disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of Craig MacFarlane nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written permission. + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS + * SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.firstinspires.ftc.robotcontroller.internal; + +import android.Manifest; +import android.os.Bundle; + +import com.qualcomm.ftcrobotcontroller.R; + +import org.firstinspires.ftc.robotcore.internal.system.Misc; +import org.firstinspires.ftc.robotcore.internal.system.PermissionValidatorActivity; + +import java.util.ArrayList; +import java.util.List; + +public class PermissionValidatorWrapper extends PermissionValidatorActivity { + + private final String TAG = "PermissionValidatorWrapper"; + + /* + * The list of dangerous permissions the robot controller needs. + */ + protected List robotControllerPermissions = new ArrayList() {{ + add(Manifest.permission.WRITE_EXTERNAL_STORAGE); + add(Manifest.permission.READ_EXTERNAL_STORAGE); + add(Manifest.permission.CAMERA); + add(Manifest.permission.ACCESS_COARSE_LOCATION); + }}; + + private final static Class startApplication = FtcRobotControllerActivity.class; + + public String mapPermissionToExplanation(final String permission) { + if (permission.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + return Misc.formatForUser(R.string.permRcWriteExternalStorageExplain); + } else if (permission.equals(Manifest.permission.READ_EXTERNAL_STORAGE)) { + return Misc.formatForUser(R.string.permRcReadExternalStorageExplain); + } else if (permission.equals(Manifest.permission.CAMERA)) { + return Misc.formatForUser(R.string.permRcCameraExplain); + } else if (permission.equals(Manifest.permission.ACCESS_COARSE_LOCATION)) { + return Misc.formatForUser(R.string.permAccessCoarseLocationExplain); + } + return Misc.formatForUser(R.string.permGenericExplain); + } + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + permissions = robotControllerPermissions; + } + + protected Class onStartApplication() + { + FtcRobotControllerActivity.setPermissionsValidated(); + return startApplication; + } +} diff --git a/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml b/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml index b47f9c24782..c74e2dee2b3 100644 --- a/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml +++ b/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml @@ -126,11 +126,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. android:layout_above="@+id/textGamepad1"> + android:orientation="vertical"> + + + + + + + + + + + + + diff --git a/README.md b/README.md index 7a343fc17b6..cd0dd25fd76 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,15 @@ +## NOTICE + +This repository contains v5.0 of the FTC SDK. No further versions will pushed to https://github.com/ftctechnh/ftc_app. + +If you are looking for the most current version of the FTC SDK software, please visit the FtcRobotController GitHub repository: + +[FtcRobotController Repository](https://github.com/FIRST-Tech-Challenge/FtcRobotController) + +v5.0 has also been posted to https://github.com/FIRST-Tech-Challenge/SkyStone where all further releases will be posted for the 2019/20 season. + +Why are we doing this? Git/GitHub is not designed to store large binary blobs. As such the ftc_app repository has grown to over 1GB. Not only does this violate GitHub's usage policies, but puts an undue burden on users of the repository when they download it. For the foreseeable future a season specific version of the repository will be hosted at the url above. Different approaches to prevent the size problem from recurring are being evaluated by the FTC Technology Team. We realize that this creates a problem with teams that have maintained a history of software within the ftc_app workspace. We appreciate your patience and understanding as work to migrate to a permanent solution. + ## Welcome! This GitHub repository contains the source code that is used to build an Android app to control a *FIRST* Tech Challenge competition robot. To use this SDK, download/clone the entire project to your local computer. @@ -41,6 +53,179 @@ For technical questions regarding the SDK, please visit the FTC Technology forum       http://ftcforum.usfirst.org/forumdisplay.php?156-FTC-Technology +************************************************************************************** +# Release Information +************************************************************************************** + +Version 5.0 (built on 19.06.14) + + * Support for the REV Robotics Control Hub. + * Adds a Java preview pane to the Blocks editor. + * Adds a new offline export feature to the Blocks editor. + * Display wifi channel in Network circle on Driver Station. + * Adds calibration for Logitech C270 + * Updates build tooling and target SDK. + * Compliance with Google's permissions infrastructure (Required after build tooling update). + * Keep Alives to mitigate the Motorola wifi scanning problem. Telemetry substitute no longer necessary. + * Improves Vuforia error reporting. + * Fixes ftctechnh/ftc_app issues 621, 713. + * Miscellaneous bug fixes and improvements. + +************************************************************************************** +# Release Information +************************************************************************************** + +Version 4.3 (built on 18.10.31) + * Includes missing TensorFlow-related libraries and files. + +************************************************************************************** +# Release Information +************************************************************************************** + +Version 4.2 (built on 18.10.30) + * Includes fix to avoid deadlock situation with WatchdogMonitor which could result in USB communication errors. + - Comm error appeared to require that user disconnect USB cable and restart the Robot Controller app to recover. + - robotControllerLog.txt would have error messages that included the words "E RobotCore: lynx xmit lock: #### abandoning lock:" + * Includes fix to correctly list the parent module address for a REV Robotics Expansion Hub in a configuration (.xml) file. + - Bug in versions 4.0 and 4.1 would incorrect list the address module for a parent REV Robotics device as "1". + - If the parent module had a higher address value than the daisy-chained module, then this bug would prevent the Robot Controller from communicating with the downstream Expansion Hub. + * Added requirement for ACCESS_COARSE_LOCATION to allow a Driver Station running Android Oreo to scan for Wi-Fi Direct devices. + * Added google() repo to build.gradle because aapt2 must be downloaded from the google() repository beginning with version 3.2 of the Android Gradle Plugin. + - Important Note: Android Studio users will need to be connected to the Internet the first time build the ftc_app project. + - Internet connectivity is required for the first build so the appropriate files can be downloaded from the Google repository. + - Users should not need to be connected to the Internet for subsequent builds. + - This should also fix buid issue where Android Studio would complain that it "Could not find com.android.tools.lint:lint-gradle:26.1.4" (or similar). + * Added support for REV Spark Mini motor controller as part of the configuration menu for a servo/PWM port on the REV Expansion Hub. + * Provide examples for playing audio files in an Op Mode. + * Block Development Tool Changes + - Includes a fix for a problem with the Velocity blocks that were reported in the FTC Technology forum (Blocks Programming subforum). + - Change the "Save completed successfully." message to a white color so it will contrast with a green background. + - Fixed the "Download image" feature so it will work if there are text blocks in the op mode. + * Introduce support for Google's TensorFlow Lite technology for object detetion for 2018-2019 game. + - TensorFlow lite can recognize Gold Mineral and Silver Mineral from 2018-2019 game. + - Example Java and Block op modes are included to show how to determine the relative position of the gold block (left, center, right). + +************************************************************************************** +# Release Information +************************************************************************************** + +Version 4.1 (released on 18.09.24) + +Changes include: + * Fix to prevent crash when deprecated configuration annotations are used. + * Change to allow FTC Robot Controller APK to be auto-updated using FIRST Global Control Hub update scripts. + * Removed samples for non supported / non legal hardware. + * Improvements to Telemetry.addData block with "text" socket. + * Updated Blocks sample op mode list to include Rover Ruckus Vuforia example. + * Update SDK library version number. + +************************************************************************************** +# Release Information +************************************************************************************** + +Version 4.0 (released on 18.09.12) + +Changes include: + * Initial support for UVC compatible cameras + - If UVC camera has a unique serial number, RC will detect and enumerate by serial number. + - If UVC camera lacks a unique serial number, RC will only support one camera of that type connected. + - Calibration settings for a few cameras are included (see TeamCode/src/main/res/xml/teamwebcamcalibrations.xml for details). + - User can upload calibration files from Program and Manage web interface. + - UVC cameras seem to draw a fair amount of electrical current from the USB bus. + + This does not appear to present any problems for the REV Robotics Control Hub. + + This does seem to create stability problems when using some cameras with an Android phone-based Robot Controller. + + FTC Tech Team is investigating options to mitigate this issue with the phone-based Robot Controllers. + - Updated sample Vuforia Navigation and VuMark Op Modes to demonstrate how to use an internal phone-based camera and an external UVC webcam. + + * Support for improved motor control. + - REV Robotics Expansion Hub firmware 1.8 and greater will support a feed forward mechanism for closed loop motor control. + - FTC SDK has been modified to support PIDF coefficients (proportional, integral, derivative, and feed forward). + - FTC Blocks development tool modified to include PIDF programming blocks. + - Deprecated older PID-related methods and variables. + - REV's 1.8.x PIDF-related changes provide a more linear and accurate way to control a motor. + + * Wireless + - Added 5GHz support for wireless channel changing for those devices that support it. + + Tested with Moto G5 and E4 phones. + + Also tested with other (currently non-approved) phones such as Samsung Galaxy S8. + +* Improved Expansion Hub firmware update support in Robot Controller app + - Changes to make the system more robust during the firmware update process (when performed through Robot Controller app). + - User no longer has to disconnect a downstream daisy-chained Expansion Hub when updating an Expansion Hub's firmware. + + If user is updating an Expansion Hub's firmware through a USB connection, he/she does not have to disconnect RS485 connection to other Expansion Hubs. + + The user still must use a USB connection to update an Expansion Hub's firmware. + + The user cannot update the Expansion Hub firmware for a downstream device that is daisy chained through an RS485 connection. + - If an Expansion Hub accidentally gets "bricked" the Robot Controller app is now more likely to recognize the Hub when it scans the USB bus. + + Robot Controller app should be able to detect an Expansion Hub, even if it accidentally was bricked in a previous update attempt. + + Robot Controller app should be able to install the firmware onto the Hub, even if if accidentally was bricked in a previous update attempt. + + * Resiliency + - FTC software can detect and enable an FTDI reset feature that is available with REV Robotics v1.8 Expansion Hub firmware and greater. + + When enabled, the Expansion Hub can detect if it hasn't communicated with the Robot Controller over the FTDI (USB) connection. + + If the Hub hasn't heard from the Robot Controller in a while, it will reset the FTDI connection. + + This action helps system recover from some ESD-induced disruptions. + - Various fixes to improve reliability of FTC software. + + * Blocks + - Fixed errors with string and list indices in blocks export to java. + - Support for USB connected UVC webcams. + - Refactored optimized Blocks Vuforia code to support Rover Ruckus image targets. + - Added programming blocks to support PIDF (proportional, integral, derivative and feed forward) motor control. + - Added formatting options (under Telemetry and Miscellaneous categories) so user can set how many decimal places to display a numerical value. + - Support to play audio files (which are uploaded through Blocks web interface) on Driver Station in addition to the Robot Controller. + - Fixed bug with Download Image of Blocks feature. + - Support for REV Robotics Blinkin LED Controller. + - Support for REV Robotics 2m Distance Sensor. + - Added support for a REV Touch Sensor (no longer have to configure as a generic digital device). + - Added blocks for DcMotorEx methods. + + These are enhanced methods that you can use when supported by the motor controller hardware. + + The REV Robotics Expansion Hub supports these enhanced methods. + + Enhanced methods include methods to get/set motor velocity (in encoder pulses per second), get/set PIDF coefficients, etc.. + + * Modest Improvements in Logging + - Decrease frequency of battery checker voltage statements. + - Removed non-FTC related log statements (wherever possible). + - Introduced a "Match Logging" feature. + + Under "Settings" a user can enable/disable this feature (it's disabled by default). + + If enabled, user provides a "Match Number" through the Driver Station user interface (top of the screen). + * The Match Number is used to create a log file specifically with log statements from that particular Op Mode run. + * Match log files are stored in /sdcard/FIRST/matlogs on the Robot Controller. + * Once an op mode run is complete, the Match Number is cleared. + * This is a convenient way to create a separate match log with statements only related to a specific op mode run. + + * New Devices + - Support for REV Robotics Blinkin LED Controller. + - Support for REV Robotics 2m Distance Sensor. + - Added configuration option for REV 20:1 HD Hex Motor. + - Added support for a REV Touch Sensor (no longer have to configure as a generic digital device). + + * Miscellaneous + - Fixed some errors in the definitions for acceleration and velocity in our javadoc documentation. + - Added ability to play audio files on Driver Station + - When user is configuring an Expansion Hub, the LED on the Expansion Hub will change blink pattern (purple-cyan) to indicate which Hub is currently being configured. + - Renamed I2cSensorType to I2cDeviceType. + - Added an external sample Op Mode that demonstrates localization using 2018-2019 (Rover Ruckus presented by QualComm) Vuforia targets. + - Added an external sample Op Mode that demonstrates how to use the REV Robotics 2m Laser Distance Sensor. + - Added an external sample Op Mode that demonstrates how to use the REV Robotics Blinkin LED Controller. + - Re-categorized external Java sample Op Modes to "TeleOp" instead of "Autonomous". + +Known issues: + * Initial support for UVC compatible cameras + - UVC cameras seem to draw significant amount of current from the USB bus. + + This does not appear to present any problems for the REV Robotics Control Hub. + + This does seem to create stability problems when using some cameras with an Android phone-based Robot Controller. + + FTC Tech Team is investigating options to mitigate this issue with the phone-based Robot Controllers. + - There might be a possible deadlock which causes the RC to become unresponsive when using a UVC webcam with a Nougat Android Robot Controller. + + * Wireless + - When user selects a wireless channel, this channel does not necessarily persist if the phone is power cycled. + + Tech Team is hoping to eventually address this issue in a future release. + + Issue has been present since apps were introduced (i.e., it is not new with the v4.0 release). + - Wireless channel is not currently displayed for WiFi Direct connections. + + * Miscellaneous + - The blink indication feature that shows which Expansion Hub is currently being configured does not work for a newly created configuration file. + + User has to first save a newly created configuration file and then close and re-edit the file in order for blink indicator to work. ************************************************************************************** diff --git a/TeamCode/build.release.gradle b/TeamCode/build.release.gradle index 17567abc8cf..bc8708f4246 100644 --- a/TeamCode/build.release.gradle +++ b/TeamCode/build.release.gradle @@ -1,8 +1,9 @@ dependencies { - compile project(':FtcRobotController') - compile (name: 'RobotCore-release', ext: 'aar') - compile (name: 'Hardware-release', ext: 'aar') - compile (name: 'FtcCommon-release', ext: 'aar') - compile (name:'Analytics-release', ext:'aar') - compile (name:'WirelessP2p-release', ext:'aar') + implementation project(':FtcRobotController') + implementation (name: 'RobotCore-release', ext: 'aar') + implementation (name: 'Hardware-release', ext: 'aar') + implementation (name: 'FtcCommon-release', ext: 'aar') + implementation (name: 'WirelessP2p-release', ext:'aar') + implementation (name: 'tfod-release', ext:'aar') + implementation (name: 'tensorflow-lite-0.0.0-nightly', ext:'aar') } diff --git a/TeamCode/src/main/res/raw/readme.md b/TeamCode/src/main/res/raw/readme.md new file mode 100644 index 00000000000..355a3c444b3 --- /dev/null +++ b/TeamCode/src/main/res/raw/readme.md @@ -0,0 +1 @@ +Place your sound files in this folder to use them as project resources. \ No newline at end of file diff --git a/TeamCode/src/main/res/xml/teamwebcamcalibrations.xml b/TeamCode/src/main/res/xml/teamwebcamcalibrations.xml new file mode 100644 index 00000000000..e2819d297d5 --- /dev/null +++ b/TeamCode/src/main/res/xml/teamwebcamcalibrations.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.common.gradle b/build.common.gradle index 7972001e976..082cfd49c86 100644 --- a/build.common.gradle +++ b/build.common.gradle @@ -21,8 +21,7 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 23 - buildToolsVersion '25.0.3' + compileSdkVersion 28 signingConfigs { debug { @@ -33,10 +32,14 @@ android { } } + aaptOptions { + noCompress "tflite" + } + defaultConfig { applicationId 'com.qualcomm.ftcrobotcontroller' minSdkVersion 19 - targetSdkVersion 19 + targetSdkVersion 26 /** * We keep the versionCode and versionName of robot controller applications in sync with @@ -68,6 +71,7 @@ android { } // Advanced user code might just want to use Vuforia directly, so we set up the libs as needed + // http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html buildTypes { release { // Disable debugging for release versions so it can be uploaded to Google Play. @@ -78,6 +82,8 @@ android { } debug { debuggable true + jniDebuggable true + renderscriptDebuggable true ndk { abiFilters "armeabi-v7a" } diff --git a/build.gradle b/build.gradle index a267db58fc6..bb3b818fc2b 100644 --- a/build.gradle +++ b/build.gradle @@ -5,11 +5,19 @@ */ buildscript { repositories { + google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.4.1' } } - +// This is now required because aapt2 has to be downloaded from the +// google() repository beginning with version 3.2 of the Android Gradle Plugin +allprojects { + repositories { + google() + jcenter() + } +} diff --git a/doc/apk/FtcDriverStation-release.apk b/doc/apk/FtcDriverStation-release.apk index 90703cf89d5..df48484942c 100644 Binary files a/doc/apk/FtcDriverStation-release.apk and b/doc/apk/FtcDriverStation-release.apk differ diff --git a/doc/apk/FtcRobotController-release.apk b/doc/apk/FtcRobotController-release.apk index 28ed76b13bf..d925deea3d3 100644 Binary files a/doc/apk/FtcRobotController-release.apk and b/doc/apk/FtcRobotController-release.apk differ diff --git a/doc/javadoc/allclasses-frame.html b/doc/javadoc/allclasses-frame.html index eb75ffd67d0..136cf2e051e 100644 --- a/doc/javadoc/allclasses-frame.html +++ b/doc/javadoc/allclasses-frame.html @@ -11,8 +11,6 @@

All Classes

@@ -155,10 +159,12 @@

Constructor Summary

Constructor and Description -LynxUsbDeviceContainer(LynxUsbDeviceImpl lynxUsbDevice)  +LynxUsbDeviceContainer(LynxUsbDeviceImpl lynxUsbDevice, + SerialNumber serialNumber)  -LynxUsbDeviceContainer(RobotUsbDevice robotUsbDevice)  +LynxUsbDeviceContainer(RobotUsbDevice robotUsbDevice, + SerialNumber serialNumber)  @@ -229,12 +235,21 @@

lynxUsbDevice

-
    +
    • robotUsbDevice

      protected final RobotUsbDevice robotUsbDevice
    + + + +
      +
    • +

      serialNumber

      +
      protected final SerialNumber serialNumber
      +
    • +
@@ -243,22 +258,24 @@

robotUsbDevice

Constructor Detail

- +
  • LynxUsbDeviceContainer

    -
    public LynxUsbDeviceContainer(LynxUsbDeviceImpl lynxUsbDevice)
    +
    public LynxUsbDeviceContainer(LynxUsbDeviceImpl lynxUsbDevice,
    +                              SerialNumber serialNumber)
- +
  • LynxUsbDeviceContainer

    -
    public LynxUsbDeviceContainer(RobotUsbDevice robotUsbDevice)
    +
    public LynxUsbDeviceContainer(RobotUsbDevice robotUsbDevice,
    +                              SerialNumber serialNumber)
diff --git a/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopBase.html b/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopBase.html index 7282f8213a6..546c1f01fc6 100644 --- a/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopBase.html +++ b/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopBase.html @@ -17,7 +17,7 @@ catch(err) { } //--> -var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10}; +var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10,"i33":10,"i34":10,"i35":10,"i36":10,"i37":10,"i38":10}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -160,7 +160,7 @@

Field Summary

Field and Description -protected Activity +protected android.app.Activity activityContext  @@ -223,10 +223,10 @@

Constructor Summary

protected -FtcEventLoopBase(HardwareFactory hardwareFactory, +FtcEventLoopBase(HardwareFactory hardwareFactory, OpModeRegister userOpmodeRegister, UpdateUI.Callback callback, - Activity activityContext, + android.app.Activity activityContext, ProgrammingModeController programmingModeController)  @@ -249,7 +249,7 @@

Method Summary

checkForChangedOpModes()  -protected void +protected boolean enterFirmwareUpdateMode(RobotUsbDevice robotUsbDevice)  @@ -258,7 +258,7 @@

Method Summary

protected java.util.List<USBAccessibleLynxModule> -getUSBAccessibleLynxDevices(boolean includeModuleAddresses)  +getUSBAccessibleLynxDevices(boolean forFirmwareUpdate)  protected void @@ -310,96 +310,122 @@

Method Summary

protected void +handleCommandRequestAboutInfo(Command command)  + + +protected void handleCommandRequestConfigurations()
Serialize the entire list of config file metadata and send to the driver station
- + protected void handleCommandRequestConfigurationTemplates()
Serialize the entire list of config file metadata and send to the driver station
- + protected void handleCommandRequestInspectionReport()
Return an inspection report of this (robot controller) device back to the caller
- + protected void handleCommandRequestParticularConfiguration(java.lang.String data)  - + protected void handleCommandRequestRememberedGroups()
Serialize the list of remembered Wifi Direct groups and send it to the driver station
- + protected void handleCommandRestartRobot()  - + protected void handleCommandSaveConfiguration(java.lang.String fileInfo)  - + protected void handleCommandShowDialog(Command command)  - + protected void handleCommandShowProgress(Command command)  - + protected void handleCommandShowToast(Command command)  - + protected void handleCommandStartDriverStationProgramAndManage()  - + protected void handleCommandStartProgrammingMode()
Starts programming mode on the robot controller, as requested by driver station.
- + protected void handleCommandStopProgrammingMode()
Stops programming mode on the robot controller, as requested by driver station.
- + +protected CallbackResult +handleCommandVisuallyConfirmWifiReset()  + + +protected CallbackResult +handleCommandVisuallyIdentify(Command command)  + + void init(EventLoopManager eventLoopManager)
Init method, this will be called before the first call to loop.
- + CallbackResult processCommand(Command command)
Process command method, this will be called if the event loop manager receives a user defined command.
- + protected void sendUIState()  - + protected USBScanManager startUsbScanMangerIfNecessary()  - + +protected void +talkToParentLynxModule(DeviceManager deviceManager, + LynxUsbDevice lynxUsbDevice, + int moduleAddress, + Consumer<LynxModule> consumer)  + + void teardown()
Teardown method, this will be called after the last call to loop.
- + +protected boolean +updateFirmwareOnce(FtcEventLoopBase.LynxUsbDeviceContainer lynxUsbDevice, + java.lang.String imageFileName, + byte[] firmwareImage, + SerialNumber serialNumber)  + + protected boolean updateLynxFirmware(SerialNumber serialNumber, com.qualcomm.ftccommon.CommandList.FWImage imageFileName) @@ -420,7 +446,7 @@

Methods inherited from class java.lang.Object

Methods inherited from interface com.qualcomm.robotcore.eventloop.EventLoop

-getOpModeManager, handleUsbModuleAttach, handleUsbModuleDetach, loop, onUsbDeviceAttached, pendUsbDeviceAttachment, processedRecentlyAttachedUsbDevices, refreshUserTelemetry, requestOpModeStop +getOpModeManager, handleUsbModuleAttach, handleUsbModuleDetach, loop, onUsbDeviceAttached, pendUsbDeviceAttachment, processedRecentlyAttachedUsbDevices, refreshUserTelemetry, requestOpModeStop @@ -464,7 +490,7 @@

networkConnectionHandler

  • activityContext

    -
    protected Activity activityContext
    +
    protected android.app.Activity activityContext
@@ -538,7 +564,7 @@

registeredOpModes

Constructor Detail

- +
    @@ -547,7 +573,7 @@

    FtcEventLoopBase

    protected FtcEventLoopBase(HardwareFactory hardwareFactory,
                                OpModeRegister userOpmodeRegister,
                                UpdateUI.Callback callback,
    -                           Activity activityContext,
    +                           android.app.Activity activityContext,
                                ProgrammingModeController programmingModeController)
@@ -770,13 +796,25 @@

updateLynxFirmware

to be the indicated firmware.
+ + + +
  • enterFirmwareUpdateMode

    -
    protected void enterFirmwareUpdateMode(RobotUsbDevice robotUsbDevice)
    +
    protected boolean enterFirmwareUpdateMode(RobotUsbDevice robotUsbDevice)
@@ -803,7 +841,7 @@

getLynxUsbDeviceForFirmwareUpdate

+ + + +
    +
  • +

    talkToParentLynxModule

    +
    protected void talkToParentLynxModule(DeviceManager deviceManager,
    +                                      LynxUsbDevice lynxUsbDevice,
    +                                      int moduleAddress,
    +                                      Consumer<LynxModule> consumer)
    +                               throws RobotCoreException,
    +                                      java.lang.InterruptedException,
    +                                      LynxNackException
    +
    +
    Throws:
    +
    RobotCoreException
    +
    java.lang.InterruptedException
    +
    LynxNackException
    +
    +
  • +
@@ -932,15 +991,42 @@

handleCommandRequestInspectionReport

Return an inspection report of this (robot controller) device back to the caller
+ + + +
    +
  • +

    handleCommandRequestAboutInfo

    +
    protected void handleCommandRequestAboutInfo(Command command)
    +
  • +
-
    +
    • handleCommandDisconnectWifiDirect

      protected void handleCommandDisconnectWifiDirect()
    + + + +
      +
    • +

      handleCommandVisuallyIdentify

      +
      protected CallbackResult handleCommandVisuallyIdentify(Command command)
      +
    • +
    + + + +
      +
    • +

      handleCommandVisuallyConfirmWifiReset

      +
      protected CallbackResult handleCommandVisuallyConfirmWifiReset()
      +
    • +
diff --git a/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopHandler.html b/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopHandler.html index 8dc794bd8bb..1a314161ad5 100644 --- a/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopHandler.html +++ b/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopHandler.html @@ -17,8 +17,8 @@ catch(err) { } //--> -var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10}; -var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; +var methods = {"i0":10,"i1":9,"i2":10,"i3":9,"i4":9,"i5":9,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10}; +var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; var tableTab = "tableTab"; @@ -132,21 +132,33 @@

Field Summary

callback  +protected static boolean +DEBUG  + + protected EventLoopManager eventLoopManager  - + protected HardwareFactory hardwareFactory  + +protected HardwareMap +hardwareMap +
the actual hardware map seen by the user
+ + protected HardwareMap -hardwareMap  +hardwareMapExtra +
the hardware map in which we keep any extra devices (ones not used by the user) we need to instantiate
+ static java.lang.String NO_VOLTAGE_SENSOR -
This string is sent in the robot battery telemetry payload to indicate +
This string is sent in the robot battery telemetry payload to identify that no voltage sensor is available on the robot.
@@ -183,7 +195,7 @@

Field Summary

robotControllerBatteryCheckerInterval  -protected Context +protected android.content.Context robotControllerContext  @@ -221,9 +233,9 @@

Constructor Summary

Constructor and Description -FtcEventLoopHandler(HardwareFactory hardwareFactory, +FtcEventLoopHandler(HardwareFactory hardwareFactory, UpdateUI.Callback callback, - Context robotControllerContext)  + android.content.Context robotControllerContext)  @@ -235,7 +247,7 @@

Constructor Summary

Method Summary

- + @@ -245,50 +257,63 @@

Method Summary

- - + + - - + + - - + + + + + + - + - + - + - + + + + + - + - + - + - + - + - + - + @@ -357,7 +382,7 @@

TAG

  • NO_VOLTAGE_SENSOR

    public static final java.lang.String NO_VOLTAGE_SENSOR
    -
    This string is sent in the robot battery telemetry payload to indicate +
    This string is sent in the robot battery telemetry payload to identify that no voltage sensor is available on the robot.
    See Also:
    @@ -365,6 +390,19 @@

    NO_VOLTAGE_SENSOR

  • + + + + @@ -389,7 +427,7 @@

    hardwareFactory

    • robotControllerContext

      -
      protected final Context robotControllerContext
      +
      protected final android.content.Context robotControllerContext
    @@ -512,10 +550,21 @@

    updateUIInterval

    -
      +
      • hardwareMap

        protected HardwareMap hardwareMap
        +
        the actual hardware map seen by the user
        +
      • +
      + + + +
        +
      • +

        hardwareMapExtra

        +
        protected HardwareMap hardwareMapExtra
        +
        the hardware map in which we keep any extra devices (ones not used by the user) we need to instantiate
      @@ -526,7 +575,7 @@

      hardwareMap

      Constructor Detail

      - +
        @@ -534,7 +583,7 @@

        Constructor Detail

        FtcEventLoopHandler

        public FtcEventLoopHandler(HardwareFactory hardwareFactory,
                                    UpdateUI.Callback callback,
        -                           Context robotControllerContext)
        + android.content.Context robotControllerContext)
      @@ -563,6 +612,15 @@

      close

      public void close()
    + + + +
      +
    • +

      closeHardwareMap

      +
      protected static void closeHardwareMap(HardwareMap hardwareMap)
      +
    • +
    @@ -597,6 +655,26 @@

    getExtantLynxDeviceImpls

    public java.util.List<LynxUsbDeviceImpl> getExtantLynxDeviceImpls()
    + + + +
      +
    • +

      getHardwareDevice

      +
      public <T> T getHardwareDevice(java.lang.Class<? extends T> classOrInterface,
      +                               SerialNumber serialNumber,
      +                               <any> usbScanManagerSupplier)
      +
      Returns the device whose serial number is the one indicated, from the hardware map if possible + but instantiating / opening it if necessary. null is returned if the object cannot be + accessed.
      +
      +
      Parameters:
      +
      classOrInterface - the interface to retrieve on the returned object
      +
      serialNumber - the serial number of the object to retrieve
      +
      usbScanManagerSupplier - how to get a USBScanManager if it ends up we need one
      +
      +
    • +
    @@ -657,31 +735,31 @@

    sendTelemetry

    java.lang.String msg) - +
    • closeMotorControllers

      -
      protected void closeMotorControllers()
      +
      protected static void closeMotorControllers(HardwareMap hardwareMap)
    - +
    • closeServoControllers

      -
      protected void closeServoControllers()
      +
      protected static void closeServoControllers(HardwareMap hardwareMap)
    - +
    • closeAutoCloseOnTeardown

      -
      protected void closeAutoCloseOnTeardown()
      +
      protected static void closeAutoCloseOnTeardown(HardwareMap hardwareMap)
    diff --git a/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopIdle.html b/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopIdle.html index 1c36a7187fd..d782b55c7ca 100644 --- a/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopIdle.html +++ b/doc/javadoc/com/qualcomm/ftccommon/FtcEventLoopIdle.html @@ -189,10 +189,10 @@

    Constructor Summary

    -
    All Methods Instance Methods Concrete Methods All Methods Static Methods Instance Methods Concrete Methods 
    Modifier and Type Method and Description close() 
    protected voidcloseAutoCloseOnTeardown() protected static voidcloseAutoCloseOnTeardown(HardwareMap hardwareMap) 
    protected void closeBatteryMonitoring() 
    protected voidcloseMotorControllers() protected static voidcloseHardwareMap(HardwareMap hardwareMap) 
    protected voidcloseServoControllers() protected static voidcloseMotorControllers(HardwareMap hardwareMap) 
    protected static voidcloseServoControllers(HardwareMap hardwareMap) 
    void displayGamePadInfo(java.lang.String activeOpModeName) 
    EventLoopManager getEventLoopManager() 
    java.util.List<LynxUsbDeviceImpl> getExtantLynxDeviceImpls() 
    Gamepad[] getGamepads() 
    <T> TgetHardwareDevice(java.lang.Class<? extends T> classOrInterface, + SerialNumber serialNumber, + <any> usbScanManagerSupplier) +
    Returns the device whose serial number is the one indicated, from the hardware map if possible + but instantiating / opening it if necessary.
    +
    HardwareMap getHardwareMap() 
    java.lang.String getOpMode(java.lang.String extra) 
    void init(EventLoopManager eventLoopManager) 
    void refreshUserTelemetry(TelemetryMessage telemetry, double requestedInterval) @@ -296,22 +321,22 @@

    Method Summary

    interval has passed since the last transmission.
    void restartRobot() 
    void sendBatteryInfo()
    Send robot phone power % and robot battery voltage level to Driver station
    void sendTelemetry(java.lang.String tag, java.lang.String msg) 
    void updateBatteryStatus(BatteryChecker.BatteryStatus status) 
    Constructor and Description
    FtcEventLoopIdle(HardwareFactory hardwareFactory, +FtcEventLoopIdle(HardwareFactory hardwareFactory, OpModeRegister userOpmodeRegister, UpdateUI.Callback callback, - Activity activityContext, + android.app.Activity activityContext, ProgrammingModeController programmingModeController) 
    @@ -243,7 +243,7 @@

    Method Summary

    void -
    onUsbDeviceAttached(UsbDevice usbDevice) +onUsbDeviceAttached(android.hardware.usb.UsbDevice usbDevice)
    Notifies the event loop that a UsbDevice has just been attached to the system.
    @@ -285,7 +285,7 @@

    Method Summary

    Methods inherited from class com.qualcomm.ftccommon.FtcEventLoopBase

    -checkForChangedOpModes, enterFirmwareUpdateMode, getLynxUsbDeviceForFirmwareUpdate, getUSBAccessibleLynxDevices, handleCommandActivateConfiguration, handleCommandClearRememberedGroups, handleCommandDeleteConfiguration, handleCommandDisconnectWifiDirect, handleCommandDismissAllDialogs, handleCommandDismissDialog, handleCommandDismissProgress, handleCommandGetCandidateLynxFirmwareImages, handleCommandGetUSBAccessibleLynxModules, handleCommandLynxChangeModuleAddresses, handleCommandLynxFirmwareUpdate, handleCommandRequestConfigurations, handleCommandRequestConfigurationTemplates, handleCommandRequestInspectionReport, handleCommandRequestParticularConfiguration, handleCommandRequestRememberedGroups, handleCommandRestartRobot, handleCommandSaveConfiguration, handleCommandShowDialog, handleCommandShowProgress, handleCommandShowToast, handleCommandStartDriverStationProgramAndManage, handleCommandStartProgrammingMode, handleCommandStopProgrammingMode, processCommand, sendUIState, startUsbScanMangerIfNecessary, updateLynxFirmware +checkForChangedOpModes, enterFirmwareUpdateMode, getLynxUsbDeviceForFirmwareUpdate, getUSBAccessibleLynxDevices, handleCommandActivateConfiguration, handleCommandClearRememberedGroups, handleCommandDeleteConfiguration, handleCommandDisconnectWifiDirect, handleCommandDismissAllDialogs, handleCommandDismissDialog, handleCommandDismissProgress, handleCommandGetCandidateLynxFirmwareImages, handleCommandGetUSBAccessibleLynxModules, handleCommandLynxChangeModuleAddresses, handleCommandLynxFirmwareUpdate, handleCommandRequestAboutInfo, handleCommandRequestConfigurations, handleCommandRequestConfigurationTemplates, handleCommandRequestInspectionReport, handleCommandRequestParticularConfiguration, handleCommandRequestRememberedGroups, handleCommandRestartRobot, handleCommandSaveConfiguration, handleCommandShowDialog, handleCommandShowProgress, handleCommandShowToast, handleCommandStartDriverStationProgramAndManage, handleCommandStartProgrammingMode, handleCommandStopProgrammingMode, handleCommandVisuallyConfirmWifiReset, handleCommandVisuallyIdentify, processCommand, sendUIState, startUsbScanMangerIfNecessary, talkToParentLynxModule, updateFirmwareOnce, updateLynxFirmware - +
    • onUsbDeviceAttached

      -
      public void onUsbDeviceAttached(UsbDevice usbDevice)
      -
      Description copied from interface: EventLoop
      +
      public void onUsbDeviceAttached(android.hardware.usb.UsbDevice usbDevice)
      +
      Description copied from interface: EventLoop
      Notifies the event loop that a UsbDevice has just been attached to the system. User interface activities that receive UsbManager.ACTION_USB_DEVICE_ATTACHED notifications should retrieve the UsbDevice using intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) then pass that along @@ -503,7 +503,7 @@

      processedRecentlyAttachedUsbDevices

      java.lang.InterruptedException
      See Also:
      EventLoop.handleUsbModuleDetach(RobotUsbModule), -EventLoop.onUsbDeviceAttached(UsbDevice)
      +EventLoop.onUsbDeviceAttached(UsbDevice)
    diff --git a/doc/javadoc/com/qualcomm/ftccommon/FtcLynxFirmwareUpdateActivity.FwResponseStatus.html b/doc/javadoc/com/qualcomm/ftccommon/FtcLynxFirmwareUpdateActivity.FwResponseStatus.html new file mode 100644 index 00000000000..3a3f613aa10 --- /dev/null +++ b/doc/javadoc/com/qualcomm/ftccommon/FtcLynxFirmwareUpdateActivity.FwResponseStatus.html @@ -0,0 +1,354 @@ + + + + + +FtcLynxFirmwareUpdateActivity.FwResponseStatus + + + + + + + + + + + +
    +
    com.qualcomm.ftccommon
    +

    Enum FtcLynxFirmwareUpdateActivity.FwResponseStatus

    +
    +
    + +
    + +
    +
    + +
    +
    +
      +
    • + + + +
        +
      • + + +

        Method Detail

        + + + +
          +
        • +

          values

          +
          public static FtcLynxFirmwareUpdateActivity.FwResponseStatus[] values()
          +
          Returns an array containing the constants of this enum type, in +the order they are declared. This method may be used to iterate +over the constants as follows: +
          +for (FtcLynxFirmwareUpdateActivity.FwResponseStatus c : FtcLynxFirmwareUpdateActivity.FwResponseStatus.values())
          +    System.out.println(c);
          +
          +
          +
          Returns:
          +
          an array containing the constants of this enum type, in the order they are declared
          +
          +
        • +
        + + + +
          +
        • +

          valueOf

          +
          public static FtcLynxFirmwareUpdateActivity.FwResponseStatus valueOf(java.lang.String name)
          +
          Returns the enum constant of this type with the specified name. +The string must match exactly an identifier used to declare an +enum constant in this type. (Extraneous whitespace characters are +not permitted.)
          +
          +
          Parameters:
          +
          name - the name of the enum constant to be returned.
          +
          Returns:
          +
          the enum constant with the specified name
          +
          Throws:
          +
          java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
          +
          java.lang.NullPointerException - if the argument is null
          +
          +
        • +
        +
      • +
      +
    • +
    +
    +
    + + + + + + + diff --git a/doc/javadoc/com/qualcomm/ftccommon/FtcLynxFirmwareUpdateActivity.ReceiveLoopCallback.html b/doc/javadoc/com/qualcomm/ftccommon/FtcLynxFirmwareUpdateActivity.ReceiveLoopCallback.html index 46f8873a485..303015c3d8d 100644 --- a/doc/javadoc/com/qualcomm/ftccommon/FtcLynxFirmwareUpdateActivity.ReceiveLoopCallback.html +++ b/doc/javadoc/com/qualcomm/ftccommon/FtcLynxFirmwareUpdateActivity.ReceiveLoopCallback.html @@ -47,7 +47,7 @@
    + + + + + + + +
      +
    • +

      cameraName

      +
      public CameraName cameraName
      +
      If camera is non-null, this value is ignored. + + Otherwise, if this value is neither null nor the 'unknown' camera name, the it indicates + the name of the camera to use with Vuforia. It will be opened as needed. + + Otherwise, if this value is the 'unknown' camera name, then this value is ignored and + cameraDirection is used to indicate the camera. + + Otherwise, this value is null, and an error has occurred.
      +
      +
      See Also:
      +
      camera, +cameraDirection
      +
      +
    • +
    @@ -276,10 +380,13 @@

    vuforiaLicenseKey

  • cameraDirection

    public VuforiaLocalizer.CameraDirection cameraDirection
    -
    Indicates the camera which Vuforia should use.
    +
    If camera is null and cameraName is the 'unknown' camera name, then + this value is used to indicate the camera to use with Vuforia. Note that this value + can only indicate the use of built-in cameras found on a phone.
    See Also:
    -
    VuforiaLocalizer.CameraDirection
    +
    camera, +cameraName
  • @@ -341,7 +448,7 @@

    cameraMonitorViewIdParent

    • cameraMonitorViewParent

      -
      public ViewGroup cameraMonitorViewParent
      +
      public android.view.ViewGroup cameraMonitorViewParent
      The view that will be used as the parent for a live monitor which provides feedback as to what the the camera is seeing. If both cameraMonitorViewIdParent and cameraMonitorViewParent are specified, cameraMonitorViewParent is used @@ -375,14 +482,91 @@

      fillCameraMonitorViewParent

      -
        +
        • activity

          -
          public Activity activity
          +
          public android.app.Activity activity
          The activity in which the localizer is to run. May be null, in which case the contextually current activity will be used.
        + + + +
          +
        • +

          webcamCalibrationResources

          +
          public int[] webcamCalibrationResources
          +
          The resources (if any, may be empty or null) used to provide additional camera calibration data for + webcams used with Vuforia. Using calibrated camera helps increase the accuracy of + Vuforia image target tracking. Calibration for several cameras is built into the FTC SDK; + the optional resources here provides a means for teams to provide calibrations beyond this + built-in set. + + The format required of the XML resource is indicated in the teamwebcamcalibrations + resource provided.
          +
          +
          See Also:
          +
          webcamCalibrationFiles
          +
          +
        • +
        + + + +
          +
        • +

          webcamCalibrationFiles

          +
          public java.io.File[] webcamCalibrationFiles
          +
          Camera calibrations resident in files instead of resources.
          +
          +
          See Also:
          +
          webcamCalibrationResources
          +
          +
        • +
        + + + +
          +
        • +

          maxWebcamAspectRatio

          +
          public double maxWebcamAspectRatio
          +
          Controls the aspect ratios used with webcams. Webcams whose aspect ratio (defined as + width / height) is larger than this value will not be used unless no other viable options exist. + + Example values of some utility include 1920.0 / 1080.0, 640.0 / 480.0, and the like.
          +
          +
          See Also:
          +
          minWebcamAspectRatio
          +
          +
        • +
        + + + +
          +
        • +

          minWebcamAspectRatio

          +
          public double minWebcamAspectRatio
          +
          Controls the aspect ratios used with webcams. Webcams whose aspect ratio (defined as + width / height) is smaller than this value will not be used unless no other viable options exist.
          +
          +
          See Also:
          +
          maxWebcamAspectRatio
          +
          +
        • +
        + + + +
          +
        • +

          secondsUsbPermissionTimeout

          +
          public int secondsUsbPermissionTimeout
          +
          How long to wait for USB permissions when connecting to a webcam.
          +
        • +
      @@ -411,6 +595,32 @@

      Parameters

    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        addWebcamCalibrationFile

        +
        public void addWebcamCalibrationFile(java.lang.String name)
        +
      • +
      + + + +
        +
      • +

        addWebcamCalibrationFile

        +
        public void addWebcamCalibrationFile(java.io.File file)
        +
      • +
      +
    • +
    @@ -464,13 +674,13 @@

    Parameters

  • Nested | 
  • Field | 
  • Constr | 
  • -
  • Method
  • +
  • Method
  • diff --git a/doc/javadoc/org/firstinspires/ftc/robotcore/external/navigation/VuforiaLocalizer.html b/doc/javadoc/org/firstinspires/ftc/robotcore/external/navigation/VuforiaLocalizer.html index eaf090f3c6b..3a960603ac2 100644 --- a/doc/javadoc/org/firstinspires/ftc/robotcore/external/navigation/VuforiaLocalizer.html +++ b/doc/javadoc/org/firstinspires/ftc/robotcore/external/navigation/VuforiaLocalizer.html @@ -17,7 +17,7 @@ catch(err) { } //--> -var methods = {"i0":6,"i1":6,"i2":6,"i3":6,"i4":6,"i5":6}; +var methods = {"i0":6,"i1":6,"i2":6,"i3":6,"i4":6,"i5":6,"i6":6,"i7":6,"i8":6,"i9":6,"i10":6,"i11":6}; var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],4:["t3","Abstract Methods"]}; var altColor = "altColor"; var rowColor = "rowColor"; @@ -47,7 +47,7 @@
    Returns:
    the raw pose of the trackable
    See Also:
    -
    getRawPose()
    +
    getVuforiaCameraFromTarget(), +getRawUpdatedPose()
    + + + + @@ -652,27 +1051,38 @@

    isVisible

    Returns:
    whether the associated trackable is currently visible or not
    See Also:
    -
    getPose()
    +
    getVuforiaCameraFromTarget()
    - +
    • -

      getLastTrackedRawPose

      -
      public OpenGLMatrix getLastTrackedRawPose()
      +

      getLastTrackedPoseVuforiaCamera

      +
      public OpenGLMatrix getLastTrackedPoseVuforiaCamera()
      Returns the pose associated with the last known tracked location of this trackable, if any. This can be used to recall the last pose seen, even if the trackable is no longer visible.
      Returns:
      the pose associated with the last known tracked location of this trackable, if any.
      See Also:
      -
      getRawPose()
      +
      getVuforiaCameraFromTarget()
    + + + + @@ -690,28 +1100,32 @@

    getVuMarkInstanceId

    - + - @@ -750,7 +1181,7 @@

    onNotTracked