diff --git a/examples/.gitignore b/examples/.gitignore index 8ea3a652..e9b0d3c9 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,5 +1,6 @@ # dependencies (rm -rf bun.lock && bun install --no-cachenstall) node_modules +.bun # output out diff --git a/examples/.gradle/config.properties b/examples/.gradle/config.properties deleted file mode 100644 index beb657d4..00000000 --- a/examples/.gradle/config.properties +++ /dev/null @@ -1,2 +0,0 @@ -#Wed Aug 13 13:17:18 EEST 2025 -java.home=C\:\\Program Files\\Android\\Android Studio\\jbr diff --git a/examples/FtcRobotController/build.gradle b/examples/FtcRobotController/build.gradle deleted file mode 100644 index 46937939..00000000 --- a/examples/FtcRobotController/build.gradle +++ /dev/null @@ -1,25 +0,0 @@ -import java.text.SimpleDateFormat - -apply plugin: 'com.android.library' - -apply from: '../build.dependencies.gradle' -android { - - defaultConfig { - minSdkVersion 24 - //noinspection ExpiredTargetSdkVersion - targetSdkVersion 28 - compileSdk = 35 - buildConfigField "String", "APP_BUILD_TIME", '"' + (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.ROOT).format(new Date())) + '"' - } - - buildFeatures { - buildConfig = true - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - namespace = 'com.qualcomm.ftcrobotcontroller' -} diff --git a/examples/FtcRobotController/src/main/AndroidManifest.xml b/examples/FtcRobotController/src/main/AndroidManifest.xml deleted file mode 100644 index 24038bfa..00000000 --- a/examples/FtcRobotController/src/main/AndroidManifest.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOmniOpMode_Linear.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOmniOpMode_Linear.java deleted file mode 100644 index 1d14dfb7..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOmniOpMode_Linear.java +++ /dev/null @@ -1,167 +0,0 @@ -/* Copyright (c) 2021 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.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * This file contains an example of a Linear "OpMode". - * An OpMode is a 'program' that runs in either the autonomous or the teleop period of an FTC match. - * The names of OpModes appear on the menu of the FTC Driver Station. - * When a selection is made from the menu, the corresponding OpMode is executed. - * - * This particular OpMode illustrates driving a 4-motor Omni-Directional (or Holonomic) robot. - * This code will work with either a Mecanum-Drive or an X-Drive train. - * Both of these drives are illustrated at https://gm0.org/en/latest/docs/robot-design/drivetrains/holonomic.html - * Note that a Mecanum drive must display an X roller-pattern when viewed from above. - * - * Also note that it is critical to set the correct rotation direction for each motor. See details below. - * - * Holonomic drives provide the ability for the robot to move in three axes (directions) simultaneously. - * Each motion axis is controlled by one Joystick axis. - * - * 1) Axial: Driving forward and backward Left-joystick Forward/Backward - * 2) Lateral: Strafing right and left Left-joystick Right and Left - * 3) Yaw: Rotating Clockwise and counter clockwise Right-joystick Right and Left - * - * This code is written assuming that the right-side motors need to be reversed for the robot to drive forward. - * When you first test your robot, if it moves backward when you push the left stick forward, then you must flip - * the direction of all 4 motors (see code below). - * - * 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="Basic: Omni Linear OpMode", group="Linear OpMode") -@Disabled -public class BasicOmniOpMode_Linear extends LinearOpMode { - - // Declare OpMode members for each of the 4 motors. - private ElapsedTime runtime = new ElapsedTime(); - private DcMotor leftFrontDrive = null; - private DcMotor leftBackDrive = null; - private DcMotor rightFrontDrive = null; - private DcMotor rightBackDrive = null; - - @Override - public void runOpMode() { - - // Initialize the hardware variables. Note that the strings used here must correspond - // to the names assigned during the robot configuration step on the DS or RC devices. - leftFrontDrive = hardwareMap.get(DcMotor.class, "left_front_drive"); - leftBackDrive = hardwareMap.get(DcMotor.class, "left_back_drive"); - rightFrontDrive = hardwareMap.get(DcMotor.class, "right_front_drive"); - rightBackDrive = hardwareMap.get(DcMotor.class, "right_back_drive"); - - // ######################################################################################## - // !!! IMPORTANT Drive Information. Test your motor directions. !!!!! - // ######################################################################################## - // Most robots need the motors on one side to be reversed to drive forward. - // The motor reversals shown here are for a "direct drive" robot (the wheels turn the same direction as the motor shaft) - // If your robot has additional gear reductions or uses a right-angled drive, it's important to ensure - // that your motors are turning in the correct direction. So, start out with the reversals here, BUT - // when you first test your robot, push the left joystick forward and observe the direction the wheels turn. - // Reverse the direction (flip FORWARD <-> REVERSE ) of any wheel that runs backward - // Keep testing until ALL the wheels move the robot forward when you push the left joystick forward. - leftFrontDrive.setDirection(DcMotor.Direction.REVERSE); - leftBackDrive.setDirection(DcMotor.Direction.REVERSE); - rightFrontDrive.setDirection(DcMotor.Direction.FORWARD); - rightBackDrive.setDirection(DcMotor.Direction.FORWARD); - - // Wait for the game to start (driver presses START) - telemetry.addData("Status", "Initialized"); - telemetry.update(); - - waitForStart(); - runtime.reset(); - - // run until the end of the match (driver presses STOP) - while (opModeIsActive()) { - double max; - - // POV Mode uses left joystick to go forward & strafe, and right joystick to rotate. - double axial = -gamepad1.left_stick_y; // Note: pushing stick forward gives negative value - double lateral = gamepad1.left_stick_x; - double yaw = gamepad1.right_stick_x; - - // Combine the joystick requests for each axis-motion to determine each wheel's power. - // Set up a variable for each drive wheel to save the power level for telemetry. - double leftFrontPower = axial + lateral + yaw; - double rightFrontPower = axial - lateral - yaw; - double leftBackPower = axial - lateral + yaw; - double rightBackPower = axial + lateral - yaw; - - // Normalize the values so no wheel power exceeds 100% - // This ensures that the robot maintains the desired motion. - max = Math.max(Math.abs(leftFrontPower), Math.abs(rightFrontPower)); - max = Math.max(max, Math.abs(leftBackPower)); - max = Math.max(max, Math.abs(rightBackPower)); - - if (max > 1.0) { - leftFrontPower /= max; - rightFrontPower /= max; - leftBackPower /= max; - rightBackPower /= max; - } - - // This is test code: - // - // Uncomment the following code to test your motor directions. - // Each button should make the corresponding motor run FORWARD. - // 1) First get all the motors to take to correct positions on the robot - // by adjusting your Robot Configuration if necessary. - // 2) Then make sure they run in the correct direction by modifying the - // the setDirection() calls above. - // Once the correct motors move in the correct direction re-comment this code. - - /* - leftFrontPower = gamepad1.x ? 1.0 : 0.0; // X gamepad - leftBackPower = gamepad1.a ? 1.0 : 0.0; // A gamepad - rightFrontPower = gamepad1.y ? 1.0 : 0.0; // Y gamepad - rightBackPower = gamepad1.b ? 1.0 : 0.0; // B gamepad - */ - - // Send calculated power to wheels - leftFrontDrive.setPower(leftFrontPower); - rightFrontDrive.setPower(rightFrontPower); - leftBackDrive.setPower(leftBackPower); - rightBackDrive.setPower(rightBackPower); - - // Show the elapsed game time and wheel power. - telemetry.addData("Status", "Run Time: " + runtime.toString()); - telemetry.addData("Front left/Right", "%4.2f, %4.2f", leftFrontPower, rightFrontPower); - telemetry.addData("Back left/Right", "%4.2f, %4.2f", leftBackPower, rightBackPower); - telemetry.update(); - } - }} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Iterative.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Iterative.java deleted file mode 100644 index 6504e58a..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Iterative.java +++ /dev/null @@ -1,140 +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.OpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; -import com.qualcomm.robotcore.util.Range; - -/* - * This file contains an example of an iterative (Non-Linear) "OpMode". - * An OpMode is a 'program' that runs in either the autonomous or the teleop period of an FTC match. - * The names of OpModes appear on the menu of the FTC Driver Station. - * When a selection is made from the menu, the corresponding OpMode - * class is instantiated on the Robot Controller and executed. - * - * This particular OpMode just executes a basic Tank Drive Teleop for a two wheeled robot - * It includes all the skeletal structure that all iterative OpModes contain. - * - * 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="Basic: Iterative OpMode", group="Iterative OpMode") -@Disabled -public class BasicOpMode_Iterative extends OpMode -{ - // Declare OpMode members. - private ElapsedTime runtime = new ElapsedTime(); - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - - /* - * Code to run ONCE when the driver hits INIT - */ - @Override - public void init() { - telemetry.addData("Status", "Initialized"); - - // 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(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left stick forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // Tell the driver that initialization is complete. - telemetry.addData("Status", "Initialized"); - } - - /* - * Code to run REPEATEDLY after the driver hits INIT, but before they hit START - */ - @Override - public void init_loop() { - } - - /* - * Code to run ONCE when the driver hits START - */ - @Override - public void start() { - runtime.reset(); - } - - /* - * Code to run REPEATEDLY after the driver hits START but before they hit STOP - */ - @Override - public void loop() { - // 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); - } - - /* - * Code to run ONCE after the driver hits STOP - */ - @Override - public void stop() { - } - -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Linear.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Linear.java deleted file mode 100644 index ab0bb254..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Linear.java +++ /dev/null @@ -1,115 +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.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; -import com.qualcomm.robotcore.util.Range; - - -/* - * This file contains an minimal example of a Linear "OpMode". An OpMode is a 'program' that runs in either - * the autonomous or the teleop period of an FTC match. The names of OpModes appear on the menu - * of the FTC Driver Station. When a selection is made from the menu, the corresponding OpMode - * class is instantiated on the Robot Controller and executed. - * - * This particular OpMode just executes a basic Tank Drive Teleop for a two wheeled robot - * It includes all the skeletal structure that all linear OpModes contain. - * - * 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="Basic: Linear OpMode", group="Linear OpMode") -@Disabled -public class BasicOpMode_Linear extends LinearOpMode { - - // Declare OpMode members. - private ElapsedTime runtime = new ElapsedTime(); - private DcMotor leftDrive = null; - private DcMotor 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(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left stick forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // Wait for the game to start (driver presses START) - 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/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTag.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTag.java deleted file mode 100644 index 8ec77dd8..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTag.java +++ /dev/null @@ -1,217 +0,0 @@ -/* Copyright (c) 2023 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.util.Size; -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.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; - -/* - * This OpMode illustrates the basics of AprilTag recognition and pose estimation, - * including Java Builder structures for specifying Vision parameters. - * - * For an introduction to AprilTags, see the FTC-DOCS link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * In this sample, any visible tag ID will be detected and displayed, but only tags that are included in the default - * "TagLibrary" will have their position and orientation information displayed. This default TagLibrary contains - * the current Season's AprilTags and a small set of "test Tags" in the high number range. - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the tag, relative to the camera. - * This information is provided in the "ftcPose" member of the returned "detection", and is explained in the ftc-docs page linked below. - * https://ftc-docs.firstinspires.org/apriltag-detection-values - * - * To experiment with using AprilTags to navigate, try out these two driving samples: - * RobotAutoDriveToAprilTagOmni and RobotAutoDriveToAprilTagTank - * - * There are many "default" VisionPortal and AprilTag configuration parameters that may be overridden if desired. - * These default parameters are shown as comments in the code below. - * - * 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 = "Concept: AprilTag", group = "Concept") -@Disabled -public class ConceptAprilTag extends LinearOpMode { - - private static final boolean USE_WEBCAM = true; // true for webcam, false for phone camera - - /** - * The variable to store our instance of the AprilTag processor. - */ - private AprilTagProcessor aprilTag; - - /** - * The variable to store our instance of the vision portal. - */ - private VisionPortal visionPortal; - - @Override - public void runOpMode() { - - initAprilTag(); - - // Wait for the DS start button to be touched. - telemetry.addData("DS preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - if (opModeIsActive()) { - while (opModeIsActive()) { - - telemetryAprilTag(); - - // Push telemetry to the Driver Station. - telemetry.update(); - - // Save CPU resources; can resume streaming when needed. - if (gamepad1.dpad_down) { - visionPortal.stopStreaming(); - } else if (gamepad1.dpad_up) { - visionPortal.resumeStreaming(); - } - - // Share the CPU. - sleep(20); - } - } - - // Save more CPU resources when camera is no longer needed. - visionPortal.close(); - - } // end method runOpMode() - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - - // Create the AprilTag processor. - aprilTag = new AprilTagProcessor.Builder() - - // The following default settings are available to un-comment and edit as needed. - //.setDrawAxes(false) - //.setDrawCubeProjection(false) - //.setDrawTagOutline(true) - //.setTagFamily(AprilTagProcessor.TagFamily.TAG_36h11) - //.setTagLibrary(AprilTagGameDatabase.getCenterStageTagLibrary()) - //.setOutputUnits(DistanceUnit.INCH, AngleUnit.DEGREES) - - // == CAMERA CALIBRATION == - // If you do not manually specify calibration parameters, the SDK will attempt - // to load a predefined calibration for your camera. - //.setLensIntrinsics(578.272, 578.272, 402.145, 221.506) - // ... these parameters are fx, fy, cx, cy. - - .build(); - - // Adjust Image Decimation to trade-off detection-range for detection-rate. - // eg: Some typical detection data using a Logitech C920 WebCam - // Decimation = 1 .. Detect 2" Tag from 10 feet away at 10 Frames per second - // Decimation = 2 .. Detect 2" Tag from 6 feet away at 22 Frames per second - // Decimation = 3 .. Detect 2" Tag from 4 feet away at 30 Frames Per Second (default) - // Decimation = 3 .. Detect 5" Tag from 10 feet away at 30 Frames Per Second (default) - // Note: Decimation can be changed on-the-fly to adapt during a match. - //aprilTag.setDecimation(3); - - // Create the vision portal by using a builder. - VisionPortal.Builder builder = new VisionPortal.Builder(); - - // Set the camera (webcam vs. built-in RC phone camera). - if (USE_WEBCAM) { - builder.setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")); - } else { - builder.setCamera(BuiltinCameraDirection.BACK); - } - - // Choose a camera resolution. Not all cameras support all resolutions. - //builder.setCameraResolution(new Size(640, 480)); - - // Enable the RC preview (LiveView). Set "false" to omit camera monitoring. - //builder.enableLiveView(true); - - // Set the stream format; MJPEG uses less bandwidth than default YUY2. - //builder.setStreamFormat(VisionPortal.StreamFormat.YUY2); - - // Choose whether or not LiveView stops if no processors are enabled. - // If set "true", monitor shows solid orange screen if no processors enabled. - // If set "false", monitor shows camera view without annotations. - //builder.setAutoStopLiveView(false); - - // Set and enable the processor. - builder.addProcessor(aprilTag); - - // Build the Vision Portal, using the above settings. - visionPortal = builder.build(); - - // Disable or re-enable the aprilTag processor at any time. - //visionPortal.setProcessorEnabled(aprilTag, true); - - } // end method initAprilTag() - - - /** - * Add telemetry about AprilTag detections. - */ - private void telemetryAprilTag() { - - List currentDetections = aprilTag.getDetections(); - telemetry.addData("# AprilTags Detected", currentDetections.size()); - - // Step through the list of detections and display info for each one. - for (AprilTagDetection detection : currentDetections) { - if (detection.metadata != null) { - telemetry.addLine(String.format("\n==== (ID %d) %s", detection.id, detection.metadata.name)); - telemetry.addLine(String.format("XYZ %6.1f %6.1f %6.1f (inch)", detection.ftcPose.x, detection.ftcPose.y, detection.ftcPose.z)); - telemetry.addLine(String.format("PRY %6.1f %6.1f %6.1f (deg)", detection.ftcPose.pitch, detection.ftcPose.roll, detection.ftcPose.yaw)); - telemetry.addLine(String.format("RBE %6.1f %6.1f %6.1f (inch, deg, deg)", detection.ftcPose.range, detection.ftcPose.bearing, detection.ftcPose.elevation)); - } else { - telemetry.addLine(String.format("\n==== (ID %d) Unknown", detection.id)); - telemetry.addLine(String.format("Center %6.0f %6.0f (pixels)", detection.center.x, detection.center.y)); - } - } // end for() loop - - // Add "key" information to telemetry - telemetry.addLine("\nkey:\nXYZ = X (Right), Y (Forward), Z (Up) dist."); - telemetry.addLine("PRY = Pitch, Roll & Yaw (XYZ Rotation)"); - telemetry.addLine("RBE = Range, Bearing & Elevation"); - - } // end method telemetryAprilTag() - -} // end class diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagEasy.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagEasy.java deleted file mode 100644 index 12dcf6e9..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagEasy.java +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright (c) 2023 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 org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; - -/* - * This OpMode illustrates the basics of AprilTag recognition and pose estimation, using - * the easy way. - * - * For an introduction to AprilTags, see the FTC-DOCS link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * In this sample, any visible tag ID will be detected and displayed, but only tags that are included in the default - * "TagLibrary" will have their position and orientation information displayed. This default TagLibrary contains - * the current Season's AprilTags and a small set of "test Tags" in the high number range. - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the tag, relative to the camera. - * This information is provided in the "ftcPose" member of the returned "detection", and is explained in the ftc-docs page linked below. - * https://ftc-docs.firstinspires.org/apriltag-detection-values - * - * To experiment with using AprilTags to navigate, try out these two driving samples: - * RobotAutoDriveToAprilTagOmni and RobotAutoDriveToAprilTagTank - * - * 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 = "Concept: AprilTag Easy", group = "Concept") -@Disabled -public class ConceptAprilTagEasy extends LinearOpMode { - - private static final boolean USE_WEBCAM = true; // true for webcam, false for phone camera - - /** - * The variable to store our instance of the AprilTag processor. - */ - private AprilTagProcessor aprilTag; - - /** - * The variable to store our instance of the vision portal. - */ - private VisionPortal visionPortal; - - @Override - public void runOpMode() { - - initAprilTag(); - - // Wait for the DS start button to be touched. - telemetry.addData("DS preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - if (opModeIsActive()) { - while (opModeIsActive()) { - - telemetryAprilTag(); - - // Push telemetry to the Driver Station. - telemetry.update(); - - // Save CPU resources; can resume streaming when needed. - if (gamepad1.dpad_down) { - visionPortal.stopStreaming(); - } else if (gamepad1.dpad_up) { - visionPortal.resumeStreaming(); - } - - // Share the CPU. - sleep(20); - } - } - - // Save more CPU resources when camera is no longer needed. - visionPortal.close(); - - } // end method runOpMode() - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - - // Create the AprilTag processor the easy way. - aprilTag = AprilTagProcessor.easyCreateWithDefaults(); - - // Create the vision portal the easy way. - if (USE_WEBCAM) { - visionPortal = VisionPortal.easyCreateWithDefaults( - hardwareMap.get(WebcamName.class, "Webcam 1"), aprilTag); - } else { - visionPortal = VisionPortal.easyCreateWithDefaults( - BuiltinCameraDirection.BACK, aprilTag); - } - - } // end method initAprilTag() - - /** - * Add telemetry about AprilTag detections. - */ - private void telemetryAprilTag() { - - List currentDetections = aprilTag.getDetections(); - telemetry.addData("# AprilTags Detected", currentDetections.size()); - - // Step through the list of detections and display info for each one. - for (AprilTagDetection detection : currentDetections) { - if (detection.metadata != null) { - telemetry.addLine(String.format("\n==== (ID %d) %s", detection.id, detection.metadata.name)); - telemetry.addLine(String.format("XYZ %6.1f %6.1f %6.1f (inch)", detection.ftcPose.x, detection.ftcPose.y, detection.ftcPose.z)); - telemetry.addLine(String.format("PRY %6.1f %6.1f %6.1f (deg)", detection.ftcPose.pitch, detection.ftcPose.roll, detection.ftcPose.yaw)); - telemetry.addLine(String.format("RBE %6.1f %6.1f %6.1f (inch, deg, deg)", detection.ftcPose.range, detection.ftcPose.bearing, detection.ftcPose.elevation)); - } else { - telemetry.addLine(String.format("\n==== (ID %d) Unknown", detection.id)); - telemetry.addLine(String.format("Center %6.0f %6.0f (pixels)", detection.center.x, detection.center.y)); - } - } // end for() loop - - // Add "key" information to telemetry - telemetry.addLine("\nkey:\nXYZ = X (Right), Y (Forward), Z (Up) dist."); - telemetry.addLine("PRY = Pitch, Roll & Yaw (XYZ Rotation)"); - telemetry.addLine("RBE = Range, Bearing & Elevation"); - - } // end method telemetryAprilTag() - -} // end class diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagLocalization.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagLocalization.java deleted file mode 100644 index d90261ef..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagLocalization.java +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (c) 2024 Dryw Wade. 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 org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; -import org.firstinspires.ftc.robotcore.external.navigation.Position; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; - -/* - * This OpMode illustrates the basics of AprilTag based localization. - * - * For an introduction to AprilTags, see the FTC-DOCS link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * In this sample, any visible tag ID will be detected and displayed, but only tags that are included in the default - * "TagLibrary" will be used to compute the robot's location and orientation. This default TagLibrary contains - * the current Season's AprilTags and a small set of "test Tags" in the high number range. - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the robot, relative to the field origin. - * This information is provided in the "robotPose" member of the returned "detection". - * - * To learn about the Field Coordinate System that is defined for FTC (and used by this OpMode), see the FTC-DOCS link below: - * https://ftc-docs.firstinspires.org/en/latest/game_specific_resources/field_coordinate_system/field-coordinate-system.html - * - * 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 = "Concept: AprilTag Localization", group = "Concept") -@Disabled -public class ConceptAprilTagLocalization extends LinearOpMode { - - private static final boolean USE_WEBCAM = true; // true for webcam, false for phone camera - - /** - * Variables to store the position and orientation of the camera on the robot. Setting these - * values requires a definition of the axes of the camera and robot: - * - * Camera axes: - * Origin location: Center of the lens - * Axes orientation: +x right, +y down, +z forward (from camera's perspective) - * - * Robot axes (this is typical, but you can define this however you want): - * Origin location: Center of the robot at field height - * Axes orientation: +x right, +y forward, +z upward - * - * Position: - * If all values are zero (no translation), that implies the camera is at the center of the - * robot. Suppose your camera is positioned 5 inches to the left, 7 inches forward, and 12 - * inches above the ground - you would need to set the position to (-5, 7, 12). - * - * Orientation: - * If all values are zero (no rotation), that implies the camera is pointing straight up. In - * most cases, you'll need to set the pitch to -90 degrees (rotation about the x-axis), meaning - * the camera is horizontal. Use a yaw of 0 if the camera is pointing forwards, +90 degrees if - * it's pointing straight left, -90 degrees for straight right, etc. You can also set the roll - * to +/-90 degrees if it's vertical, or 180 degrees if it's upside-down. - */ - private Position cameraPosition = new Position(DistanceUnit.INCH, - 0, 0, 0, 0); - private YawPitchRollAngles cameraOrientation = new YawPitchRollAngles(AngleUnit.DEGREES, - 0, -90, 0, 0); - - /** - * The variable to store our instance of the AprilTag processor. - */ - private AprilTagProcessor aprilTag; - - /** - * The variable to store our instance of the vision portal. - */ - private VisionPortal visionPortal; - - @Override - public void runOpMode() { - - initAprilTag(); - - // Wait for the DS start button to be touched. - telemetry.addData("DS preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) { - - telemetryAprilTag(); - - // Push telemetry to the Driver Station. - telemetry.update(); - - // Save CPU resources; can resume streaming when needed. - if (gamepad1.dpad_down) { - visionPortal.stopStreaming(); - } else if (gamepad1.dpad_up) { - visionPortal.resumeStreaming(); - } - - // Share the CPU. - sleep(20); - } - - // Save more CPU resources when camera is no longer needed. - visionPortal.close(); - - } // end method runOpMode() - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - - // Create the AprilTag processor. - aprilTag = new AprilTagProcessor.Builder() - - // The following default settings are available to un-comment and edit as needed. - //.setDrawAxes(false) - //.setDrawCubeProjection(false) - //.setDrawTagOutline(true) - //.setTagFamily(AprilTagProcessor.TagFamily.TAG_36h11) - //.setTagLibrary(AprilTagGameDatabase.getCenterStageTagLibrary()) - //.setOutputUnits(DistanceUnit.INCH, AngleUnit.DEGREES) - .setCameraPose(cameraPosition, cameraOrientation) - - // == CAMERA CALIBRATION == - // If you do not manually specify calibration parameters, the SDK will attempt - // to load a predefined calibration for your camera. - //.setLensIntrinsics(578.272, 578.272, 402.145, 221.506) - // ... these parameters are fx, fy, cx, cy. - - .build(); - - // Adjust Image Decimation to trade-off detection-range for detection-rate. - // eg: Some typical detection data using a Logitech C920 WebCam - // Decimation = 1 .. Detect 2" Tag from 10 feet away at 10 Frames per second - // Decimation = 2 .. Detect 2" Tag from 6 feet away at 22 Frames per second - // Decimation = 3 .. Detect 2" Tag from 4 feet away at 30 Frames Per Second (default) - // Decimation = 3 .. Detect 5" Tag from 10 feet away at 30 Frames Per Second (default) - // Note: Decimation can be changed on-the-fly to adapt during a match. - //aprilTag.setDecimation(3); - - // Create the vision portal by using a builder. - VisionPortal.Builder builder = new VisionPortal.Builder(); - - // Set the camera (webcam vs. built-in RC phone camera). - if (USE_WEBCAM) { - builder.setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")); - } else { - builder.setCamera(BuiltinCameraDirection.BACK); - } - - // Choose a camera resolution. Not all cameras support all resolutions. - //builder.setCameraResolution(new Size(640, 480)); - - // Enable the RC preview (LiveView). Set "false" to omit camera monitoring. - //builder.enableLiveView(true); - - // Set the stream format; MJPEG uses less bandwidth than default YUY2. - //builder.setStreamFormat(VisionPortal.StreamFormat.YUY2); - - // Choose whether or not LiveView stops if no processors are enabled. - // If set "true", monitor shows solid orange screen if no processors enabled. - // If set "false", monitor shows camera view without annotations. - //builder.setAutoStopLiveView(false); - - // Set and enable the processor. - builder.addProcessor(aprilTag); - - // Build the Vision Portal, using the above settings. - visionPortal = builder.build(); - - // Disable or re-enable the aprilTag processor at any time. - //visionPortal.setProcessorEnabled(aprilTag, true); - - } // end method initAprilTag() - - /** - * Add telemetry about AprilTag detections. - */ - private void telemetryAprilTag() { - - List currentDetections = aprilTag.getDetections(); - telemetry.addData("# AprilTags Detected", currentDetections.size()); - - // Step through the list of detections and display info for each one. - for (AprilTagDetection detection : currentDetections) { - if (detection.metadata != null) { - telemetry.addLine(String.format("\n==== (ID %d) %s", detection.id, detection.metadata.name)); - telemetry.addLine(String.format("XYZ %6.1f %6.1f %6.1f (inch)", - detection.robotPose.getPosition().x, - detection.robotPose.getPosition().y, - detection.robotPose.getPosition().z)); - telemetry.addLine(String.format("PRY %6.1f %6.1f %6.1f (deg)", - detection.robotPose.getOrientation().getPitch(AngleUnit.DEGREES), - detection.robotPose.getOrientation().getRoll(AngleUnit.DEGREES), - detection.robotPose.getOrientation().getYaw(AngleUnit.DEGREES))); - } else { - telemetry.addLine(String.format("\n==== (ID %d) Unknown", detection.id)); - telemetry.addLine(String.format("Center %6.0f %6.0f (pixels)", detection.center.x, detection.center.y)); - } - } // end for() loop - - // Add "key" information to telemetry - telemetry.addLine("\nkey:\nXYZ = X (Right), Y (Forward), Z (Up) dist."); - telemetry.addLine("PRY = Pitch, Roll & Yaw (XYZ Rotation)"); - - } // end method telemetryAprilTag() - -} // end class diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagMultiPortal.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagMultiPortal.java deleted file mode 100644 index da5cc3ed..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagMultiPortal.java +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (c) 2024 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 org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -/** - * This OpMode demonstrates the basics of using multiple vision portals simultaneously - */ -@TeleOp(name = "Concept: AprilTagMultiPortal", group = "Concept") -@Disabled -public class ConceptAprilTagMultiPortal extends LinearOpMode -{ - VisionPortal portal1; - VisionPortal portal2; - - AprilTagProcessor aprilTagProcessor1; - AprilTagProcessor aprilTagProcessor2; - - @Override - public void runOpMode() throws InterruptedException - { - // Because we want to show two camera feeds simultaneously, we need to inform - // the SDK that we want it to split the camera monitor area into two smaller - // areas for us. It will then give us View IDs which we can pass to the individual - // vision portals to allow them to properly hook into the UI in tandem. - int[] viewIds = VisionPortal.makeMultiPortalView(2, VisionPortal.MultiPortalLayout.VERTICAL); - - // We extract the two view IDs from the array to make our lives a little easier later. - // NB: the array is 2 long because we asked for 2 portals up above. - int portal1ViewId = viewIds[0]; - int portal2ViewId = viewIds[1]; - - // If we want to run AprilTag detection on two portals simultaneously, - // we need to create two distinct instances of the AprilTag processor, - // one for each portal. If you want to see more detail about different - // options that you have when creating these processors, go check out - // the ConceptAprilTag OpMode. - aprilTagProcessor1 = AprilTagProcessor.easyCreateWithDefaults(); - aprilTagProcessor2 = AprilTagProcessor.easyCreateWithDefaults(); - - // Now we build both portals. The CRITICAL thing to notice here is the call to - // setLiveViewContainerId(), where we pass in the IDs we received earlier from - // makeMultiPortalView(). - portal1 = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .setLiveViewContainerId(portal1ViewId) - .addProcessor(aprilTagProcessor1) - .build(); - portal2 = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 2")) - .setLiveViewContainerId(portal2ViewId) - .addProcessor(aprilTagProcessor2) - .build(); - - waitForStart(); - - // Main Loop - while (opModeIsActive()) - { - // Just show some basic telemetry to demonstrate both processors are working in parallel - // on their respective cameras. If you want to see more detail about the information you - // can get back from the processor, you should look at ConceptAprilTag. - telemetry.addData("Number of tags in Camera 1", aprilTagProcessor1.getDetections().size()); - telemetry.addData("Number of tags in Camera 2", aprilTagProcessor2.getDetections().size()); - telemetry.update(); - sleep(20); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagOptimizeExposure.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagOptimizeExposure.java deleted file mode 100644 index adee952b..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagOptimizeExposure.java +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright (c) 2023 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; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.ExposureControl; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.GainControl; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -/* - * This OpMode determines the best Exposure for minimizing image motion-blur on a Webcam - * Note that it is not possible to control the exposure for a Phone Camera, so if you are using a Phone for the Robot Controller - * this OpMode/Feature only applies to an externally connected Webcam - * - * The goal is to determine the smallest (shortest) Exposure value that still provides reliable Tag Detection. - * Starting with the minimum Exposure and maximum Gain, the exposure is slowly increased until the Tag is - * detected reliably from the likely operational distance. - * - * - * The best way to run this optimization is to view the camera preview screen while changing the exposure and gains. - * - * To do this, you need to view the RobotController screen directly (not from Driver Station) - * This can be done directly from a RC phone screen (if you are using an external Webcam), but for a Control Hub you must either plug an - * HDMI monitor into the Control Hub HDMI port, or use an external viewer program like ScrCpy (https://scrcpy.org/) - * - * Use Android Studio to Copy this Class, and Paste it into the TeamCode/src/main/java/org/firstinspires/ftc/teamcode folder. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list. - */ - -@TeleOp(name="Optimize AprilTag Exposure", group = "Concept") -@Disabled -public class ConceptAprilTagOptimizeExposure extends LinearOpMode -{ - private VisionPortal visionPortal = null; // Used to manage the video source. - private AprilTagProcessor aprilTag; // Used for managing the AprilTag detection process. - private int myExposure ; - private int minExposure ; - private int maxExposure ; - private int myGain ; - private int minGain ; - private int maxGain ; - - boolean thisExpUp = false; - boolean thisExpDn = false; - boolean thisGainUp = false; - boolean thisGainDn = false; - - boolean lastExpUp = false; - boolean lastExpDn = false; - boolean lastGainUp = false; - boolean lastGainDn = false; - @Override public void runOpMode() - { - // Initialize the Apriltag Detection process - initAprilTag(); - - // Establish Min and Max Gains and Exposure. Then set a low exposure with high gain - getCameraSetting(); - myExposure = Math.min(5, minExposure); - myGain = maxGain; - setManualExposure(myExposure, myGain); - - // Wait for the match to begin. - telemetry.addData("Camera preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) - { - telemetry.addLine("Find lowest Exposure that gives reliable detection."); - telemetry.addLine("Use Left bump/trig to adjust Exposure."); - telemetry.addLine("Use Right bump/trig to adjust Gain.\n"); - - // Display how many Tags Detected - List currentDetections = aprilTag.getDetections(); - int numTags = currentDetections.size(); - if (numTags > 0 ) - telemetry.addData("Tag", "####### %d Detected ######", currentDetections.size()); - else - telemetry.addData("Tag", "----------- none - ----------"); - - telemetry.addData("Exposure","%d (%d - %d)", myExposure, minExposure, maxExposure); - telemetry.addData("Gain","%d (%d - %d)", myGain, minGain, maxGain); - telemetry.update(); - - // check to see if we need to change exposure or gain. - thisExpUp = gamepad1.left_bumper; - thisExpDn = gamepad1.left_trigger > 0.25; - thisGainUp = gamepad1.right_bumper; - thisGainDn = gamepad1.right_trigger > 0.25; - - // look for clicks to change exposure - if (thisExpUp && !lastExpUp) { - myExposure = Range.clip(myExposure + 1, minExposure, maxExposure); - setManualExposure(myExposure, myGain); - } else if (thisExpDn && !lastExpDn) { - myExposure = Range.clip(myExposure - 1, minExposure, maxExposure); - setManualExposure(myExposure, myGain); - } - - // look for clicks to change the gain - if (thisGainUp && !lastGainUp) { - myGain = Range.clip(myGain + 1, minGain, maxGain ); - setManualExposure(myExposure, myGain); - } else if (thisGainDn && !lastGainDn) { - myGain = Range.clip(myGain - 1, minGain, maxGain ); - setManualExposure(myExposure, myGain); - } - - lastExpUp = thisExpUp; - lastExpDn = thisExpDn; - lastGainUp = thisGainUp; - lastGainDn = thisGainDn; - - sleep(20); - } - } - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - // Create the AprilTag processor by using a builder. - aprilTag = new AprilTagProcessor.Builder().build(); - - // Create the WEBCAM vision portal by using a builder. - visionPortal = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .addProcessor(aprilTag) - .build(); - } - - /* - Manually set the camera gain and exposure. - Can only be called AFTER calling initAprilTag(); - Returns true if controls are set. - */ - private boolean setManualExposure(int exposureMS, int gain) { - // Ensure Vision Portal has been setup. - if (visionPortal == null) { - return false; - } - - // Wait for the camera to be open - if (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING) { - telemetry.addData("Camera", "Waiting"); - telemetry.update(); - while (!isStopRequested() && (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING)) { - sleep(20); - } - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - - // Set camera controls unless we are stopping. - if (!isStopRequested()) - { - // Set exposure. Make sure we are in Manual Mode for these values to take effect. - ExposureControl exposureControl = visionPortal.getCameraControl(ExposureControl.class); - if (exposureControl.getMode() != ExposureControl.Mode.Manual) { - exposureControl.setMode(ExposureControl.Mode.Manual); - sleep(50); - } - exposureControl.setExposure((long)exposureMS, TimeUnit.MILLISECONDS); - sleep(20); - - // Set Gain. - GainControl gainControl = visionPortal.getCameraControl(GainControl.class); - gainControl.setGain(gain); - sleep(20); - return (true); - } else { - return (false); - } - } - - /* - Read this camera's minimum and maximum Exposure and Gain settings. - Can only be called AFTER calling initAprilTag(); - */ - private void getCameraSetting() { - // Ensure Vision Portal has been setup. - if (visionPortal == null) { - return; - } - - // Wait for the camera to be open - if (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING) { - telemetry.addData("Camera", "Waiting"); - telemetry.update(); - while (!isStopRequested() && (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING)) { - sleep(20); - } - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - - // Get camera control values unless we are stopping. - if (!isStopRequested()) { - ExposureControl exposureControl = visionPortal.getCameraControl(ExposureControl.class); - minExposure = (int)exposureControl.getMinExposure(TimeUnit.MILLISECONDS) + 1; - maxExposure = (int)exposureControl.getMaxExposure(TimeUnit.MILLISECONDS); - - GainControl gainControl = visionPortal.getCameraControl(GainControl.class); - minGain = gainControl.getMinGain(); - maxGain = gainControl.getMaxGain(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagSwitchableCameras.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagSwitchableCameras.java deleted file mode 100644 index 7ee1064b..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagSwitchableCameras.java +++ /dev/null @@ -1,196 +0,0 @@ -/* Copyright (c) 2023 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 org.firstinspires.ftc.robotcore.external.ClassFactory; -import org.firstinspires.ftc.robotcore.external.hardware.camera.CameraName; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.VisionPortal.CameraState; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; - -/* - * This OpMode illustrates the basics of AprilTag recognition and pose estimation, using - * two webcams. - * - * 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 = "Concept: AprilTag Switchable Cameras", group = "Concept") -@Disabled -public class ConceptAprilTagSwitchableCameras extends LinearOpMode { - - /* - * Variables used for switching cameras. - */ - private WebcamName webcam1, webcam2; - private boolean oldLeftBumper; - private boolean oldRightBumper; - - /** - * The variable to store our instance of the AprilTag processor. - */ - private AprilTagProcessor aprilTag; - - /** - * The variable to store our instance of the vision portal. - */ - private VisionPortal visionPortal; - - @Override - public void runOpMode() { - - initAprilTag(); - - // Wait for the DS start button to be touched. - telemetry.addData("DS preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - if (opModeIsActive()) { - while (opModeIsActive()) { - - telemetryCameraSwitching(); - telemetryAprilTag(); - - // Push telemetry to the Driver Station. - telemetry.update(); - - // Save CPU resources; can resume streaming when needed. - if (gamepad1.dpad_down) { - visionPortal.stopStreaming(); - } else if (gamepad1.dpad_up) { - visionPortal.resumeStreaming(); - } - - doCameraSwitching(); - - // Share the CPU. - sleep(20); - } - } - - // Save more CPU resources when camera is no longer needed. - visionPortal.close(); - - } // end runOpMode() - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - - // Create the AprilTag processor by using a builder. - aprilTag = new AprilTagProcessor.Builder().build(); - - webcam1 = hardwareMap.get(WebcamName.class, "Webcam 1"); - webcam2 = hardwareMap.get(WebcamName.class, "Webcam 2"); - CameraName switchableCamera = ClassFactory.getInstance() - .getCameraManager().nameForSwitchableCamera(webcam1, webcam2); - - // Create the vision portal by using a builder. - visionPortal = new VisionPortal.Builder() - .setCamera(switchableCamera) - .addProcessor(aprilTag) - .build(); - - } // end method initAprilTag() - - /** - * Add telemetry about camera switching. - */ - private void telemetryCameraSwitching() { - - if (visionPortal.getActiveCamera().equals(webcam1)) { - telemetry.addData("activeCamera", "Webcam 1"); - telemetry.addData("Press RightBumper", "to switch to Webcam 2"); - } else { - telemetry.addData("activeCamera", "Webcam 2"); - telemetry.addData("Press LeftBumper", "to switch to Webcam 1"); - } - - } // end method telemetryCameraSwitching() - - /** - * Add telemetry about AprilTag detections. - */ - private void telemetryAprilTag() { - - List currentDetections = aprilTag.getDetections(); - telemetry.addData("# AprilTags Detected", currentDetections.size()); - - // Step through the list of detections and display info for each one. - for (AprilTagDetection detection : currentDetections) { - if (detection.metadata != null) { - telemetry.addLine(String.format("\n==== (ID %d) %s", detection.id, detection.metadata.name)); - telemetry.addLine(String.format("XYZ %6.1f %6.1f %6.1f (inch)", detection.ftcPose.x, detection.ftcPose.y, detection.ftcPose.z)); - telemetry.addLine(String.format("PRY %6.1f %6.1f %6.1f (deg)", detection.ftcPose.pitch, detection.ftcPose.roll, detection.ftcPose.yaw)); - telemetry.addLine(String.format("RBE %6.1f %6.1f %6.1f (inch, deg, deg)", detection.ftcPose.range, detection.ftcPose.bearing, detection.ftcPose.elevation)); - } else { - telemetry.addLine(String.format("\n==== (ID %d) Unknown", detection.id)); - telemetry.addLine(String.format("Center %6.0f %6.0f (pixels)", detection.center.x, detection.center.y)); - } - } // end for() loop - - // Add "key" information to telemetry - telemetry.addLine("\nkey:\nXYZ = X (Right), Y (Forward), Z (Up) dist."); - telemetry.addLine("PRY = Pitch, Roll & Yaw (XYZ Rotation)"); - telemetry.addLine("RBE = Range, Bearing & Elevation"); - - } // end method telemetryAprilTag() - - /** - * Set the active camera according to input from the gamepad. - */ - private void doCameraSwitching() { - if (visionPortal.getCameraState() == CameraState.STREAMING) { - // If the left bumper is pressed, use Webcam 1. - // If the right bumper is pressed, use Webcam 2. - boolean newLeftBumper = gamepad1.left_bumper; - boolean newRightBumper = gamepad1.right_bumper; - if (newLeftBumper && !oldLeftBumper) { - visionPortal.setActiveCamera(webcam1); - } else if (newRightBumper && !oldRightBumper) { - visionPortal.setActiveCamera(webcam2); - } - oldLeftBumper = newLeftBumper; - oldRightBumper = newRightBumper; - } - - } // end method doCameraSwitching() - -} // end class diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExploringIMUOrientation.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExploringIMUOrientation.java deleted file mode 100644 index 751d54f9..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExploringIMUOrientation.java +++ /dev/null @@ -1,184 +0,0 @@ -/* -Copyright (c) 2022 REV Robotics, 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 REV Robotics 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.RevHubOrientationOnRobot; -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.IMU; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; - -/* - * This OpMode demonstrates the impact of setting the IMU orientation correctly or incorrectly. This - * code assumes there is an IMU configured with the name "imu". - * - * Note: This OpMode is more of a tool than a code sample. The User Interface portion of this code - * goes beyond simply showing how to interface to the IMU.
- * For a minimal example of interfacing to an IMU, please see the SensorIMUOrthogonal or SensorIMUNonOrthogonal sample OpModes. - * - * This OpMode enables you to re-specify the Hub Mounting orientation dynamically by using gamepad controls. - * While doing so, the sample will display how Pitch, Roll and Yaw angles change as the hub is moved. - * - * The gamepad controls let you change the two parameters that specify how the Control/Expansion Hub is mounted.
- * The first parameter specifies which direction the printed logo on the Hub is pointing.
- * The second parameter specifies which direction the USB connector on the Hub is pointing.
- * All directions are relative to the robot, and left/right is as viewed from behind the robot. - * - * How will you know if you have chosen the correct Orientation? With the correct orientation - * parameters selected, pitch/roll/yaw should act as follows: - * - * Pitch value should INCREASE as the robot is tipped UP at the front. (Rotation about X)
- * Roll value should INCREASE as the robot is tipped UP at the left side. (Rotation about Y)
- * Yaw value should INCREASE as the robot is rotated Counter Clockwise. (Rotation about Z)
- * - * The Yaw can be reset (to zero) by pressing the Y button on the gamepad (Triangle on a PS4 controller) - * - * The rotational velocities should follow the change in corresponding axes. - */ - -@TeleOp(name="Concept: IMU Orientation", group="Concept") -@Disabled -public class ConceptExploringIMUOrientation extends LinearOpMode { - static RevHubOrientationOnRobot.LogoFacingDirection[] logoFacingDirections - = RevHubOrientationOnRobot.LogoFacingDirection.values(); - static RevHubOrientationOnRobot.UsbFacingDirection[] usbFacingDirections - = RevHubOrientationOnRobot.UsbFacingDirection.values(); - static int LAST_DIRECTION = logoFacingDirections.length - 1; - static float TRIGGER_THRESHOLD = 0.2f; - - IMU imu; - int logoFacingDirectionPosition; - int usbFacingDirectionPosition; - boolean orientationIsValid = true; - - @Override public void runOpMode() throws InterruptedException { - imu = hardwareMap.get(IMU.class, "imu"); - logoFacingDirectionPosition = 0; // Up - usbFacingDirectionPosition = 2; // Forward - - updateOrientation(); - - boolean justChangedLogoDirection = false; - boolean justChangedUsbDirection = false; - - // Loop until stop requested - while (!isStopRequested()) { - - // Check to see if Yaw reset is requested (Y button) - if (gamepad1.y) { - telemetry.addData("Yaw", "Resetting\n"); - imu.resetYaw(); - } else { - telemetry.addData("Yaw", "Press Y (triangle) on Gamepad to reset.\n"); - } - - // Check to see if new Logo Direction is requested - if (gamepad1.left_bumper || gamepad1.right_bumper) { - if (!justChangedLogoDirection) { - justChangedLogoDirection = true; - if (gamepad1.left_bumper) { - logoFacingDirectionPosition--; - if (logoFacingDirectionPosition < 0) { - logoFacingDirectionPosition = LAST_DIRECTION; - } - } else { - logoFacingDirectionPosition++; - if (logoFacingDirectionPosition > LAST_DIRECTION) { - logoFacingDirectionPosition = 0; - } - } - updateOrientation(); - } - } else { - justChangedLogoDirection = false; - } - - // Check to see if new USB Direction is requested - if (gamepad1.left_trigger > TRIGGER_THRESHOLD || gamepad1.right_trigger > TRIGGER_THRESHOLD) { - if (!justChangedUsbDirection) { - justChangedUsbDirection = true; - if (gamepad1.left_trigger > TRIGGER_THRESHOLD) { - usbFacingDirectionPosition--; - if (usbFacingDirectionPosition < 0) { - usbFacingDirectionPosition = LAST_DIRECTION; - } - } else { - usbFacingDirectionPosition++; - if (usbFacingDirectionPosition > LAST_DIRECTION) { - usbFacingDirectionPosition = 0; - } - } - updateOrientation(); - } - } else { - justChangedUsbDirection = false; - } - - // Display User instructions and IMU data - telemetry.addData("logo Direction (set with bumpers)", logoFacingDirections[logoFacingDirectionPosition]); - telemetry.addData("usb Direction (set with triggers)", usbFacingDirections[usbFacingDirectionPosition] + "\n"); - - if (orientationIsValid) { - YawPitchRollAngles orientation = imu.getRobotYawPitchRollAngles(); - AngularVelocity angularVelocity = imu.getRobotAngularVelocity(AngleUnit.DEGREES); - - telemetry.addData("Yaw (Z)", "%.2f Deg. (Heading)", orientation.getYaw(AngleUnit.DEGREES)); - telemetry.addData("Pitch (X)", "%.2f Deg.", orientation.getPitch(AngleUnit.DEGREES)); - telemetry.addData("Roll (Y)", "%.2f Deg.\n", orientation.getRoll(AngleUnit.DEGREES)); - telemetry.addData("Yaw (Z) velocity", "%.2f Deg/Sec", angularVelocity.zRotationRate); - telemetry.addData("Pitch (X) velocity", "%.2f Deg/Sec", angularVelocity.xRotationRate); - telemetry.addData("Roll (Y) velocity", "%.2f Deg/Sec", angularVelocity.yRotationRate); - } else { - telemetry.addData("Error", "Selected orientation on robot is invalid"); - } - - telemetry.update(); - } - } - - // apply any requested orientation changes. - void updateOrientation() { - RevHubOrientationOnRobot.LogoFacingDirection logo = logoFacingDirections[logoFacingDirectionPosition]; - RevHubOrientationOnRobot.UsbFacingDirection usb = usbFacingDirections[usbFacingDirectionPosition]; - try { - RevHubOrientationOnRobot orientationOnRobot = new RevHubOrientationOnRobot(logo, usb); - imu.initialize(new IMU.Parameters(orientationOnRobot)); - orientationIsValid = true; - } catch (IllegalArgumentException e) { - orientationIsValid = false; - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExternalHardwareClass.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExternalHardwareClass.java deleted file mode 100644 index 7a721fef..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExternalHardwareClass.java +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (c) 2022 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 illustrates how to use an external "hardware" class to modularize all the robot's sensors and actuators. - * This approach is very efficient because the same hardware class can be used by all of your teleop and autonomous OpModes - * without requiring many copy & paste operations. Once you have defined and tested the hardware class with one OpMode, - * it is instantly available to other OpModes. - * - * The real benefit of this approach is that as you tweak your robot hardware, you only need to make changes in ONE place (the Hardware Class). - * So, to be effective you should put as much or your hardware setup and access code as possible in the hardware class. - * Essentially anything you do with hardware in BOTH Teleop and Auto should likely go in the hardware class. - * - * The Hardware Class is created in a separate file, and then an "instance" of this class is created in each OpMode. - * In order for the class to do typical OpMode things (like send telemetry data) it must be passed a reference to the - * OpMode object when it's created, so it can access all core OpMode functions. This is illustrated below. - * - * In this concept sample, the hardware class file is called RobotHardware.java and it must accompany this sample OpMode. - * So, if you copy ConceptExternalHardwareClass.java into TeamCode (using Android Studio or OnBotJava) then RobotHardware.java - * must also be copied to the same location (maintaining its name). - * - * For comparison purposes, this sample and its accompanying hardware class duplicates the functionality of the - * RobotTelopPOV_Linear OpMode. It assumes three motors (left_drive, right_drive and arm) and two servos (left_hand and right_hand) - * - * View the RobotHardware.java class file for more details - * - * 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 - * - * In OnBot Java, add a new OpMode, select this sample, and select TeleOp. - * Also add another new file named RobotHardware.java, select the sample with that name, and select Not an OpMode. - */ - -@TeleOp(name="Concept: Robot Hardware Class", group="Robot") -@Disabled -public class ConceptExternalHardwareClass extends LinearOpMode { - - // Create a RobotHardware object to be used to access robot hardware. - // Prefix any hardware functions with "robot." to access this class. - RobotHardware robot = new RobotHardware(this); - - @Override - public void runOpMode() { - double drive = 0; - double turn = 0; - double arm = 0; - double handOffset = 0; - - // initialize all the hardware, using the hardware class. See how clean and simple this is? - robot.init(); - - // Send telemetry message to signify robot waiting; - // Wait for the game to start (driver presses START) - waitForStart(); - - // run until the end of the match (driver presses STOP) - while (opModeIsActive()) { - - // Run wheels in POV mode (note: The joystick goes negative when pushed forward, so negate it) - // In this mode the Left stick moves the robot fwd and back, the Right stick turns left and right. - // This way it's also easy to just drive straight, or just turn. - drive = -gamepad1.left_stick_y; - turn = gamepad1.right_stick_x; - - // Combine drive and turn for blended motion. Use RobotHardware class - robot.driveRobot(drive, turn); - - // Use gamepad left & right Bumpers to open and close the claw - // Use the SERVO constants defined in RobotHardware class. - // Each time around the loop, the servos will move by a small amount. - // Limit the total offset to half of the full travel range - if (gamepad1.right_bumper) - handOffset += robot.HAND_SPEED; - else if (gamepad1.left_bumper) - handOffset -= robot.HAND_SPEED; - handOffset = Range.clip(handOffset, -0.5, 0.5); - - // Move both servos to new position. Use RobotHardware class - robot.setHandPositions(handOffset); - - // Use gamepad buttons to move arm up (Y) and down (A) - // Use the MOTOR constants defined in RobotHardware class. - if (gamepad1.y) - arm = robot.ARM_UP_POWER; - else if (gamepad1.a) - arm = robot.ARM_DOWN_POWER; - else - arm = 0; - - robot.setArmPower(arm); - - // Send telemetry messages to explain controls and show robot status - telemetry.addData("Drive", "Left Stick"); - telemetry.addData("Turn", "Right Stick"); - telemetry.addData("Arm Up/Down", "Y & A Buttons"); - telemetry.addData("Hand Open/Closed", "Left and Right Bumpers"); - telemetry.addData("-", "-------"); - - telemetry.addData("Drive Power", "%.2f", drive); - telemetry.addData("Turn Power", "%.2f", turn); - telemetry.addData("Arm Power", "%.2f", arm); - telemetry.addData("Hand Position", "Offset = %.2f", handOffset); - telemetry.update(); - - // Pace this loop so hands move at a reasonable speed. - sleep(50); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadRumble.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadRumble.java deleted file mode 100644 index cf846e18..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadRumble.java +++ /dev/null @@ -1,200 +0,0 @@ -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.Gamepad; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * This OpMode illustrates using the rumble feature of many gamepads. - * - * Note: Some gamepads "rumble" better than others. - * The Xbox & PS4 have a left (rumble1) and right (rumble2) rumble motor. - * These two gamepads have two distinct rumble modes: Large on the left, and small on the right - * The Etpark gamepad may only respond to rumble1, and may only run at full power. - * The Logitech F310 gamepad does not have *any* rumble ability. - * - * Moral: You should use this sample to experiment with your specific gamepads to explore their rumble features. - * - * The rumble motors are accessed through the standard gamepad1 and gamepad2 objects. - * Several new methods were added to the Gamepad class in FTC SDK Rev 7 - * The key methods are as follows: - * - * .rumble(double rumble1, double rumble2, int durationMs) - * This method sets the rumble power of both motors for a specific time duration. - * Both rumble arguments are motor-power levels in the 0.0 to 1.0 range. - * durationMs is the desired length of the rumble action in milliseconds. - * This method returns immediately. - * Note: - * Use a durationMs of Gamepad.RUMBLE_DURATION_CONTINUOUS to provide a continuous rumble - * Use a power of 0, or duration of 0 to stop a rumble. - * - * .rumbleBlips(int count) allows an easy way to signal the driver with a series of rumble blips. - * Just specify how many blips you want. - * This method returns immediately. - * - * .runRumbleEffect(customRumbleEffect) allows you to run a custom rumble sequence that you have - * built using the Gamepad.RumbleEffect.Builder() - * A "custom effect" is a sequence of steps, where each step can rumble any of the - * rumble motors for a specific period at a specific power level. - * The Custom Effect will play as the (un-blocked) OpMode continues to run - * - * .isRumbling() returns true if there is a rumble effect in progress. - * Use this call to prevent stepping on a current rumble. - * - * .stopRumble() Stop any ongoing rumble or custom rumble effect. - * - * .rumble(int durationMs) Full power rumble for fixed duration. - * - * Note: Whenever a new Rumble command is issued, any currently executing rumble action will - * be truncated, and the new action started immediately. Take these precautions: - * 1) Do Not SPAM the rumble motors by issuing rapid fire commands - * 2) Multiple sources for rumble commands must coordinate to avoid tromping on each other. - * - * This can be achieved several possible ways: - * 1) Only having one source for rumble actions - * 2) Issuing rumble commands on transitions, rather than states. - * e.g. The moment a touch sensor is pressed, rather than the entire time it is being pressed. - * 3) Scheduling rumble commands based on timed events. e.g. 10 seconds prior to endgame - * 4) Rumble on non-overlapping mechanical actions. e.g. arm fully-extended or fully-retracted. - * 5) Use isRumbling() to hold off on a new rumble if one is already in progress. - * - * The examples shown here are representstive of how to invoke a gamepad rumble. - * It is assumed that these will be modified to suit the specific robot and team strategy needs. - * - * ######## Read the telemetry display on the Driver Station Screen for instructions. ###### - * - * Ex 1) This example shows a) how to create a custom rumble effect, and then b) how to trigger it based - * on game time. One use for this might be to alert the driver that half-time or End-game is approaching. - * - * Ex 2) This example shows tying the rumble power to a changing sensor value. - * In this case it is the Gamepad trigger, but it could be any sensor output scaled to the 0-1 range. - * Since it takes over the rumble motors, it is only performed when the Left Bumper is pressed. - * Note that this approach MUST include a way to turn OFF the rumble when the button is released. - * - * Ex 3) This example shows a simple way to trigger a 3-blip sequence. In this case it is - * triggered by the gamepad A (Cross) button, but it could be any sensor, like a touch or light sensor. - * Note that this code ensures that it only rumbles once when the input goes true. - * - * Ex 4) This example shows how to trigger a single rumble when an input value gets over a certain value. - * In this case it is reading the Right Trigger, but it could be any variable sensor, like a - * range sensor, or position sensor. The code needs to ensure that it is only triggered once, so - * it waits till the sensor drops back below the threshold before it can trigger again. - * - * 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. - */ - -@Disabled -@TeleOp(name="Concept: Gamepad Rumble", group ="Concept") -public class ConceptGamepadRumble extends LinearOpMode -{ - boolean lastA = false; // Use to track the prior button state. - boolean lastLB = false; // Use to track the prior button state. - boolean highLevel = false; // used to prevent multiple level-based rumbles. - boolean secondHalf = false; // Use to prevent multiple half-time warning rumbles. - - Gamepad.RumbleEffect customRumbleEffect; // Use to build a custom rumble sequence. - ElapsedTime runtime = new ElapsedTime(); // Use to determine when end game is starting. - - final double HALF_TIME = 60.0; // Wait this many seconds before rumble-alert for half-time. - final double TRIGGER_THRESHOLD = 0.75; // Squeeze more than 3/4 to get rumble. - - @Override - public void runOpMode() - { - // Example 1. a) start by creating a three-pulse rumble sequence: right, LEFT, LEFT - customRumbleEffect = new Gamepad.RumbleEffect.Builder() - .addStep(0.0, 1.0, 500) // Rumble right motor 100% for 500 mSec - .addStep(0.0, 0.0, 300) // Pause for 300 mSec - .addStep(1.0, 0.0, 250) // Rumble left motor 100% for 250 mSec - .addStep(0.0, 0.0, 250) // Pause for 250 mSec - .addStep(1.0, 0.0, 250) // Rumble left motor 100% for 250 mSec - .build(); - - telemetry.addData(">", "Press Start"); - telemetry.update(); - - waitForStart(); - runtime.reset(); // Start game timer. - - // Loop while monitoring buttons for rumble triggers - while (opModeIsActive()) - { - // Read and save the current gamepad button states. - boolean currentA = gamepad1.a ; - boolean currentLB = gamepad1.left_bumper ; - - // Display the current Rumble status. Just for interest. - telemetry.addData(">", "Are we RUMBLING? %s\n", gamepad1.isRumbling() ? "YES" : "no" ); - - // ---------------------------------------------------------------------------------------- - // Example 1. b) Watch the runtime timer, and run the custom rumble when we hit half-time. - // Make sure we only signal once by setting "secondHalf" flag to prevent further rumbles. - // ---------------------------------------------------------------------------------------- - if ((runtime.seconds() > HALF_TIME) && !secondHalf) { - gamepad1.runRumbleEffect(customRumbleEffect); - secondHalf =true; - } - - // Display the time remaining while we are still counting down. - if (!secondHalf) { - telemetry.addData(">", "Halftime Alert Countdown: %3.0f Sec \n", (HALF_TIME - runtime.seconds()) ); - } - - - // ---------------------------------------------------------------------------------------- - // Example 2. If Left Bumper is being pressed, power the rumble motors based on the two trigger depressions. - // This is useful to see how the rumble feels at various power levels. - // ---------------------------------------------------------------------------------------- - if (currentLB) { - // Left Bumper is being pressed, so send left and right "trigger" values to left and right rumble motors. - gamepad1.rumble(gamepad1.left_trigger, gamepad1.right_trigger, Gamepad.RUMBLE_DURATION_CONTINUOUS); - - // Show what is being sent to rumbles - telemetry.addData(">", "Squeeze triggers to control rumbles"); - telemetry.addData("> : Rumble", "Left: %.0f%% Right: %.0f%%", gamepad1.left_trigger * 100, gamepad1.right_trigger * 100); - } else { - // Make sure rumble is turned off when Left Bumper is released (only one time each press) - if (lastLB) { - gamepad1.stopRumble(); - } - - // Prompt for manual rumble action - telemetry.addData(">", "Hold Left-Bumper to test Manual Rumble"); - telemetry.addData(">", "Press A (Cross) for three blips"); - telemetry.addData(">", "Squeeze right trigger slowly for 1 blip"); - } - lastLB = currentLB; // remember the current button state for next time around the loop - - - // ---------------------------------------------------------------------------------------- - // Example 3. Blip 3 times at the moment that A (Cross) is pressed. (look for pressed transition) - // BUT !!! Skip it altogether if the Gamepad is already rumbling. - // ---------------------------------------------------------------------------------------- - if (currentA && !lastA) { - if (!gamepad1.isRumbling()) // Check for possible overlap of rumbles. - gamepad1.rumbleBlips(3); - } - lastA = currentA; // remember the current button state for next time around the loop - - - // ---------------------------------------------------------------------------------------- - // Example 4. Rumble once when gamepad right trigger goes above the THRESHOLD. - // ---------------------------------------------------------------------------------------- - if (gamepad1.right_trigger > TRIGGER_THRESHOLD) { - if (!highLevel) { - gamepad1.rumble(0.9, 0, 200); // 200 mSec burst on left motor. - highLevel = true; // Hold off any more triggers - } - } else { - highLevel = false; // We can trigger again now. - } - - // Send the telemetry data to the Driver Station, and then pause to pace the program. - telemetry.update(); - sleep(10); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadTouchpad.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadTouchpad.java deleted file mode 100644 index 84d8cec9..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadTouchpad.java +++ /dev/null @@ -1,77 +0,0 @@ -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 org.firstinspires.ftc.robotcore.external.Telemetry; - -/* - * This OpMode illustrates using the touchpad feature found on some gamepads. - * - * The Sony PS4 gamepad can detect two distinct touches on the central touchpad. - * Other gamepads with different touchpads may provide mixed results. - * - * The touchpads are accessed through the standard gamepad1 and gamepad2 objects. - * Several new members were added to the Gamepad class in FTC SDK Rev 7 - * - * .touchpad_finger_1 returns true if at least one finger is detected. - * .touchpad_finger_1_x finger 1 X coordinate. Valid if touchpad_finger_1 is true - * .touchpad_finger_1_y finger 1 Y coordinate. Valid if touchpad_finger_1 is true - * - * .touchpad_finger_2 returns true if a second finger is detected - * .touchpad_finger_2_x finger 2 X coordinate. Valid if touchpad_finger_2 is true - * .touchpad_finger_2_y finger 2 Y coordinate. Valid if touchpad_finger_2 is true - * - * Finger touches are reported with an X and Y coordinate in following coordinate system. - * - * 1) X is the Horizontal axis, and Y is the vertical axis - * 2) The 0,0 origin is at the center of the touchpad. - * 3) 1.0, 1.0 is at the top right corner of the touchpad. - * 4) -1.0,-1.0 is at the bottom left corner of the touchpad. - * - * 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. - */ - -@Disabled -@TeleOp(name="Concept: Gamepad Touchpad", group ="Concept") -public class ConceptGamepadTouchpad extends LinearOpMode -{ - @Override - public void runOpMode() - { - telemetry.setDisplayFormat(Telemetry.DisplayFormat.MONOSPACE); - - telemetry.addData(">", "Press Start"); - telemetry.update(); - - waitForStart(); - - while (opModeIsActive()) - { - boolean finger = false; - - // Display finger 1 x & y position if finger detected - if(gamepad1.touchpad_finger_1) - { - finger = true; - telemetry.addLine(String.format("Finger 1: x=%5.2f y=%5.2f\n", gamepad1.touchpad_finger_1_x, gamepad1.touchpad_finger_1_y)); - } - - // Display finger 2 x & y position if finger detected - if(gamepad1.touchpad_finger_2) - { - finger = true; - telemetry.addLine(String.format("Finger 2: x=%5.2f y=%5.2f\n", gamepad1.touchpad_finger_2_x, gamepad1.touchpad_finger_2_y)); - } - - if(!finger) - { - telemetry.addLine("No fingers"); - } - - telemetry.update(); - sleep(10); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptLEDStick.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptLEDStick.java deleted file mode 100644 index 01729bbb..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptLEDStick.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.firstinspires.ftc.robotcontroller.external.samples; -/* - Copyright (c) 2021-24 Alan Smith - - 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 Alan Smith 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 FITNESSFOR 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. -*/ - -import android.graphics.Color; - -import com.qualcomm.hardware.sparkfun.SparkFunLEDStick; -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.Range; - -/* - * This OpMode illustrates how to use the SparkFun QWIIC LED Strip - * - * This is a simple way to add a strip of 10 LEDs to your robot where you can set the color of each - * LED or the whole strip. This allows for driver feedback or even just fun ways to show your team - * colors. - * - * Why? - * Because more LEDs == more fun!! - * - * This OpMode assumes that the QWIIC LED Stick is attached to an I2C interface named "back_leds" in the robot configuration. - * - * 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 - * - * You can buy this product here: https://www.sparkfun.com/products/18354 - * Don't forget to also buy this to make it easy to connect to your Control or Expansion Hub: - * https://www.sparkfun.com/products/25596 - */ -@TeleOp(name = "Concept: LED Stick", group = "Concept") -@Disabled -public class ConceptLEDStick extends OpMode { - private boolean wasUp; - private boolean wasDown; - private int brightness = 5; // this needs to be between 0 and 31 - private final static double END_GAME_TIME = 120 - 30; - - private SparkFunLEDStick ledStick; - - @Override - public void init() { - ledStick = hardwareMap.get(SparkFunLEDStick.class, "back_leds"); - ledStick.setBrightness(brightness); - ledStick.setColor(Color.GREEN); - } - - @Override - public void start() { - resetRuntime(); - } - - @Override - public void loop() { - telemetry.addLine("Hold the A button to turn blue"); - telemetry.addLine("Hold the B button to turn red"); - telemetry.addLine("Hold the left bumper to turn off"); - telemetry.addLine("Use DPAD Up/Down to change brightness"); - - if (getRuntime() > END_GAME_TIME) { - int[] ledColors = {Color.RED, Color.YELLOW, Color.RED, Color.YELLOW, Color.RED, - Color.YELLOW, Color.RED, Color.YELLOW, Color.RED, Color.YELLOW}; - ledStick.setColors(ledColors); - } else if (gamepad1.a) { - ledStick.setColor(Color.BLUE); - } else if (gamepad1.b) { - ledStick.setColor(Color.RED); - } else if (gamepad1.left_bumper) { - ledStick.turnAllOff(); - } else { - ledStick.setColor(Color.GREEN); - } - - /* - * Use DPAD up and down to change brightness - */ - int newBrightness = brightness; - if (gamepad1.dpad_up && !wasUp) { - newBrightness = brightness + 1; - } else if (gamepad1.dpad_down && !wasDown) { - newBrightness = brightness - 1; - } - if (newBrightness != brightness) { - brightness = Range.clip(newBrightness, 0, 31); - ledStick.setBrightness(brightness); - } - telemetry.addData("Brightness", brightness); - - wasDown = gamepad1.dpad_down; - wasUp = gamepad1.dpad_up; - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptMotorBulkRead.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptMotorBulkRead.java deleted file mode 100644 index 5439f780..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptMotorBulkRead.java +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright (c) 2019 Phil Malone. 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.lynx.LynxModule; -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.DcMotorEx; -import com.qualcomm.robotcore.util.ElapsedTime; - -import java.util.List; - -/* - * This OpMode illustrates how to use the Expansion Hub's Bulk-Read feature to speed up control cycle times. - * In this example there are 4 motors that need their encoder positions, and velocities read. - * The sample is written to work with one or two expansion hubs, with no assumption as to where the motors are located. - * - * Three scenarios are tested: - * Cache Mode = OFF This is the normal default, where no cache is used, and every read produces a discrete transaction with - * an expansion hub, which is the slowest approach, but guarentees that the value is as fresh (recent) as possible.. - * - * Cache Mode = AUTO This mode will attempt to minimize the number of discrete read commands, by performing bulk-reads - * and then returning values that have been cached. The cache is updated automatically whenever any specific encoder is re-read. - * This mode will always return new data, but it may perform more bulk-reads than absolutely required. - * Extra reads will be performed if multiple encoder/velocity reads are performed on the same encoder in one control cycle. - * This mode is a good compromise between the OFF and MANUAL modes. - * Note: If there are significant user-program delays between encoder reads, the cached value may not be fresh (recent). - * You can issue a clearBulkCache() call at any time force a fresh bulk-read on the next encoder read. - * - * Cache Mode = MANUAL This mode requires the user's code to determine the best time to clear the cached bulk-read data. - * Well organized code will reset the cache once at the beginning of the control cycle, and then immediately read and store all the encoder values. - * This approach will produce the shortest cycle times, but it does require the user to manually clear the cache. - * Since NO automatic Bulk-Reads are performed, neglecting to clear the bulk cache will result in the same values being returned - * each time an encoder read is performed. - * - * ------------------------------------- - * - * General tip to speed up your control cycles: - * - * No matter what method you use to read encoders and other inputs, you should try to - * avoid reading the same encoder input multiple times around a control loop. - * Under normal conditions, this will slow down the control loop. - * The preferred method is to read all the required inputs ONCE at the beginning of the loop, - * and save the values in variable that can be used by other parts of the control code. - * - * eg: if you are sending encoder positions to your telemetry display, putting a getCurrentPosition() - * call in the telemetry statement will force the code to go and get another copy which will take time. - * It's much better read the position into a variable once, and use that variable for control AND display. - * Reading saved variables takes no time at all. - * - * Once you put all your sensor reads at the beginning of the control cycle, it's very easy to use - * the bulk-read AUTO mode to streamline your cycle timing. - */ -@TeleOp (name = "Motor Bulk Reads", group = "Tests") -@Disabled -public class ConceptMotorBulkRead extends LinearOpMode { - - final int TEST_CYCLES = 500; // Number of control cycles to run to determine cycle times. - - private DcMotorEx m1, m2, m3, m4; // Motor Objects - private long e1, e2, e3, e4; // Encoder Values - private double v1, v2, v3, v4; // Velocities - - // Cycle Times - double t1 = 0; - double t2 = 0; - double t3 = 0; - - @Override - public void runOpMode() { - - int cycles; - - // Important Step 1: Make sure you use DcMotorEx when you instantiate your motors. - m1 = hardwareMap.get(DcMotorEx.class, "m1"); // Configure the robot to use these 4 motor names, - m2 = hardwareMap.get(DcMotorEx.class, "m2"); // or change these strings to match your existing Robot Configuration. - m3 = hardwareMap.get(DcMotorEx.class, "m3"); - m4 = hardwareMap.get(DcMotorEx.class, "m4"); - - // Important Step 2: Get access to a list of Expansion Hub Modules to enable changing caching methods. - List allHubs = hardwareMap.getAll(LynxModule.class); - - ElapsedTime timer = new ElapsedTime(); - - telemetry.addData(">", "Press START to start tests"); - telemetry.addData(">", "Test results will update for each access method."); - telemetry.update(); - waitForStart(); - - // -------------------------------------------------------------------------------------- - // Run control loop using legacy encoder reads - // In this mode, a single read is done for each encoder position, and a bulk read is done for each velocity read. - // This is the worst case scenario. - // This is the same as using LynxModule.BulkCachingMode.OFF - // -------------------------------------------------------------------------------------- - - displayCycleTimes("Test 1 of 3 (Wait for completion)"); - - timer.reset(); - cycles = 0; - while (opModeIsActive() && (cycles++ < TEST_CYCLES)) { - e1 = m1.getCurrentPosition(); - e2 = m2.getCurrentPosition(); - e3 = m3.getCurrentPosition(); - e4 = m4.getCurrentPosition(); - - v1 = m1.getVelocity(); - v2 = m2.getVelocity(); - v3 = m3.getVelocity(); - v4 = m4.getVelocity(); - - // Put Control loop action code here. - - } - // calculate the average cycle time. - t1 = timer.milliseconds() / cycles; - displayCycleTimes("Test 2 of 3 (Wait for completion)"); - - // -------------------------------------------------------------------------------------- - // Run test cycles using AUTO cache mode - // In this mode, only one bulk read is done per cycle, UNLESS you read a specific encoder/velocity item AGAIN in that cycle. - // -------------------------------------------------------------------------------------- - - // Important Step 3: Option A. Set all Expansion hubs to use the AUTO Bulk Caching mode - for (LynxModule module : allHubs) { - module.setBulkCachingMode(LynxModule.BulkCachingMode.AUTO); - } - - timer.reset(); - cycles = 0; - while (opModeIsActive() && (cycles++ < TEST_CYCLES)) { - e1 = m1.getCurrentPosition(); // Uses 1 bulk-read for all 4 encoder/velocity reads, - e2 = m2.getCurrentPosition(); // but don't do any `get` operations more than once per cycle. - e3 = m3.getCurrentPosition(); - e4 = m4.getCurrentPosition(); - - v1 = m1.getVelocity(); - v2 = m2.getVelocity(); - v3 = m3.getVelocity(); - v4 = m4.getVelocity(); - - // Put Control loop action code here. - - } - // calculate the average cycle time. - t2 = timer.milliseconds() / cycles; - displayCycleTimes("Test 3 of 3 (Wait for completion)"); - - // -------------------------------------------------------------------------------------- - // Run test cycles using MANUAL cache mode - // In this mode, only one block read is done each control cycle. - // This is the MOST efficient method, but it does require that the cache is cleared manually each control cycle. - // -------------------------------------------------------------------------------------- - - // Important Step 3: Option B. Set all Expansion hubs to use the MANUAL Bulk Caching mode - for (LynxModule module : allHubs) { - module.setBulkCachingMode(LynxModule.BulkCachingMode.MANUAL); - } - - timer.reset(); - cycles = 0; - while (opModeIsActive() && (cycles++ < TEST_CYCLES)) { - - // Important Step 4: If you are using MANUAL mode, you must clear the BulkCache once per control cycle - for (LynxModule module : allHubs) { - module.clearBulkCache(); - } - - e1 = m1.getCurrentPosition(); // Uses 1 bulk-read to obtain ALL the motor data - e2 = m2.getCurrentPosition(); // There is no penalty for doing more `get` operations in this cycle, - e3 = m3.getCurrentPosition(); // but they will return the same data. - e4 = m4.getCurrentPosition(); - - v1 = m1.getVelocity(); - v2 = m2.getVelocity(); - v3 = m3.getVelocity(); - v4 = m4.getVelocity(); - - // Put Control loop action code here. - - } - // calculate the average cycle time. - t3 = timer.milliseconds() / cycles; - displayCycleTimes("Complete"); - - // wait until op-mode is stopped by user, before clearing display. - while (opModeIsActive()) ; - } - - // Display three comparison times. - void displayCycleTimes(String status) { - telemetry.addData("Testing", status); - telemetry.addData("Cache = OFF", "%5.1f mS/cycle", t1); - telemetry.addData("Cache = AUTO", "%5.1f mS/cycle", t2); - telemetry.addData("Cache = MANUAL", "%5.1f mS/cycle", t3); - telemetry.update(); - } -} - diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java deleted file mode 100644 index 4a887bda..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java +++ /dev/null @@ -1,89 +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.OpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * Demonstrates an empty iterative OpMode - */ -@TeleOp(name = "Concept: NullOp", group = "Concept") -@Disabled -public class ConceptNullOp extends OpMode { - - private ElapsedTime runtime = new ElapsedTime(); - - /** - * This method will be called once, when the INIT button is pressed. - */ - @Override - public void init() { - telemetry.addData("Status", "Initialized"); - } - - /** - * This method will be called repeatedly during the period between when - * the INIT button is pressed and when the START button is pressed (or the - * OpMode is stopped). - */ - @Override - public void init_loop() { - } - - /** - * This method will be called once, when the START button is pressed. - */ - @Override - public void start() { - runtime.reset(); - } - - /** - * This method will be called repeatedly during the period between when - * the START button is pressed and when the OpMode is stopped. - */ - @Override - public void loop() { - telemetry.addData("Status", "Run Time: " + runtime.toString()); - } - - /** - * This method will be called once, when this OpMode is stopped. - *

- * Your ability to control hardware from this method will be limited. - */ - @Override - public void stop() { - - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java deleted file mode 100644 index 6e0be376..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java +++ /dev/null @@ -1,114 +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.DcMotor; - -/* - * This OpMode ramps a single motor speed up and down repeatedly until Stop is pressed. - * The code is structured as a LinearOpMode - * - * This code assumes a DC motor configured with the name "left_drive" as is found on a Robot. - * - * INCREMENT sets how much to increase/decrease the power each cycle - * CYCLE_MS sets the update period. - * - * 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 = "Concept: Ramp Motor Speed", group = "Concept") -@Disabled -public class ConceptRampMotorSpeed extends LinearOpMode { - - static final double INCREMENT = 0.01; // amount to ramp motor each CYCLE_MS cycle - static final int CYCLE_MS = 50; // period of each cycle - static final double MAX_FWD = 1.0; // Maximum FWD power applied to motor - static final double MAX_REV = -1.0; // Maximum REV power applied to motor - - // Define class members - DcMotor motor; - double power = 0; - boolean rampUp = true; - - - @Override - public void runOpMode() { - - // Connect to motor (Assume standard left wheel) - // Change the text in quotes to match any motor name on your robot. - motor = hardwareMap.get(DcMotor.class, "left_drive"); - - // Wait for the start button - telemetry.addData(">", "Press Start to run Motors." ); - telemetry.update(); - waitForStart(); - - // Ramp motor speeds till stop pressed. - while(opModeIsActive()) { - - // Ramp the motors, according to the rampUp variable. - if (rampUp) { - // Keep stepping up until we hit the max value. - power += INCREMENT ; - if (power >= MAX_FWD ) { - power = MAX_FWD; - rampUp = !rampUp; // Switch ramp direction - } - } - else { - // Keep stepping down until we hit the min value. - power -= INCREMENT ; - if (power <= MAX_REV ) { - power = MAX_REV; - rampUp = !rampUp; // Switch ramp direction - } - } - - // Display the current value - telemetry.addData("Motor Power", "%5.2f", power); - telemetry.addData(">", "Press Stop to end test." ); - telemetry.update(); - - // Set the motor to the new power and pause; - motor.setPower(power); - sleep(CYCLE_MS); - idle(); - } - - // Turn off motor and signal done; - motor.setPower(0); - telemetry.addData(">", "Done"); - telemetry.update(); - - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevLED.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevLED.java deleted file mode 100644 index 9c168d50..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevLED.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (c) 2024 Alan Smith - 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 Alan Smith 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 FITNESSFOR 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; - -/* - * This OpMode illustrates how to use the REV Digital Indicator - * - * This is a simple way to add the REV Digital Indicator which has a red and green LED. - * (and as you may remember, red + green = yellow so when they are both on you can get yellow) - * - * Why? - * You can use this to show information to the driver. For example, green might be that you can - * pick up more game elements and red would be that you already have the possession limit. - * - * This OpMode assumes that the REV Digital Indicator is setup as 2 Digital Channels named - * front_led_green and front_led_red. (the green should be the lower of the 2 channels it is plugged - * into and the red should be the higher) - * - * 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 - * - * You can buy this product here: https://www.revrobotics.com/rev-31-2010/ - */ -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.hardware.LED; - -@TeleOp(name = "Concept: RevLED", group = "Concept") -@Disabled -public class ConceptRevLED extends OpMode { - LED frontLED_red; - LED frontLED_green; - - @Override - public void init() { - frontLED_green = hardwareMap.get(LED.class, "front_led_green"); - frontLED_red = hardwareMap.get(LED.class, "front_led_red"); - } - - @Override - public void loop() { - if (gamepad1.a) { - frontLED_red.on(); - } else { - frontLED_red.off(); - } - if (gamepad1.b) { - frontLED_green.on(); - } else { - frontLED_green.off(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevSPARKMini.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevSPARKMini.java deleted file mode 100644 index 798d6893..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevSPARKMini.java +++ /dev/null @@ -1,111 +0,0 @@ -/* 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 demonstrates a POV Drive system, with commented-out code for a Tank Drive system, - * for a two wheeled robot using two REV SPARKminis. - * To use this example, connect two REV SPARKminis into servo ports on the Control Hub. On the - * robot configuration, use the drop down list under 'Servos' to select 'REV SPARKmini Controller' - * and name them 'left_drive' and 'right_drive'. - * - * 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="REV SPARKmini 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 robot configuration. - 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 backward when connected directly to the battery - leftDrive.setDirection(DcMotorSimple.Direction.FORWARD); - rightDrive.setDirection(DcMotorSimple.Direction.REVERSE); - - // Wait for the game to start (driver presses START) - 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/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java deleted file mode 100644 index 2b8ad332..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java +++ /dev/null @@ -1,115 +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.Servo; - -/* - * This OpMode scans a single servo back and forward until Stop is pressed. - * The code is structured as a LinearOpMode - * 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_hand" as is found on a Robot. - * - * 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. - * - * 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 = "Concept: Scan Servo", group = "Concept") -@Disabled -public class ConceptScanServo extends LinearOpMode { - - static final double INCREMENT = 0.01; // amount to slew servo each CYCLE_MS cycle - static final int CYCLE_MS = 50; // period of each cycle - static final double MAX_POS = 1.0; // Maximum rotational position - static final double MIN_POS = 0.0; // Minimum rotational position - - // Define class members - Servo servo; - double position = (MAX_POS - MIN_POS) / 2; // Start at halfway position - boolean rampUp = true; - - - @Override - public void runOpMode() { - - // Connect to servo (Assume Robot Left Hand) - // Change the text in quotes to match any servo name on your robot. - servo = hardwareMap.get(Servo.class, "left_hand"); - - // Wait for the start button - telemetry.addData(">", "Press Start to scan Servo." ); - telemetry.update(); - waitForStart(); - - - // Scan servo till stop pressed. - while(opModeIsActive()){ - - // slew the servo, according to the rampUp (direction) variable. - if (rampUp) { - // Keep stepping up until we hit the max value. - position += INCREMENT ; - if (position >= MAX_POS ) { - position = MAX_POS; - rampUp = !rampUp; // Switch ramp direction - } - } - else { - // Keep stepping down until we hit the min value. - position -= INCREMENT ; - if (position <= MIN_POS ) { - position = MIN_POS; - rampUp = !rampUp; // Switch ramp direction - } - } - - // Display the current value - telemetry.addData("Servo Position", "%5.2f", position); - telemetry.addData(">", "Press Stop to end test." ); - telemetry.update(); - - // Set the servo to the new position and pause; - servo.setPosition(position); - sleep(CYCLE_MS); - idle(); - } - - // Signal done; - telemetry.addData(">", "Done"); - telemetry.update(); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsASJava.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsASJava.java deleted file mode 100644 index 1ceaa17d..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsASJava.java +++ /dev/null @@ -1,133 +0,0 @@ -/* 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; - -/* - * This OpMode 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 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 - * - * 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 START) - 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/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsOnBotJava.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsOnBotJava.java deleted file mode 100644 index fbb7416c..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsOnBotJava.java +++ /dev/null @@ -1,120 +0,0 @@ -/* 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 OpMode 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/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsSKYSTONE.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsSKYSTONE.java deleted file mode 100644 index 983e434f..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsSKYSTONE.java +++ /dev/null @@ -1,122 +0,0 @@ -/* 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 android.content.Context; -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; - -/* - * This OpMode demonstrates how to play one of the several SKYSTONE/Star Wars sounds loaded into the SDK. - * It does this by creating a simple "chooser" controlled by the gamepad Up Down buttons. - * This code also prevents sounds from stacking up by setting a "playing" flag, which is cleared when the sound finishes playing. - * - * 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 - * - * Operation: - * Use the DPAD to change the selected sound, and the Right Bumper to play it. - */ - -@TeleOp(name="SKYSTONE Sounds", group="Concept") -@Disabled -public class ConceptSoundsSKYSTONE extends LinearOpMode { - - // List of available sound resources - String sounds[] = {"ss_alarm", "ss_bb8_down", "ss_bb8_up", "ss_darth_vader", "ss_fly_by", - "ss_mf_fail", "ss_laser", "ss_laser_burst", "ss_light_saber", "ss_light_saber_long", "ss_light_saber_short", - "ss_light_speed", "ss_mine", "ss_power_up", "ss_r2d2_up", "ss_roger_roger", "ss_siren", "ss_wookie" }; - boolean soundPlaying = false; - - @Override - public void runOpMode() { - - // Variables for choosing from the available sounds - int soundIndex = 0; - int soundID = -1; - boolean was_dpad_up = false; - boolean was_dpad_down = false; - - Context myApp = hardwareMap.appContext; - - // create a sound parameter that holds the desired player parameters. - SoundPlayer.PlaySoundParams params = new SoundPlayer.PlaySoundParams(); - params.loopControl = 0; - params.waitForNonLoopingSoundsToFinish = true; - - // In this sample, we will skip waiting for the user to press play, and start displaying sound choices right away - while (!isStopRequested()) { - - // Look for DPAD presses to change the selection - if (gamepad1.dpad_down && !was_dpad_down) { - // Go to next sound (with list wrap) and display it - soundIndex = (soundIndex + 1) % sounds.length; - } - - if (gamepad1.dpad_up && !was_dpad_up) { - // Go to previous sound (with list wrap) and display it - soundIndex = (soundIndex + sounds.length - 1) % sounds.length; - } - - // Look for trigger to see if we should play sound - // Only start a new sound if we are currently not playing one. - if (gamepad1.right_bumper && !soundPlaying) { - - // Determine Resource IDs for the sounds you want to play, and make sure it's valid. - if ((soundID = myApp.getResources().getIdentifier(sounds[soundIndex], "raw", myApp.getPackageName())) != 0){ - - // Signal that the sound is now playing. - soundPlaying = true; - - // Start playing, and also Create a callback that will clear the playing flag when the sound is complete. - SoundPlayer.getInstance().startPlaying(myApp, soundID, params, null, - new Runnable() { - public void run() { - soundPlaying = false; - }} ); - } - } - - // Remember the last state of the dpad to detect changes. - was_dpad_up = gamepad1.dpad_up; - was_dpad_down = gamepad1.dpad_down; - - // Display the current sound choice, and the playing status. - telemetry.addData("", "Use DPAD up/down to choose sound."); - telemetry.addData("", "Press Right Bumper to play sound."); - telemetry.addData("", ""); - telemetry.addData("Sound >", sounds[soundIndex]); - telemetry.addData("Status >", soundPlaying ? "Playing" : "Stopped"); - telemetry.update(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java deleted file mode 100644 index f2c60970..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java +++ /dev/null @@ -1,177 +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.VoltageSensor; -import com.qualcomm.robotcore.util.ElapsedTime; -import org.firstinspires.ftc.robotcore.external.Func; -import org.firstinspires.ftc.robotcore.external.Telemetry; - -/* - * This OpMode illustrates various ways in which telemetry can be - * transmitted from the robot controller to the driver station. The sample illustrates - * numeric and text data, formatted output, and optimized evaluation of expensive-to-acquire - * information. The telemetry log is illustrated by scrolling a poem - * to the driver station. - * - * Also see the Telemetry javadocs. - */ -@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 */ - int poemLine = 0; - - /** Keeps track of how long it's been since we last emitted a line of poetry */ - ElapsedTime poemElapsed = new ElapsedTime(); - - static final String[] poem = new String[] { - - "Mary had a little lamb,", - "His fleece was white as snow,", - "And everywhere that Mary went,", - "The lamb was sure to go.", - "", - "He followed her to school one day,", - "Which was against the rule,", - "It made the children laugh and play", - "To see a lamb at school.", - "", - "And so the teacher turned it out,", - "But still it lingered near,", - "And waited patiently about,", - "Till Mary did appear.", - "", - "\"Why does the lamb love Mary so?\"", - "The eager children cry.", - "\"Why, Mary loves the lamb, you know,\"", - "The teacher did reply.", - "", - "" - }; - - @Override public void runOpMode() { - - /* we keep track of how long it's been since the OpMode was started, just - * to have some interesting data to show */ - ElapsedTime opmodeRunTime = new ElapsedTime(); - - // We show the log in oldest-to-newest order, as that's better for poetry - telemetry.log().setDisplayOrder(Telemetry.Log.DisplayOrder.OLDEST_FIRST); - // We can control the number of lines shown in the log - telemetry.log().setCapacity(6); - // The interval between lines of poetry, in seconds - double sPoemInterval = 0.6; - - /* - * Wait until we've been given the ok to go. For something to do, we emit the - * elapsed time as we sit here and wait. If we didn't want to do anything while - * we waited, we would just call waitForStart(). - */ - while (!isStarted()) { - telemetry.addData("time", "%.1f seconds", opmodeRunTime.seconds()); - telemetry.update(); - idle(); - } - - // Ok, we've been given the ok to go - - /* - * As an illustration, the first line on our telemetry display will display the battery voltage. - * The idea here is that it's expensive to compute the voltage (at least for purposes of illustration) - * so you don't want to do it unless the data is _actually_ going to make it to the - * driver station (recall that telemetry transmission is throttled to reduce bandwidth use. - * Note that getBatteryVoltage() below returns 'Infinity' if there's no voltage sensor attached. - * - * @see Telemetry#getMsTransmissionInterval() - */ - telemetry.addData("voltage", "%.1f volts", new Func() { - @Override public Double value() { - return getBatteryVoltage(); - } - }); - - // Reset to keep some timing stats for the post-'start' part of the OpMode - opmodeRunTime.reset(); - int loopCount = 1; - - // Go go gadget robot! - while (opModeIsActive()) { - - // Emit poetry if it's been a while - if (poemElapsed.seconds() > sPoemInterval) { - emitPoemLine(); - } - - // As an illustration, show some loop timing information - telemetry.addData("loop count", loopCount); - telemetry.addData("ms/loop", "%.3f ms", opmodeRunTime.milliseconds() / loopCount); - - // Show joystick information as some other illustrative data - telemetry.addLine("left joystick | ") - .addData("x", gamepad1.left_stick_x) - .addData("y", gamepad1.left_stick_y); - telemetry.addLine("right joystick | ") - .addData("x", gamepad1.right_stick_x) - .addData("y", gamepad1.right_stick_y); - - /* - * Transmit the telemetry to the driver station, subject to throttling. - * See the documentation for Telemetry.getMsTransmissionInterval() for more information. - */ - telemetry.update(); - - // Update loop info - loopCount++; - } - } - - // emits a line of poetry to the telemetry log - void emitPoemLine() { - telemetry.log().add(poem[poemLine]); - poemLine = (poemLine+1) % poem.length; - poemElapsed.reset(); - } - - // Computes the current battery voltage - double getBatteryVoltage() { - double result = Double.POSITIVE_INFINITY; - for (VoltageSensor sensor : hardwareMap.voltageSensor) { - double voltage = sensor.getVoltage(); - if (voltage > 0) { - result = Math.min(result, voltage); - } - } - return result; - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorLocator.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorLocator.java deleted file mode 100644 index 987694db..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorLocator.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2024 Phil Malone - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import android.util.Size; - -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.SortOrder; - -import org.firstinspires.ftc.robotcore.external.Telemetry; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.opencv.ColorBlobLocatorProcessor; -import org.firstinspires.ftc.vision.opencv.ColorRange; -import org.firstinspires.ftc.vision.opencv.ImageRegion; -import org.opencv.core.RotatedRect; - -import java.util.List; - -/* - * This OpMode illustrates how to use a video source (camera) to locate specifically colored regions - * - * Unlike a "color sensor" which determines the color of an object in the field of view, this "color locator" - * will search the Region Of Interest (ROI) in a camera image, and find any "blobs" of color that match the requested color range. - * These blobs can be further filtered and sorted to find the one most likely to be the item the user is looking for. - * - * To perform this function, a VisionPortal runs a ColorBlobLocatorProcessor process. - * The ColorBlobLocatorProcessor process is created first, and then the VisionPortal is built to use this process. - * The ColorBlobLocatorProcessor analyses the ROI and locates pixels that match the ColorRange to form a "mask". - * The matching pixels are then collected into contiguous "blobs" of pixels. The outer boundaries of these blobs are called its "contour". - * For each blob, the process then creates the smallest possible rectangle "boxFit" that will fully encase the contour. - * The user can then call getBlobs() to retrieve the list of Blobs, where each Blob contains the contour and the boxFit data. - * Note: The default sort order for Blobs is ContourArea, in descending order, so the biggest contours are listed first. - * - * To aid the user, a colored boxFit rectangle is drawn on the camera preview to show the location of each Blob - * The original Blob contour can also be added to the preview. This is helpful when configuring the ColorBlobLocatorProcessor parameters. - * - * 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 - */ - -@Disabled -@TeleOp(name = "Concept: Vision Color-Locator", group = "Concept") -public class ConceptVisionColorLocator extends LinearOpMode -{ - @Override - public void runOpMode() - { - /* Build a "Color Locator" vision processor based on the ColorBlobLocatorProcessor class. - * - Specify the color range you are looking for. You can use a predefined color, or create you own color range - * .setTargetColorRange(ColorRange.BLUE) // use a predefined color match - * Available predefined colors are: RED, BLUE YELLOW GREEN - * .setTargetColorRange(new ColorRange(ColorSpace.YCrCb, // or define your own color match - * new Scalar( 32, 176, 0), - * new Scalar(255, 255, 132))) - * - * - Focus the color locator by defining a RegionOfInterest (ROI) which you want to search. - * This can be the entire frame, or a sub-region defined using: - * 1) standard image coordinates or 2) a normalized +/- 1.0 coordinate system. - * Use one form of the ImageRegion class to define the ROI. - * ImageRegion.entireFrame() - * ImageRegion.asImageCoordinates(50, 50, 150, 150) 100x100 pixel square near the upper left corner - * ImageRegion.asUnityCenterCoordinates(-0.5, 0.5, 0.5, -0.5) 50% width/height square centered on screen - * - * - Define which contours are included. - * You can get ALL the contours, or you can skip any contours that are completely inside another contour. - * .setContourMode(ColorBlobLocatorProcessor.ContourMode.ALL_FLATTENED_HIERARCHY) // return all contours - * .setContourMode(ColorBlobLocatorProcessor.ContourMode.EXTERNAL_ONLY) // exclude contours inside other contours - * note: EXTERNAL_ONLY helps to avoid bright reflection spots from breaking up areas of solid color. - * - * - turn the display of contours ON or OFF. Turning this on helps debugging but takes up valuable CPU time. - * .setDrawContours(true) - * - * - include any pre-processing of the image or mask before looking for Blobs. - * There are some extra processing you can include to improve the formation of blobs. Using these features requires - * an understanding of how they may effect the final blobs. The "pixels" argument sets the NxN kernel size. - * .setBlurSize(int pixels) Blurring an image helps to provide a smooth color transition between objects, and smoother contours. - * The higher the number of pixels, the more blurred the image becomes. - * Note: Even "pixels" values will be incremented to satisfy the "odd number" requirement. - * Blurring too much may hide smaller features. A "pixels" size of 5 is good for a 320x240 image. - * .setErodeSize(int pixels) Erosion removes floating pixels and thin lines so that only substantive objects remain. - * Erosion can grow holes inside regions, and also shrink objects. - * "pixels" in the range of 2-4 are suitable for low res images. - * .setDilateSize(int pixels) Dilation makes objects more visible by filling in small holes, making lines appear thicker, - * and making filled shapes appear larger. Dilation is useful for joining broken parts of an - * object, such as when removing noise from an image. - * "pixels" in the range of 2-4 are suitable for low res images. - */ - ColorBlobLocatorProcessor colorLocator = new ColorBlobLocatorProcessor.Builder() - .setTargetColorRange(ColorRange.BLUE) // use a predefined color match - .setContourMode(ColorBlobLocatorProcessor.ContourMode.EXTERNAL_ONLY) // exclude blobs inside blobs - .setRoi(ImageRegion.asUnityCenterCoordinates(-0.5, 0.5, 0.5, -0.5)) // search central 1/4 of camera view - .setDrawContours(true) // Show contours on the Stream Preview - .setBlurSize(5) // Smooth the transitions between different colors in image - .build(); - - /* - * Build a vision portal to run the Color Locator process. - * - * - Add the colorLocator process created above. - * - Set the desired video resolution. - * Since a high resolution will not improve this process, choose a lower resolution that is - * supported by your camera. This will improve overall performance and reduce latency. - * - Choose your video source. This may be - * .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) ..... for a webcam - * or - * .setCamera(BuiltinCameraDirection.BACK) ... for a Phone Camera - */ - VisionPortal portal = new VisionPortal.Builder() - .addProcessor(colorLocator) - .setCameraResolution(new Size(320, 240)) - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .build(); - - telemetry.setMsTransmissionInterval(50); // Speed up telemetry updates, Just use for debugging. - telemetry.setDisplayFormat(Telemetry.DisplayFormat.MONOSPACE); - - // WARNING: To be able to view the stream preview on the Driver Station, this code runs in INIT mode. - while (opModeIsActive() || opModeInInit()) - { - telemetry.addData("preview on/off", "... Camera Stream\n"); - - // Read the current list - List blobs = colorLocator.getBlobs(); - - /* - * The list of Blobs can be filtered to remove unwanted Blobs. - * Note: All contours will be still displayed on the Stream Preview, but only those that satisfy the filter - * conditions will remain in the current list of "blobs". Multiple filters may be used. - * - * Use any of the following filters. - * - * ColorBlobLocatorProcessor.Util.filterByArea(minArea, maxArea, blobs); - * A Blob's area is the number of pixels contained within the Contour. Filter out any that are too big or small. - * Start with a large range and then refine the range based on the likely size of the desired object in the viewfinder. - * - * ColorBlobLocatorProcessor.Util.filterByDensity(minDensity, maxDensity, blobs); - * A blob's density is an indication of how "full" the contour is. - * If you put a rubber band around the contour you would get the "Convex Hull" of the contour. - * The density is the ratio of Contour-area to Convex Hull-area. - * - * ColorBlobLocatorProcessor.Util.filterByAspectRatio(minAspect, maxAspect, blobs); - * A blob's Aspect ratio is the ratio of boxFit long side to short side. - * A perfect Square has an aspect ratio of 1. All others are > 1 - */ - ColorBlobLocatorProcessor.Util.filterByArea(50, 20000, blobs); // filter out very small blobs. - - /* - * The list of Blobs can be sorted using the same Blob attributes as listed above. - * No more than one sort call should be made. Sorting can use ascending or descending order. - * ColorBlobLocatorProcessor.Util.sortByArea(SortOrder.DESCENDING, blobs); // Default - * ColorBlobLocatorProcessor.Util.sortByDensity(SortOrder.DESCENDING, blobs); - * ColorBlobLocatorProcessor.Util.sortByAspectRatio(SortOrder.DESCENDING, blobs); - */ - - telemetry.addLine(" Area Density Aspect Center"); - - // Display the size (area) and center location for each Blob. - for(ColorBlobLocatorProcessor.Blob b : blobs) - { - RotatedRect boxFit = b.getBoxFit(); - telemetry.addLine(String.format("%5d %4.2f %5.2f (%3d,%3d)", - b.getContourArea(), b.getDensity(), b.getAspectRatio(), (int) boxFit.center.x, (int) boxFit.center.y)); - } - - telemetry.update(); - sleep(50); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorSensor.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorSensor.java deleted file mode 100644 index 6be2bc4e..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorSensor.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2024 Phil Malone - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import android.graphics.Color; -import android.util.Size; - -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.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.opencv.ImageRegion; -import org.firstinspires.ftc.vision.opencv.PredominantColorProcessor; - -/* - * This OpMode illustrates how to use a video source (camera) as a color sensor - * - * A "color sensor" will typically determine the color of the object that it is pointed at. - * - * This sample performs the same function, except it uses a video camera to inspect an object or scene. - * The user may choose to inspect all, or just a Region of Interest (ROI), of the active camera view. - * The user must also provide a list of "acceptable colors" (Swatches) from which the closest matching color will be selected. - * - * To perform this function, a VisionPortal runs a PredominantColorProcessor process. - * The PredominantColorProcessor process is created first, and then the VisionPortal is built to use this process. - * The PredominantColorProcessor analyses the ROI and splits the colored pixels into several color-clusters. - * The largest of these clusters is then considered to be the "Predominant Color" - * The process then matches the Predominant Color with the closest Swatch and returns that match. - * - * To aid the user, a colored rectangle is drawn on the camera preview to show the RegionOfInterest, - * The Predominant Color is used to paint the rectangle border, so the user can verify that the color is reasonable. - * - * 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 - */ - -@Disabled -@TeleOp(name = "Concept: Vision Color-Sensor", group = "Concept") -public class ConceptVisionColorSensor extends LinearOpMode -{ - @Override - public void runOpMode() - { - /* Build a "Color Sensor" vision processor based on the PredominantColorProcessor class. - * - * - Focus the color sensor by defining a RegionOfInterest (ROI) which you want to inspect. - * This can be the entire frame, or a sub-region defined using: - * 1) standard image coordinates or 2) a normalized +/- 1.0 coordinate system. - * Use one form of the ImageRegion class to define the ROI. - * ImageRegion.entireFrame() - * ImageRegion.asImageCoordinates(50, 50, 150, 150) 100x100 pixel square near the upper left corner - * ImageRegion.asUnityCenterCoordinates(-0.1, 0.1, 0.1, -0.1) 10% width/height square centered on screen - * - * - Set the list of "acceptable" color swatches (matches). - * Only colors that you assign here will be returned. - * If you know the sensor will be pointing to one of a few specific colors, enter them here. - * Or, if the sensor may be pointed randomly, provide some additional colors that may match the surrounding. - * Possible choices are: - * RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, PURPLE, MAGENTA, BLACK, WHITE; - * - * Note that in the example shown below, only some of the available colors are included. - * This will force any other colored region into one of these colors. - * eg: Green may be reported as YELLOW, as this may be the "closest" match. - */ - PredominantColorProcessor colorSensor = new PredominantColorProcessor.Builder() - .setRoi(ImageRegion.asUnityCenterCoordinates(-0.1, 0.1, 0.1, -0.1)) - .setSwatches( - PredominantColorProcessor.Swatch.RED, - PredominantColorProcessor.Swatch.BLUE, - PredominantColorProcessor.Swatch.YELLOW, - PredominantColorProcessor.Swatch.BLACK, - PredominantColorProcessor.Swatch.WHITE) - .build(); - - /* - * Build a vision portal to run the Color Sensor process. - * - * - Add the colorSensor process created above. - * - Set the desired video resolution. - * Since a high resolution will not improve this process, choose a lower resolution that is - * supported by your camera. This will improve overall performance and reduce latency. - * - Choose your video source. This may be - * .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) ..... for a webcam - * or - * .setCamera(BuiltinCameraDirection.BACK) ... for a Phone Camera - */ - VisionPortal portal = new VisionPortal.Builder() - .addProcessor(colorSensor) - .setCameraResolution(new Size(320, 240)) - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .build(); - - telemetry.setMsTransmissionInterval(50); // Speed up telemetry updates, Just use for debugging. - - // WARNING: To be able to view the stream preview on the Driver Station, this code runs in INIT mode. - while (opModeIsActive() || opModeInInit()) - { - telemetry.addData("DS preview on/off", "3 dots, Camera Stream\n"); - - // Request the most recent color analysis. - // This will return the closest matching colorSwatch and the predominant RGB color. - // Note: to take actions based on the detected color, simply use the colorSwatch in a comparison or switch. - // eg: - // if (result.closestSwatch == PredominantColorProcessor.Swatch.RED) {... some code ...} - PredominantColorProcessor.Result result = colorSensor.getAnalysis(); - - // Display the Color Sensor result. - telemetry.addData("Best Match:", result.closestSwatch); - telemetry.addLine(String.format("R %3d, G %3d, B %3d", Color.red(result.rgb), Color.green(result.rgb), Color.blue(result.rgb))); - telemetry.update(); - - sleep(20); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByEncoder_Linear.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByEncoder_Linear.java deleted file mode 100644 index 63293d0c..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByEncoder_Linear.java +++ /dev/null @@ -1,187 +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.Autonomous; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * This OpMode illustrates the concept of driving a path based on encoder counts. - * The code is structured as a LinearOpMode - * - * The code REQUIRES that you DO have encoders on the wheels, - * otherwise you would use: RobotAutoDriveByTime; - * - * This code ALSO requires that the drive Motors have been configured such that a positive - * power command moves them forward, and causes the encoders to count UP. - * - * The desired path in this example is: - * - Drive forward for 48 inches - * - Spin right for 12 Inches - * - Drive Backward for 24 inches - * - Stop and close the claw. - * - * The code is written using a method called: encoderDrive(speed, leftInches, rightInches, timeoutS) - * that performs the actual movement. - * This method assumes that each movement is relative to the last stopping place. - * There are other ways to perform encoder based moves, but this method is probably the simplest. - * This code uses the RUN_TO_POSITION mode to enable the Motor controllers to generate the run profile - * - * 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="Robot: Auto Drive By Encoder", group="Robot") -@Disabled -public class RobotAutoDriveByEncoder_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - - private ElapsedTime runtime = new ElapsedTime(); - - // Calculate the COUNTS_PER_INCH for your specific drive train. - // Go to your motor vendor website to determine your motor's COUNTS_PER_MOTOR_REV - // For external drive gearing, set DRIVE_GEAR_REDUCTION as needed. - // For example, use a value of 2.0 for a 12-tooth spur gear driving a 24-tooth spur gear. - // This is gearing DOWN for less speed and more torque. - // For gearing UP, use a gear ratio less than 1.0. Note this will affect the direction of wheel rotation. - static final double COUNTS_PER_MOTOR_REV = 1440 ; // eg: TETRIX Motor Encoder - static final double DRIVE_GEAR_REDUCTION = 1.0 ; // No External Gearing. - static final double WHEEL_DIAMETER_INCHES = 4.0 ; // For figuring circumference - static final double COUNTS_PER_INCH = (COUNTS_PER_MOTOR_REV * DRIVE_GEAR_REDUCTION) / - (WHEEL_DIAMETER_INCHES * 3.1415); - static final double DRIVE_SPEED = 0.6; - static final double TURN_SPEED = 0.5; - - @Override - public void runOpMode() { - - // Initialize the drive system variables. - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - leftDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); - rightDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); - - leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Send telemetry message to indicate successful Encoder reset - telemetry.addData("Starting at", "%7d :%7d", - leftDrive.getCurrentPosition(), - rightDrive.getCurrentPosition()); - telemetry.update(); - - // Wait for the game to start (driver presses START) - waitForStart(); - - // Step through each leg of the path, - // Note: Reverse movement is obtained by setting a negative distance (not speed) - encoderDrive(DRIVE_SPEED, 48, 48, 5.0); // S1: Forward 47 Inches with 5 Sec timeout - encoderDrive(TURN_SPEED, 12, -12, 4.0); // S2: Turn Right 12 Inches with 4 Sec timeout - encoderDrive(DRIVE_SPEED, -24, -24, 4.0); // S3: Reverse 24 Inches with 4 Sec timeout - - telemetry.addData("Path", "Complete"); - telemetry.update(); - sleep(1000); // pause to display final telemetry message. - } - - /* - * Method to perform a relative move, based on encoder counts. - * Encoders are not reset as the move is based on the current position. - * Move will stop if any of three conditions occur: - * 1) Move gets to the desired position - * 2) Move runs out of time - * 3) Driver stops the OpMode running. - */ - public void encoderDrive(double speed, - double leftInches, double rightInches, - double timeoutS) { - int newLeftTarget; - int newRightTarget; - - // Ensure that the OpMode is still active - if (opModeIsActive()) { - - // Determine new target position, and pass to motor controller - newLeftTarget = leftDrive.getCurrentPosition() + (int)(leftInches * COUNTS_PER_INCH); - newRightTarget = rightDrive.getCurrentPosition() + (int)(rightInches * COUNTS_PER_INCH); - leftDrive.setTargetPosition(newLeftTarget); - rightDrive.setTargetPosition(newRightTarget); - - // Turn On RUN_TO_POSITION - leftDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION); - rightDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION); - - // reset the timeout time and start motion. - runtime.reset(); - leftDrive.setPower(Math.abs(speed)); - rightDrive.setPower(Math.abs(speed)); - - // keep looping while we are still active, and there is time left, and both motors are running. - // Note: We use (isBusy() && isBusy()) in the loop test, which means that when EITHER motor hits - // its target position, the motion will stop. This is "safer" in the event that the robot will - // always end the motion as soon as possible. - // However, if you require that BOTH motors have finished their moves before the robot continues - // onto the next step, use (isBusy() || isBusy()) in the loop test. - while (opModeIsActive() && - (runtime.seconds() < timeoutS) && - (leftDrive.isBusy() && rightDrive.isBusy())) { - - // Display it for the driver. - telemetry.addData("Running to", " %7d :%7d", newLeftTarget, newRightTarget); - telemetry.addData("Currently at", " at %7d :%7d", - leftDrive.getCurrentPosition(), rightDrive.getCurrentPosition()); - telemetry.update(); - } - - // Stop all motion; - leftDrive.setPower(0); - rightDrive.setPower(0); - - // Turn off RUN_TO_POSITION - leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - sleep(250); // optional pause after each move. - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByGyro_Linear.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByGyro_Linear.java deleted file mode 100644 index ab709344..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByGyro_Linear.java +++ /dev/null @@ -1,429 +0,0 @@ -/* Copyright (c) 2022 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.RevHubOrientationOnRobot; -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.DcMotor; -import com.qualcomm.robotcore.hardware.IMU; -import com.qualcomm.robotcore.util.ElapsedTime; -import com.qualcomm.robotcore.util.Range; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; - -/* - * This OpMode illustrates the concept of driving an autonomous path based on Gyro (IMU) heading and encoder counts. - * The code is structured as a LinearOpMode - * - * The path to be followed by the robot is built from a series of drive, turn or pause steps. - * Each step on the path is defined by a single function call, and these can be strung together in any order. - * - * The code REQUIRES that you have encoders on the drive motors, otherwise you should use: RobotAutoDriveByTime; - * - * This code uses the Universal IMU interface so it will work with either the BNO055, or BHI260 IMU. - * To run as written, the Control/Expansion hub should be mounted horizontally on a flat part of the robot chassis. - * The REV Logo should be facing UP, and the USB port should be facing forward. - * If this is not the configuration of your REV Control Hub, then the code should be modified to reflect the correct orientation. - * - * This sample requires that the drive Motors have been configured with names : left_drive and right_drive. - * It also requires that a positive power command moves both motors forward, and causes the encoders to count UP. - * So please verify that both of your motors move the robot forward on the first move. If not, make the required correction. - * See the beginning of runOpMode() to set the FORWARD/REVERSE option for each motor. - * - * This code uses RUN_TO_POSITION mode for driving straight, and RUN_USING_ENCODER mode for turning and holding. - * Note: This code implements the requirement of calling setTargetPosition() at least once before switching to RUN_TO_POSITION mode. - * - * Notes: - * - * All angles are referenced to the coordinate-frame that is set whenever resetHeading() is called. - * In this sample, the heading is reset when the Start button is touched on the Driver Station. - * Note: It would be possible to reset the heading after each move, but this would accumulate steering errors. - * - * The angle of movement/rotation is assumed to be a standardized rotation around the robot Z axis, - * which means that a Positive rotation is Counter Clockwise, looking down on the field. - * This is consistent with the FTC field coordinate conventions set out in the document: - * https://ftc-docs.firstinspires.org/field-coordinate-system - * - * Control Approach. - * - * To reach, or maintain a required heading, this code implements a basic Proportional Controller where: - * - * Steering power = Heading Error * Proportional Gain. - * - * "Heading Error" is calculated by taking the difference between the desired heading and the actual heading, - * and then "normalizing" it by converting it to a value in the +/- 180 degree range. - * - * "Proportional Gain" is a constant that YOU choose to set the "strength" of the steering response. - * - * Use Android Studio to Copy this Class, and Paste it into your "TeamCode" folder with a new name. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list - */ - -@Autonomous(name="Robot: Auto Drive By Gyro", group="Robot") -@Disabled -public class RobotAutoDriveByGyro_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - private IMU imu = null; // Control/Expansion Hub IMU - - private double headingError = 0; - - // These variable are declared here (as class members) so they can be updated in various methods, - // but still be displayed by sendTelemetry() - private double targetHeading = 0; - private double driveSpeed = 0; - private double turnSpeed = 0; - private double leftSpeed = 0; - private double rightSpeed = 0; - private int leftTarget = 0; - private int rightTarget = 0; - - // Calculate the COUNTS_PER_INCH for your specific drive train. - // Go to your motor vendor website to determine your motor's COUNTS_PER_MOTOR_REV - // For external drive gearing, set DRIVE_GEAR_REDUCTION as needed. - // For example, use a value of 2.0 for a 12-tooth spur gear driving a 24-tooth spur gear. - // This is gearing DOWN for less speed and more torque. - // For gearing UP, use a gear ratio less than 1.0. Note this will affect the direction of wheel rotation. - static final double COUNTS_PER_MOTOR_REV = 537.7 ; // eg: GoBILDA 312 RPM Yellow Jacket - static final double DRIVE_GEAR_REDUCTION = 1.0 ; // No External Gearing. - static final double WHEEL_DIAMETER_INCHES = 4.0 ; // For figuring circumference - static final double COUNTS_PER_INCH = (COUNTS_PER_MOTOR_REV * DRIVE_GEAR_REDUCTION) / - (WHEEL_DIAMETER_INCHES * 3.1415); - - // These constants define the desired driving/control characteristics - // They can/should be tweaked to suit the specific robot drive train. - static final double DRIVE_SPEED = 0.4; // Max driving speed for better distance accuracy. - static final double TURN_SPEED = 0.2; // Max turn speed to limit turn rate. - static final double HEADING_THRESHOLD = 1.0 ; // How close must the heading get to the target before moving to next step. - // Requiring more accuracy (a smaller number) will often make the turn take longer to get into the final position. - // Define the Proportional control coefficient (or GAIN) for "heading control". - // We define one value when Turning (larger errors), and the other is used when Driving straight (smaller errors). - // Increase these numbers if the heading does not correct strongly enough (eg: a heavy robot or using tracks) - // Decrease these numbers if the heading does not settle on the correct value (eg: very agile robot with omni wheels) - static final double P_TURN_GAIN = 0.02; // Larger is more responsive, but also less stable. - static final double P_DRIVE_GAIN = 0.03; // Larger is more responsive, but also less stable. - - - @Override - public void runOpMode() { - - // Initialize the drive system variables. - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - /* The next two lines define Hub orientation. - * The Default Orientation (shown) is when a hub is mounted horizontally with the printed logo pointing UP and the USB port pointing FORWARD. - * - * To Do: EDIT these two lines to match YOUR mounting configuration. - */ - RevHubOrientationOnRobot.LogoFacingDirection logoDirection = RevHubOrientationOnRobot.LogoFacingDirection.UP; - RevHubOrientationOnRobot.UsbFacingDirection usbDirection = RevHubOrientationOnRobot.UsbFacingDirection.FORWARD; - RevHubOrientationOnRobot orientationOnRobot = new RevHubOrientationOnRobot(logoDirection, usbDirection); - - // Now initialize the IMU with this mounting orientation - // This sample expects the IMU to be in a REV Hub and named "imu". - imu = hardwareMap.get(IMU.class, "imu"); - imu.initialize(new IMU.Parameters(orientationOnRobot)); - - // Ensure the robot is stationary. Reset the encoders and set the motors to BRAKE mode - leftDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); - rightDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); - leftDrive.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE); - rightDrive.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE); - - // Wait for the game to start (Display Gyro value while waiting) - while (opModeInInit()) { - telemetry.addData(">", "Robot Heading = %4.0f", getHeading()); - telemetry.update(); - } - - // Set the encoders for closed loop speed control, and reset the heading. - leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - imu.resetYaw(); - - // Step through each leg of the path, - // Notes: Reverse movement is obtained by setting a negative distance (not speed) - // holdHeading() is used after turns to let the heading stabilize - // Add a sleep(2000) after any step to keep the telemetry data visible for review - - driveStraight(DRIVE_SPEED, 24.0, 0.0); // Drive Forward 24" - turnToHeading( TURN_SPEED, -45.0); // Turn CW to -45 Degrees - holdHeading( TURN_SPEED, -45.0, 0.5); // Hold -45 Deg heading for a 1/2 second - - driveStraight(DRIVE_SPEED, 17.0, -45.0); // Drive Forward 17" at -45 degrees (12"x and 12"y) - turnToHeading( TURN_SPEED, 45.0); // Turn CCW to 45 Degrees - holdHeading( TURN_SPEED, 45.0, 0.5); // Hold 45 Deg heading for a 1/2 second - - driveStraight(DRIVE_SPEED, 17.0, 45.0); // Drive Forward 17" at 45 degrees (-12"x and 12"y) - turnToHeading( TURN_SPEED, 0.0); // Turn CW to 0 Degrees - holdHeading( TURN_SPEED, 0.0, 1.0); // Hold 0 Deg heading for 1 second - - driveStraight(DRIVE_SPEED,-48.0, 0.0); // Drive in Reverse 48" (should return to approx. staring position) - - telemetry.addData("Path", "Complete"); - telemetry.update(); - sleep(1000); // Pause to display last telemetry message. - } - - /* - * ==================================================================================================== - * Driving "Helper" functions are below this line. - * These provide the high and low level methods that handle driving straight and turning. - * ==================================================================================================== - */ - - // ********** HIGH Level driving functions. ******************** - - /** - * Drive in a straight line, on a fixed compass heading (angle), based on encoder counts. - * Move will stop if either of these conditions occur: - * 1) Move gets to the desired position - * 2) Driver stops the OpMode running. - * - * @param maxDriveSpeed MAX Speed for forward/rev motion (range 0 to +1.0) . - * @param distance Distance (in inches) to move from current position. Negative distance means move backward. - * @param heading Absolute Heading Angle (in Degrees) relative to last gyro reset. - * 0 = fwd. +ve is CCW from fwd. -ve is CW from forward. - * If a relative angle is required, add/subtract from the current robotHeading. - */ - public void driveStraight(double maxDriveSpeed, - double distance, - double heading) { - - // Ensure that the OpMode is still active - if (opModeIsActive()) { - - // Determine new target position, and pass to motor controller - int moveCounts = (int)(distance * COUNTS_PER_INCH); - leftTarget = leftDrive.getCurrentPosition() + moveCounts; - rightTarget = rightDrive.getCurrentPosition() + moveCounts; - - // Set Target FIRST, then turn on RUN_TO_POSITION - leftDrive.setTargetPosition(leftTarget); - rightDrive.setTargetPosition(rightTarget); - - leftDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION); - rightDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION); - - // Set the required driving speed (must be positive for RUN_TO_POSITION) - // Start driving straight, and then enter the control loop - maxDriveSpeed = Math.abs(maxDriveSpeed); - moveRobot(maxDriveSpeed, 0); - - // keep looping while we are still active, and BOTH motors are running. - while (opModeIsActive() && - (leftDrive.isBusy() && rightDrive.isBusy())) { - - // Determine required steering to keep on heading - turnSpeed = getSteeringCorrection(heading, P_DRIVE_GAIN); - - // if driving in reverse, the motor correction also needs to be reversed - if (distance < 0) - turnSpeed *= -1.0; - - // Apply the turning correction to the current driving speed. - moveRobot(driveSpeed, turnSpeed); - - // Display drive status for the driver. - sendTelemetry(true); - } - - // Stop all motion & Turn off RUN_TO_POSITION - moveRobot(0, 0); - leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - } - } - - /** - * Spin on the central axis to point in a new direction. - *

- * Move will stop if either of these conditions occur: - *

- * 1) Move gets to the heading (angle) - *

- * 2) Driver stops the OpMode running. - * - * @param maxTurnSpeed Desired MAX speed of turn. (range 0 to +1.0) - * @param heading Absolute Heading Angle (in Degrees) relative to last gyro reset. - * 0 = fwd. +ve is CCW from fwd. -ve is CW from forward. - * If a relative angle is required, add/subtract from current heading. - */ - public void turnToHeading(double maxTurnSpeed, double heading) { - - // Run getSteeringCorrection() once to pre-calculate the current error - getSteeringCorrection(heading, P_DRIVE_GAIN); - - // keep looping while we are still active, and not on heading. - while (opModeIsActive() && (Math.abs(headingError) > HEADING_THRESHOLD)) { - - // Determine required steering to keep on heading - turnSpeed = getSteeringCorrection(heading, P_TURN_GAIN); - - // Clip the speed to the maximum permitted value. - turnSpeed = Range.clip(turnSpeed, -maxTurnSpeed, maxTurnSpeed); - - // Pivot in place by applying the turning correction - moveRobot(0, turnSpeed); - - // Display drive status for the driver. - sendTelemetry(false); - } - - // Stop all motion; - moveRobot(0, 0); - } - - /** - * Obtain & hold a heading for a finite amount of time - *

- * Move will stop once the requested time has elapsed - *

- * This function is useful for giving the robot a moment to stabilize its heading between movements. - * - * @param maxTurnSpeed Maximum differential turn speed (range 0 to +1.0) - * @param heading Absolute Heading Angle (in Degrees) relative to last gyro reset. - * 0 = fwd. +ve is CCW from fwd. -ve is CW from forward. - * If a relative angle is required, add/subtract from current heading. - * @param holdTime Length of time (in seconds) to hold the specified heading. - */ - public void holdHeading(double maxTurnSpeed, double heading, double holdTime) { - - ElapsedTime holdTimer = new ElapsedTime(); - holdTimer.reset(); - - // keep looping while we have time remaining. - while (opModeIsActive() && (holdTimer.time() < holdTime)) { - // Determine required steering to keep on heading - turnSpeed = getSteeringCorrection(heading, P_TURN_GAIN); - - // Clip the speed to the maximum permitted value. - turnSpeed = Range.clip(turnSpeed, -maxTurnSpeed, maxTurnSpeed); - - // Pivot in place by applying the turning correction - moveRobot(0, turnSpeed); - - // Display drive status for the driver. - sendTelemetry(false); - } - - // Stop all motion; - moveRobot(0, 0); - } - - // ********** LOW Level driving functions. ******************** - - /** - * Use a Proportional Controller to determine how much steering correction is required. - * - * @param desiredHeading The desired absolute heading (relative to last heading reset) - * @param proportionalGain Gain factor applied to heading error to obtain turning power. - * @return Turning power needed to get to required heading. - */ - public double getSteeringCorrection(double desiredHeading, double proportionalGain) { - targetHeading = desiredHeading; // Save for telemetry - - // Determine the heading current error - headingError = targetHeading - getHeading(); - - // Normalize the error to be within +/- 180 degrees - while (headingError > 180) headingError -= 360; - while (headingError <= -180) headingError += 360; - - // Multiply the error by the gain to determine the required steering correction/ Limit the result to +/- 1.0 - return Range.clip(headingError * proportionalGain, -1, 1); - } - - /** - * Take separate drive (fwd/rev) and turn (right/left) requests, - * combines them, and applies the appropriate speed commands to the left and right wheel motors. - * @param drive forward motor speed - * @param turn clockwise turning motor speed. - */ - public void moveRobot(double drive, double turn) { - driveSpeed = drive; // save this value as a class member so it can be used by telemetry. - turnSpeed = turn; // save this value as a class member so it can be used by telemetry. - - leftSpeed = drive - turn; - rightSpeed = drive + turn; - - // Scale speeds down if either one exceeds +/- 1.0; - double max = Math.max(Math.abs(leftSpeed), Math.abs(rightSpeed)); - if (max > 1.0) - { - leftSpeed /= max; - rightSpeed /= max; - } - - leftDrive.setPower(leftSpeed); - rightDrive.setPower(rightSpeed); - } - - /** - * Display the various control parameters while driving - * - * @param straight Set to true if we are driving straight, and the encoder positions should be included in the telemetry. - */ - private void sendTelemetry(boolean straight) { - - if (straight) { - telemetry.addData("Motion", "Drive Straight"); - telemetry.addData("Target Pos L:R", "%7d:%7d", leftTarget, rightTarget); - telemetry.addData("Actual Pos L:R", "%7d:%7d", leftDrive.getCurrentPosition(), - rightDrive.getCurrentPosition()); - } else { - telemetry.addData("Motion", "Turning"); - } - - telemetry.addData("Heading- Target : Current", "%5.2f : %5.0f", targetHeading, getHeading()); - telemetry.addData("Error : Steer Pwr", "%5.1f : %5.1f", headingError, turnSpeed); - telemetry.addData("Wheel Speeds L : R", "%5.2f : %5.2f", leftSpeed, rightSpeed); - telemetry.update(); - } - - /** - * read the Robot heading directly from the IMU (in degrees) - */ - public double getHeading() { - YawPitchRollAngles orientation = imu.getRobotYawPitchRollAngles(); - return orientation.getYaw(AngleUnit.DEGREES); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByTime_Linear.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByTime_Linear.java deleted file mode 100644 index a7147481..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByTime_Linear.java +++ /dev/null @@ -1,128 +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.Autonomous; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * This OpMode illustrates the concept of driving a path based on time. - * The code is structured as a LinearOpMode - * - * The code assumes that you do NOT have encoders on the wheels, - * otherwise you would use: RobotAutoDriveByEncoder; - * - * The desired path in this example is: - * - Drive forward for 3 seconds - * - Spin right for 1.3 seconds - * - Drive Backward for 1 Second - * - * The code is written in a simple form with no optimizations. - * However, there are several ways that this type of sequence could be streamlined, - * - * 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="Robot: Auto Drive By Time", group="Robot") -@Disabled -public class RobotAutoDriveByTime_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - - private ElapsedTime runtime = new ElapsedTime(); - - - static final double FORWARD_SPEED = 0.6; - static final double TURN_SPEED = 0.5; - - @Override - public void runOpMode() { - - // Initialize the drive system variables. - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // Send telemetry message to signify robot waiting; - telemetry.addData("Status", "Ready to run"); // - telemetry.update(); - - // Wait for the game to start (driver presses START) - waitForStart(); - - // Step through each leg of the path, ensuring that the OpMode has not been stopped along the way. - - // Step 1: Drive forward for 3 seconds - leftDrive.setPower(FORWARD_SPEED); - rightDrive.setPower(FORWARD_SPEED); - runtime.reset(); - while (opModeIsActive() && (runtime.seconds() < 3.0)) { - telemetry.addData("Path", "Leg 1: %4.1f S Elapsed", runtime.seconds()); - telemetry.update(); - } - - // Step 2: Spin right for 1.3 seconds - leftDrive.setPower(TURN_SPEED); - rightDrive.setPower(-TURN_SPEED); - runtime.reset(); - while (opModeIsActive() && (runtime.seconds() < 1.3)) { - telemetry.addData("Path", "Leg 2: %4.1f S Elapsed", runtime.seconds()); - telemetry.update(); - } - - // Step 3: Drive Backward for 1 Second - leftDrive.setPower(-FORWARD_SPEED); - rightDrive.setPower(-FORWARD_SPEED); - runtime.reset(); - while (opModeIsActive() && (runtime.seconds() < 1.0)) { - telemetry.addData("Path", "Leg 3: %4.1f S Elapsed", runtime.seconds()); - telemetry.update(); - } - - // Step 4: Stop - leftDrive.setPower(0); - rightDrive.setPower(0); - - telemetry.addData("Path", "Complete"); - telemetry.update(); - sleep(1000); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagOmni.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagOmni.java deleted file mode 100644 index 9bac0069..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagOmni.java +++ /dev/null @@ -1,321 +0,0 @@ -/* Copyright (c) 2023 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.DcMotor; -import com.qualcomm.robotcore.util.Range; -import org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.ExposureControl; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.GainControl; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -/* - * This OpMode illustrates using a camera to locate and drive towards a specific AprilTag. - * The code assumes a Holonomic (Mecanum or X Drive) Robot. - * - * For an introduction to AprilTags, see the ftc-docs link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the tag, relative to the camera. - * This information is provided in the "ftcPose" member of the returned "detection", and is explained in the ftc-docs page linked below. - * https://ftc-docs.firstinspires.org/apriltag-detection-values - * - * The drive goal is to rotate to keep the Tag centered in the camera, while strafing to be directly in front of the tag, and - * driving towards the tag to achieve the desired distance. - * To reduce any motion blur (which will interrupt the detection process) the Camera exposure is reduced to a very low value (5mS) - * You can determine the best Exposure and Gain values by using the ConceptAprilTagOptimizeExposure OpMode in this Samples folder. - * - * The code assumes a Robot Configuration with motors named: leftfront_drive and rightfront_drive, leftback_drive and rightback_drive. - * The motor directions must be set so a positive power goes forward on all wheels. - * This sample assumes that the current game AprilTag Library (usually for the current season) is being loaded by default, - * so you should choose to approach a valid tag ID. - * - * Under manual control, the left stick will move forward/back & left/right. The right stick will rotate the robot. - * Manually drive the robot until it displays Target data on the Driver Station. - * - * Press and hold the *Left Bumper* to enable the automatic "Drive to target" mode. - * Release the Left Bumper to return to manual driving mode. - * - * Under "Drive To Target" mode, the robot has three goals: - * 1) Turn the robot to always keep the Tag centered on the camera frame. (Use the Target Bearing to turn the robot.) - * 2) Strafe the robot towards the centerline of the Tag, so it approaches directly in front of the tag. (Use the Target Yaw to strafe the robot) - * 3) Drive towards the Tag to get to the desired distance. (Use Tag Range to drive the robot forward/backward) - * - * Use DESIRED_DISTANCE to set how close you want the robot to get to the target. - * Speed and Turn sensitivity can be adjusted using the SPEED_GAIN, STRAFE_GAIN and TURN_GAIN constants. - * - * Use Android Studio to Copy this Class, and Paste it into the TeamCode/src/main/java/org/firstinspires/ftc/teamcode folder. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list. - * - */ - -@TeleOp(name="Omni Drive To AprilTag", group = "Concept") -@Disabled -public class RobotAutoDriveToAprilTagOmni extends LinearOpMode -{ - // Adjust these numbers to suit your robot. - final double DESIRED_DISTANCE = 12.0; // this is how close the camera should get to the target (inches) - - // Set the GAIN constants to control the relationship between the measured position error, and how much power is - // applied to the drive motors to correct the error. - // Drive = Error * Gain Make these values smaller for smoother control, or larger for a more aggressive response. - final double SPEED_GAIN = 0.02 ; // Forward Speed Control "Gain". e.g. Ramp up to 50% power at a 25 inch error. (0.50 / 25.0) - final double STRAFE_GAIN = 0.015 ; // Strafe Speed Control "Gain". e.g. Ramp up to 37% power at a 25 degree Yaw error. (0.375 / 25.0) - final double TURN_GAIN = 0.01 ; // Turn Control "Gain". e.g. Ramp up to 25% power at a 25 degree error. (0.25 / 25.0) - - final double MAX_AUTO_SPEED = 0.5; // Clip the approach speed to this max value (adjust for your robot) - final double MAX_AUTO_STRAFE= 0.5; // Clip the strafing speed to this max value (adjust for your robot) - final double MAX_AUTO_TURN = 0.3; // Clip the turn speed to this max value (adjust for your robot) - - private DcMotor leftFrontDrive = null; // Used to control the left front drive wheel - private DcMotor rightFrontDrive = null; // Used to control the right front drive wheel - private DcMotor leftBackDrive = null; // Used to control the left back drive wheel - private DcMotor rightBackDrive = null; // Used to control the right back drive wheel - - private static final boolean USE_WEBCAM = true; // Set true to use a webcam, or false for a phone camera - private static final int DESIRED_TAG_ID = -1; // Choose the tag you want to approach or set to -1 for ANY tag. - private VisionPortal visionPortal; // Used to manage the video source. - private AprilTagProcessor aprilTag; // Used for managing the AprilTag detection process. - private AprilTagDetection desiredTag = null; // Used to hold the data for a detected AprilTag - - @Override public void runOpMode() - { - boolean targetFound = false; // Set to true when an AprilTag target is detected - double drive = 0; // Desired forward power/speed (-1 to +1) - double strafe = 0; // Desired strafe power/speed (-1 to +1) - double turn = 0; // Desired turning power/speed (-1 to +1) - - // Initialize the Apriltag Detection process - initAprilTag(); - - // Initialize the hardware variables. Note that the strings used here as parameters - // to 'get' must match the names assigned during the robot configuration. - // step (using the FTC Robot Controller app on the phone). - leftFrontDrive = hardwareMap.get(DcMotor.class, "leftfront_drive"); - rightFrontDrive = hardwareMap.get(DcMotor.class, "rightfront_drive"); - leftBackDrive = hardwareMap.get(DcMotor.class, "leftback_drive"); - rightBackDrive = hardwareMap.get(DcMotor.class, "rightback_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftFrontDrive.setDirection(DcMotor.Direction.REVERSE); - leftBackDrive.setDirection(DcMotor.Direction.REVERSE); - rightFrontDrive.setDirection(DcMotor.Direction.FORWARD); - rightBackDrive.setDirection(DcMotor.Direction.FORWARD); - - if (USE_WEBCAM) - setManualExposure(6, 250); // Use low exposure time to reduce motion blur - - // Wait for driver to press start - telemetry.addData("Camera preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) - { - targetFound = false; - desiredTag = null; - - // Step through the list of detected tags and look for a matching tag - List currentDetections = aprilTag.getDetections(); - for (AprilTagDetection detection : currentDetections) { - // Look to see if we have size info on this tag. - if (detection.metadata != null) { - // Check to see if we want to track towards this tag. - if ((DESIRED_TAG_ID < 0) || (detection.id == DESIRED_TAG_ID)) { - // Yes, we want to use this tag. - targetFound = true; - desiredTag = detection; - break; // don't look any further. - } else { - // This tag is in the library, but we do not want to track it right now. - telemetry.addData("Skipping", "Tag ID %d is not desired", detection.id); - } - } else { - // This tag is NOT in the library, so we don't have enough information to track to it. - telemetry.addData("Unknown", "Tag ID %d is not in TagLibrary", detection.id); - } - } - - // Tell the driver what we see, and what to do. - if (targetFound) { - telemetry.addData("\n>","HOLD Left-Bumper to Drive to Target\n"); - telemetry.addData("Found", "ID %d (%s)", desiredTag.id, desiredTag.metadata.name); - telemetry.addData("Range", "%5.1f inches", desiredTag.ftcPose.range); - telemetry.addData("Bearing","%3.0f degrees", desiredTag.ftcPose.bearing); - telemetry.addData("Yaw","%3.0f degrees", desiredTag.ftcPose.yaw); - } else { - telemetry.addData("\n>","Drive using joysticks to find valid target\n"); - } - - // If Left Bumper is being pressed, AND we have found the desired target, Drive to target Automatically . - if (gamepad1.left_bumper && targetFound) { - - // Determine heading, range and Yaw (tag image rotation) error so we can use them to control the robot automatically. - double rangeError = (desiredTag.ftcPose.range - DESIRED_DISTANCE); - double headingError = desiredTag.ftcPose.bearing; - double yawError = desiredTag.ftcPose.yaw; - - // Use the speed and turn "gains" to calculate how we want the robot to move. - drive = Range.clip(rangeError * SPEED_GAIN, -MAX_AUTO_SPEED, MAX_AUTO_SPEED); - turn = Range.clip(headingError * TURN_GAIN, -MAX_AUTO_TURN, MAX_AUTO_TURN) ; - strafe = Range.clip(-yawError * STRAFE_GAIN, -MAX_AUTO_STRAFE, MAX_AUTO_STRAFE); - - telemetry.addData("Auto","Drive %5.2f, Strafe %5.2f, Turn %5.2f ", drive, strafe, turn); - } else { - - // drive using manual POV Joystick mode. Slow things down to make the robot more controlable. - drive = -gamepad1.left_stick_y / 2.0; // Reduce drive rate to 50%. - strafe = -gamepad1.left_stick_x / 2.0; // Reduce strafe rate to 50%. - turn = -gamepad1.right_stick_x / 3.0; // Reduce turn rate to 33%. - telemetry.addData("Manual","Drive %5.2f, Strafe %5.2f, Turn %5.2f ", drive, strafe, turn); - } - telemetry.update(); - - // Apply desired axes motions to the drivetrain. - moveRobot(drive, strafe, turn); - sleep(10); - } - } - - /** - * Move robot according to desired axes motions - *

- * Positive X is forward - *

- * Positive Y is strafe left - *

- * Positive Yaw is counter-clockwise - */ - public void moveRobot(double x, double y, double yaw) { - // Calculate wheel powers. - double leftFrontPower = x -y -yaw; - double rightFrontPower = x +y +yaw; - double leftBackPower = x +y -yaw; - double rightBackPower = x -y +yaw; - - // Normalize wheel powers to be less than 1.0 - double max = Math.max(Math.abs(leftFrontPower), Math.abs(rightFrontPower)); - max = Math.max(max, Math.abs(leftBackPower)); - max = Math.max(max, Math.abs(rightBackPower)); - - if (max > 1.0) { - leftFrontPower /= max; - rightFrontPower /= max; - leftBackPower /= max; - rightBackPower /= max; - } - - // Send powers to the wheels. - leftFrontDrive.setPower(leftFrontPower); - rightFrontDrive.setPower(rightFrontPower); - leftBackDrive.setPower(leftBackPower); - rightBackDrive.setPower(rightBackPower); - } - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - // Create the AprilTag processor by using a builder. - aprilTag = new AprilTagProcessor.Builder().build(); - - // Adjust Image Decimation to trade-off detection-range for detection-rate. - // e.g. Some typical detection data using a Logitech C920 WebCam - // Decimation = 1 .. Detect 2" Tag from 10 feet away at 10 Frames per second - // Decimation = 2 .. Detect 2" Tag from 6 feet away at 22 Frames per second - // Decimation = 3 .. Detect 2" Tag from 4 feet away at 30 Frames Per Second - // Decimation = 3 .. Detect 5" Tag from 10 feet away at 30 Frames Per Second - // Note: Decimation can be changed on-the-fly to adapt during a match. - aprilTag.setDecimation(2); - - // Create the vision portal by using a builder. - if (USE_WEBCAM) { - visionPortal = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .addProcessor(aprilTag) - .build(); - } else { - visionPortal = new VisionPortal.Builder() - .setCamera(BuiltinCameraDirection.BACK) - .addProcessor(aprilTag) - .build(); - } - } - - /* - Manually set the camera gain and exposure. - This can only be called AFTER calling initAprilTag(), and only works for Webcams; - */ - private void setManualExposure(int exposureMS, int gain) { - // Wait for the camera to be open, then use the controls - - if (visionPortal == null) { - return; - } - - // Make sure camera is streaming before we try to set the exposure controls - if (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING) { - telemetry.addData("Camera", "Waiting"); - telemetry.update(); - while (!isStopRequested() && (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING)) { - sleep(20); - } - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - - // Set camera controls unless we are stopping. - if (!isStopRequested()) - { - ExposureControl exposureControl = visionPortal.getCameraControl(ExposureControl.class); - if (exposureControl.getMode() != ExposureControl.Mode.Manual) { - exposureControl.setMode(ExposureControl.Mode.Manual); - sleep(50); - } - exposureControl.setExposure((long)exposureMS, TimeUnit.MILLISECONDS); - sleep(20); - GainControl gainControl = visionPortal.getCameraControl(GainControl.class); - gainControl.setGain(gain); - sleep(20); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagTank.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagTank.java deleted file mode 100644 index ba3eb4f9..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagTank.java +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (c) 2023 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.DcMotor; -import com.qualcomm.robotcore.util.Range; -import org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.ExposureControl; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.GainControl; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -/* - * This OpMode illustrates using a camera to locate and drive towards a specific AprilTag. - * The code assumes a basic two-wheel (Tank) Robot Drivetrain - * - * For an introduction to AprilTags, see the ftc-docs link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the tag, relative to the camera. - * This information is provided in the "ftcPose" member of the returned "detection", and is explained in the ftc-docs page linked below. - * https://ftc-docs.firstinspires.org/apriltag-detection-values - * - * The driving goal is to rotate to keep the tag centered in the camera, while driving towards the tag to achieve the desired distance. - * To reduce any motion blur (which will interrupt the detection process) the Camera exposure is reduced to a very low value (5mS) - * You can determine the best exposure and gain values by using the ConceptAprilTagOptimizeExposure OpMode in this Samples folder. - * - * The code assumes a Robot Configuration with motors named left_drive and right_drive. - * The motor directions must be set so a positive power goes forward on both wheels; - * This sample assumes that the default AprilTag Library (usually for the current season) is being loaded by default - * so you should choose to approach a valid tag ID. - * - * Under manual control, the left stick will move forward/back, and the right stick will rotate the robot. - * This is called POV Joystick mode, different than Tank Drive (where each joystick controls a wheel). - * - * Manually drive the robot until it displays Target data on the Driver Station. - * Press and hold the *Left Bumper* to enable the automatic "Drive to target" mode. - * Release the Left Bumper to return to manual driving mode. - * - * Under "Drive To Target" mode, the robot has two goals: - * 1) Turn the robot to always keep the Tag centered on the camera frame. (Use the Target Bearing to turn the robot.) - * 2) Drive towards the Tag to get to the desired distance. (Use Tag Range to drive the robot forward/backward) - * - * Use DESIRED_DISTANCE to set how close you want the robot to get to the target. - * Speed and Turn sensitivity can be adjusted using the SPEED_GAIN and TURN_GAIN constants. - * - * Use Android Studio to Copy this Class, and Paste it into the TeamCode/src/main/java/org/firstinspires/ftc/teamcode folder. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list. - * - */ - -@TeleOp(name="Tank Drive To AprilTag", group = "Concept") -@Disabled -public class RobotAutoDriveToAprilTagTank extends LinearOpMode -{ - // Adjust these numbers to suit your robot. - final double DESIRED_DISTANCE = 12.0; // this is how close the camera should get to the target (inches) - - // Set the GAIN constants to control the relationship between the measured position error, and how much power is - // applied to the drive motors to correct the error. - // Drive = Error * Gain Make these values smaller for smoother control, or larger for a more aggressive response. - final double SPEED_GAIN = 0.02 ; // Speed Control "Gain". e.g. Ramp up to 50% power at a 25 inch error. (0.50 / 25.0) - final double TURN_GAIN = 0.01 ; // Turn Control "Gain". e.g. Ramp up to 25% power at a 25 degree error. (0.25 / 25.0) - - final double MAX_AUTO_SPEED = 0.5; // Clip the approach speed to this max value (adjust for your robot) - final double MAX_AUTO_TURN = 0.25; // Clip the turn speed to this max value (adjust for your robot) - - private DcMotor leftDrive = null; // Used to control the left drive wheel - private DcMotor rightDrive = null; // Used to control the right drive wheel - - private static final boolean USE_WEBCAM = true; // Set true to use a webcam, or false for a phone camera - private static final int DESIRED_TAG_ID = -1; // Choose the tag you want to approach or set to -1 for ANY tag. - private VisionPortal visionPortal; // Used to manage the video source. - private AprilTagProcessor aprilTag; // Used for managing the AprilTag detection process. - private AprilTagDetection desiredTag = null; // Used to hold the data for a detected AprilTag - - @Override public void runOpMode() - { - boolean targetFound = false; // Set to true when an AprilTag target is detected - double drive = 0; // Desired forward power/speed (-1 to +1) +ve is forward - double turn = 0; // Desired turning power/speed (-1 to +1) +ve is CounterClockwise - - // Initialize the Apriltag Detection process - initAprilTag(); - - // Initialize the hardware variables. Note that the strings used here as parameters - // to 'get' must match the names assigned during the robot configuration. - // step (using the FTC Robot Controller app on the phone). - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Single Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - if (USE_WEBCAM) - setManualExposure(6, 250); // Use low exposure time to reduce motion blur - - // Wait for the driver to press Start - telemetry.addData("Camera preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) - { - targetFound = false; - desiredTag = null; - - // Step through the list of detected tags and look for a matching tag - List currentDetections = aprilTag.getDetections(); - for (AprilTagDetection detection : currentDetections) { - // Look to see if we have size info on this tag. - if (detection.metadata != null) { - // Check to see if we want to track towards this tag. - if ((DESIRED_TAG_ID < 0) || (detection.id == DESIRED_TAG_ID)) { - // Yes, we want to use this tag. - targetFound = true; - desiredTag = detection; - break; // don't look any further. - } else { - // This tag is in the library, but we do not want to track it right now. - telemetry.addData("Skipping", "Tag ID %d is not desired", detection.id); - } - } else { - // This tag is NOT in the library, so we don't have enough information to track to it. - telemetry.addData("Unknown", "Tag ID %d is not in TagLibrary", detection.id); - } - } - - // Tell the driver what we see, and what to do. - if (targetFound) { - telemetry.addData("\n>","HOLD Left-Bumper to Drive to Target\n"); - telemetry.addData("Found", "ID %d (%s)", desiredTag.id, desiredTag.metadata.name); - telemetry.addData("Range", "%5.1f inches", desiredTag.ftcPose.range); - telemetry.addData("Bearing","%3.0f degrees", desiredTag.ftcPose.bearing); - } else { - telemetry.addData("\n>","Drive using joysticks to find valid target\n"); - } - - // If Left Bumper is being pressed, AND we have found the desired target, Drive to target Automatically . - if (gamepad1.left_bumper && targetFound) { - - // Determine heading and range error so we can use them to control the robot automatically. - double rangeError = (desiredTag.ftcPose.range - DESIRED_DISTANCE); - double headingError = desiredTag.ftcPose.bearing; - - // Use the speed and turn "gains" to calculate how we want the robot to move. Clip it to the maximum - drive = Range.clip(rangeError * SPEED_GAIN, -MAX_AUTO_SPEED, MAX_AUTO_SPEED); - turn = Range.clip(headingError * TURN_GAIN, -MAX_AUTO_TURN, MAX_AUTO_TURN) ; - - telemetry.addData("Auto","Drive %5.2f, Turn %5.2f", drive, turn); - } else { - - // drive using manual POV Joystick mode. - drive = -gamepad1.left_stick_y / 2.0; // Reduce drive rate to 50%. - turn = -gamepad1.right_stick_x / 4.0; // Reduce turn rate to 25%. - telemetry.addData("Manual","Drive %5.2f, Turn %5.2f", drive, turn); - } - telemetry.update(); - - // Apply desired axes motions to the drivetrain. - moveRobot(drive, turn); - sleep(10); - } - } - - /** - * Move robot according to desired axes motions - *

- * Positive X is forward - *

- * Positive Yaw is counter-clockwise - */ - public void moveRobot(double x, double yaw) { - // Calculate left and right wheel powers. - double leftPower = x - yaw; - double rightPower = x + yaw; - - // Normalize wheel powers to be less than 1.0 - double max = Math.max(Math.abs(leftPower), Math.abs(rightPower)); - if (max >1.0) { - leftPower /= max; - rightPower /= max; - } - - // Send powers to the wheels. - leftDrive.setPower(leftPower); - rightDrive.setPower(rightPower); - } - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - // Create the AprilTag processor by using a builder. - aprilTag = new AprilTagProcessor.Builder().build(); - - // Adjust Image Decimation to trade-off detection-range for detection-rate. - // e.g. Some typical detection data using a Logitech C920 WebCam - // Decimation = 1 .. Detect 2" Tag from 10 feet away at 10 Frames per second - // Decimation = 2 .. Detect 2" Tag from 6 feet away at 22 Frames per second - // Decimation = 3 .. Detect 2" Tag from 4 feet away at 30 Frames Per Second - // Decimation = 3 .. Detect 5" Tag from 10 feet away at 30 Frames Per Second - // Note: Decimation can be changed on-the-fly to adapt during a match. - aprilTag.setDecimation(2); - - // Create the vision portal by using a builder. - if (USE_WEBCAM) { - visionPortal = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .addProcessor(aprilTag) - .build(); - } else { - visionPortal = new VisionPortal.Builder() - .setCamera(BuiltinCameraDirection.BACK) - .addProcessor(aprilTag) - .build(); - } - } - - /* - Manually set the camera gain and exposure. - This can only be called AFTER calling initAprilTag(), and only works for Webcams; - */ - private void setManualExposure(int exposureMS, int gain) { - // Wait for the camera to be open, then use the controls - - if (visionPortal == null) { - return; - } - - // Make sure camera is streaming before we try to set the exposure controls - if (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING) { - telemetry.addData("Camera", "Waiting"); - telemetry.update(); - while (!isStopRequested() && (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING)) { - sleep(20); - } - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - - // Set camera controls unless we are stopping. - if (!isStopRequested()) - { - ExposureControl exposureControl = visionPortal.getCameraControl(ExposureControl.class); - if (exposureControl.getMode() != ExposureControl.Mode.Manual) { - exposureControl.setMode(ExposureControl.Mode.Manual); - sleep(50); - } - exposureControl.setExposure((long)exposureMS, TimeUnit.MILLISECONDS); - sleep(20); - GainControl gainControl = visionPortal.getCameraControl(GainControl.class); - gainControl.setGain(gain); - sleep(20); - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToLine_Linear.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToLine_Linear.java deleted file mode 100644 index 780f2604..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToLine_Linear.java +++ /dev/null @@ -1,142 +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.Autonomous; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.hardware.NormalizedColorSensor; -import com.qualcomm.robotcore.hardware.NormalizedRGBA; -import com.qualcomm.robotcore.hardware.SwitchableLight; - -/* - * This OpMode illustrates the concept of driving up to a line and then stopping. - * The code is structured as a LinearOpMode - * - * The Sensor used here can be a REV Color Sensor V2 or V3. Make sure the white LED is turned on. - * The sensor can be plugged into any I2C port, and must be named "sensor_color" in the active configuration. - * - * Depending on the height of your color sensor, you may want to set the sensor "gain". - * The higher the gain, the greater the reflected light reading will be. - * Use the SensorColor sample in this folder to determine the minimum gain value that provides an - * "Alpha" reading of 1.0 when you are on top of the white line. In this sample, we use a gain of 15 - * which works well with a Rev V2 color sensor - * - * Setting the correct WHITE_THRESHOLD value is key to stopping correctly. - * This should be set halfway between the bare-tile, and white-line "Alpha" values. - * The reflected light value can be read on the screen once the OpMode has been INIT, but before it is STARTED. - * Move the sensor on and off the white line and note the min and max readings. - * Edit this code to make WHITE_THRESHOLD halfway between the min and max. - * - * 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="Robot: Auto Drive To Line", group="Robot") -@Disabled -public class RobotAutoDriveToLine_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - - /** The variable to store a reference to our color sensor hardware object */ - NormalizedColorSensor colorSensor; - - static final double WHITE_THRESHOLD = 0.5; // spans between 0.0 - 1.0 from dark to light - static final double APPROACH_SPEED = 0.25; - - @Override - public void runOpMode() { - - // Initialize the drive system variables. - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // If there are encoders connected, switch to RUN_USING_ENCODER mode for greater accuracy - // leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - // rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Get a reference to our sensor object. It's recommended to use NormalizedColorSensor over - // ColorSensor, because NormalizedColorSensor consistently gives values between 0 and 1, while - // the values you get from ColorSensor are dependent on the specific sensor you're using. - colorSensor = hardwareMap.get(NormalizedColorSensor.class, "sensor_color"); - - // If necessary, turn ON the white LED (if there is no LED switch on the sensor) - if (colorSensor instanceof SwitchableLight) { - ((SwitchableLight)colorSensor).enableLight(true); - } - - // Some sensors allow you to set your light sensor gain for optimal sensitivity... - // See the SensorColor sample in this folder for how to determine the optimal gain. - // A gain of 15 causes a Rev Color Sensor V2 to produce an Alpha value of 1.0 at about 1.5" above the floor. - colorSensor.setGain(15); - - // Wait for driver to press START) - // Abort this loop is started or stopped. - while (opModeInInit()) { - - // Send telemetry message to signify robot waiting; - telemetry.addData("Status", "Ready to drive to white line."); // - - // Display the light level while we are waiting to start - getBrightness(); - } - - // Start the robot moving forward, and then begin looking for a white line. - leftDrive.setPower(APPROACH_SPEED); - rightDrive.setPower(APPROACH_SPEED); - - // run until the white line is seen OR the driver presses STOP; - while (opModeIsActive() && (getBrightness() < WHITE_THRESHOLD)) { - sleep(5); - } - - // Stop all motors - leftDrive.setPower(0); - rightDrive.setPower(0); - } - - // to obtain reflected light, read the normalized values from the color sensor. Return the Alpha channel. - double getBrightness() { - NormalizedRGBA colors = colorSensor.getNormalizedColors(); - telemetry.addData("Light Level (0 to 1)", "%4.2f", colors.alpha); - telemetry.update(); - - return colors.alpha; - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotHardware.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotHardware.java deleted file mode 100644 index b1c8de62..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotHardware.java +++ /dev/null @@ -1,167 +0,0 @@ -/* Copyright (c) 2022 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.hardware.DcMotor; -import com.qualcomm.robotcore.hardware.Servo; -import com.qualcomm.robotcore.util.Range; - -/* - * This file works in conjunction with the External Hardware Class sample called: ConceptExternalHardwareClass.java - * Please read the explanations in that Sample about how to use this class definition. - * - * This file defines a Java Class that performs all the setup and configuration for a sample robot's hardware (motors and sensors). - * It assumes three motors (left_drive, right_drive and arm) and two servos (left_hand and right_hand) - * - * This one file/class can be used by ALL of your OpModes without having to cut & paste the code each time. - * - * Where possible, the actual hardware objects are "abstracted" (or hidden) so the OpMode code just makes calls into the class, - * rather than accessing the internal hardware directly. This is why the objects are declared "private". - * - * Use Android Studio to Copy this Class, and Paste it into your team's code folder with *exactly the same name*. - * - * Or... In OnBot Java, add a new file named RobotHardware.java, select this sample, and select Not an OpMode. - * Also add a new OpMode, select the sample ConceptExternalHardwareClass.java, and select TeleOp. - * - */ - -public class RobotHardware { - - /* Declare OpMode members. */ - private LinearOpMode myOpMode = null; // gain access to methods in the calling OpMode. - - // Define Motor and Servo objects (Make them private so they can't be accessed externally) - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - private DcMotor armMotor = null; - private Servo leftHand = null; - private Servo rightHand = null; - - // Define Drive constants. Make them public so they CAN be used by the calling OpMode - public static final double MID_SERVO = 0.5 ; - public static final double HAND_SPEED = 0.02 ; // sets rate to move servo - public static final double ARM_UP_POWER = 0.45 ; - public static final double ARM_DOWN_POWER = -0.45 ; - - // Define a constructor that allows the OpMode to pass a reference to itself. - public RobotHardware (LinearOpMode opmode) { - myOpMode = opmode; - } - - /** - * Initialize all the robot's hardware. - * This method must be called ONCE when the OpMode is initialized. - *

- * All of the hardware devices are accessed via the hardware map, and initialized. - */ - public void init() { - // Define and Initialize Motors (note: need to use reference to actual OpMode). - leftDrive = myOpMode.hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = myOpMode.hardwareMap.get(DcMotor.class, "right_drive"); - armMotor = myOpMode.hardwareMap.get(DcMotor.class, "arm"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left stick forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // If there are encoders connected, switch to RUN_USING_ENCODER mode for greater accuracy - // leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - // rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Define and initialize ALL installed servos. - leftHand = myOpMode.hardwareMap.get(Servo.class, "left_hand"); - rightHand = myOpMode.hardwareMap.get(Servo.class, "right_hand"); - leftHand.setPosition(MID_SERVO); - rightHand.setPosition(MID_SERVO); - - myOpMode.telemetry.addData(">", "Hardware Initialized"); - myOpMode.telemetry.update(); - } - - /** - * Calculates the left/right motor powers required to achieve the requested - * robot motions: Drive (Axial motion) and Turn (Yaw motion). - * Then sends these power levels to the motors. - * - * @param Drive Fwd/Rev driving power (-1.0 to 1.0) +ve is forward - * @param Turn Right/Left turning power (-1.0 to 1.0) +ve is CW - */ - public void driveRobot(double Drive, double Turn) { - // Combine drive and turn for blended motion. - double left = Drive + Turn; - double right = Drive - Turn; - - // Scale the values so neither exceed +/- 1.0 - double max = Math.max(Math.abs(left), Math.abs(right)); - if (max > 1.0) - { - left /= max; - right /= max; - } - - // Use existing function to drive both wheels. - setDrivePower(left, right); - } - - /** - * Pass the requested wheel motor powers to the appropriate hardware drive motors. - * - * @param leftWheel Fwd/Rev driving power (-1.0 to 1.0) +ve is forward - * @param rightWheel Fwd/Rev driving power (-1.0 to 1.0) +ve is forward - */ - public void setDrivePower(double leftWheel, double rightWheel) { - // Output the values to the motor drives. - leftDrive.setPower(leftWheel); - rightDrive.setPower(rightWheel); - } - - /** - * Pass the requested arm power to the appropriate hardware drive motor - * - * @param power driving power (-1.0 to 1.0) - */ - public void setArmPower(double power) { - armMotor.setPower(power); - } - - /** - * Send the two hand-servos to opposing (mirrored) positions, based on the passed offset. - * - * @param offset - */ - public void setHandPositions(double offset) { - offset = Range.clip(offset, -0.5, 0.5); - leftHand.setPosition(MID_SERVO + offset); - rightHand.setPosition(MID_SERVO - offset); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopPOV_Linear.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopPOV_Linear.java deleted file mode 100644 index af3840d3..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopPOV_Linear.java +++ /dev/null @@ -1,159 +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.DcMotor; -import com.qualcomm.robotcore.hardware.Servo; -import com.qualcomm.robotcore.util.Range; - -/* - * This OpMode executes a POV Game style Teleop for a direct drive robot - * The code is structured as a LinearOpMode - * - * In this mode the left stick moves the robot FWD and back, the Right stick turns left and right. - * It raises and lowers the arm using the Gamepad Y and A buttons respectively. - * It also opens and closes the claws slowly using the left and right Bumper buttons. - * - * 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="Robot: Teleop POV", group="Robot") -@Disabled -public class RobotTeleopPOV_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - public DcMotor leftDrive = null; - public DcMotor rightDrive = null; - public DcMotor leftArm = null; - public Servo leftClaw = null; - public Servo rightClaw = null; - - double clawOffset = 0; - - public static final double MID_SERVO = 0.5 ; - public static final double CLAW_SPEED = 0.02 ; // sets rate to move servo - public static final double ARM_UP_POWER = 0.45 ; - public static final double ARM_DOWN_POWER = -0.45 ; - - @Override - public void runOpMode() { - double left; - double right; - double drive; - double turn; - double max; - - // Define and Initialize Motors - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - leftArm = hardwareMap.get(DcMotor.class, "left_arm"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left stick forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // If there are encoders connected, switch to RUN_USING_ENCODER mode for greater accuracy - // leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - // rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Define and initialize ALL installed servos. - leftClaw = hardwareMap.get(Servo.class, "left_hand"); - rightClaw = hardwareMap.get(Servo.class, "right_hand"); - leftClaw.setPosition(MID_SERVO); - rightClaw.setPosition(MID_SERVO); - - // Send telemetry message to signify robot waiting; - telemetry.addData(">", "Robot Ready. Press START."); // - telemetry.update(); - - // Wait for the game to start (driver presses START) - waitForStart(); - - // run until the end of the match (driver presses STOP) - while (opModeIsActive()) { - - // Run wheels in POV mode (note: The joystick goes negative when pushed forward, so negate it) - // In this mode the Left stick moves the robot fwd and back, the Right stick turns left and right. - // This way it's also easy to just drive straight, or just turn. - drive = -gamepad1.left_stick_y; - turn = gamepad1.right_stick_x; - - // Combine drive and turn for blended motion. - left = drive + turn; - right = drive - turn; - - // Normalize the values so neither exceed +/- 1.0 - max = Math.max(Math.abs(left), Math.abs(right)); - if (max > 1.0) - { - left /= max; - right /= max; - } - - // Output the safe vales to the motor drives. - leftDrive.setPower(left); - rightDrive.setPower(right); - - // Use gamepad left & right Bumpers to open and close the claw - if (gamepad1.right_bumper) - clawOffset += CLAW_SPEED; - else if (gamepad1.left_bumper) - clawOffset -= CLAW_SPEED; - - // Move both servos to new position. Assume servos are mirror image of each other. - clawOffset = Range.clip(clawOffset, -0.5, 0.5); - leftClaw.setPosition(MID_SERVO + clawOffset); - rightClaw.setPosition(MID_SERVO - clawOffset); - - // Use gamepad buttons to move arm up (Y) and down (A) - if (gamepad1.y) - leftArm.setPower(ARM_UP_POWER); - else if (gamepad1.a) - leftArm.setPower(ARM_DOWN_POWER); - else - leftArm.setPower(0.0); - - // Send telemetry message to signify robot running; - telemetry.addData("claw", "Offset = %.2f", clawOffset); - telemetry.addData("left", "%.2f", left); - telemetry.addData("right", "%.2f", right); - telemetry.update(); - - // Pace this loop so jaw action is reasonable speed. - sleep(50); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopTank_Iterative.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopTank_Iterative.java deleted file mode 100644 index a622f27b..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopTank_Iterative.java +++ /dev/null @@ -1,160 +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.OpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.hardware.Servo; -import com.qualcomm.robotcore.util.Range; - -/* - * This OpMode executes a Tank Drive control TeleOp a direct drive robot - * The code is structured as an Iterative OpMode - * - * In this mode, the left and right joysticks control the left and right motors respectively. - * Pushing a joystick forward will make the attached motor drive forward. - * It raises and lowers the claw using the Gamepad Y and A buttons respectively. - * It also opens and closes the claws slowly using the left and right Bumper buttons. - * - * 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="Robot: Teleop Tank", group="Robot") -@Disabled -public class RobotTeleopTank_Iterative extends OpMode{ - - /* Declare OpMode members. */ - public DcMotor leftDrive = null; - public DcMotor rightDrive = null; - public DcMotor leftArm = null; - public Servo leftClaw = null; - public Servo rightClaw = null; - - double clawOffset = 0; - - public static final double MID_SERVO = 0.5 ; - public static final double CLAW_SPEED = 0.02 ; // sets rate to move servo - public static final double ARM_UP_POWER = 0.50 ; // Run arm motor up at 50% power - public static final double ARM_DOWN_POWER = -0.25 ; // Run arm motor down at -25% power - - /* - * Code to run ONCE when the driver hits INIT - */ - @Override - public void init() { - // Define and Initialize Motors - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - leftArm = hardwareMap.get(DcMotor.class, "left_arm"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left and right sticks forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // If there are encoders connected, switch to RUN_USING_ENCODER mode for greater accuracy - // leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - // rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Define and initialize ALL installed servos. - leftClaw = hardwareMap.get(Servo.class, "left_hand"); - rightClaw = hardwareMap.get(Servo.class, "right_hand"); - leftClaw.setPosition(MID_SERVO); - rightClaw.setPosition(MID_SERVO); - - // Send telemetry message to signify robot waiting; - telemetry.addData(">", "Robot Ready. Press START."); // - } - - /* - * Code to run REPEATEDLY after the driver hits INIT, but before they hit START - */ - @Override - public void init_loop() { - } - - /* - * Code to run ONCE when the driver hits START - */ - @Override - public void start() { - } - - /* - * Code to run REPEATEDLY after the driver hits START but before they hit STOP - */ - @Override - public void loop() { - double left; - double right; - - // Run wheels in tank mode (note: The joystick goes negative when pushed forward, so negate it) - left = -gamepad1.left_stick_y; - right = -gamepad1.right_stick_y; - - leftDrive.setPower(left); - rightDrive.setPower(right); - - // Use gamepad left & right Bumpers to open and close the claw - if (gamepad1.right_bumper) - clawOffset += CLAW_SPEED; - else if (gamepad1.left_bumper) - clawOffset -= CLAW_SPEED; - - // Move both servos to new position. Assume servos are mirror image of each other. - clawOffset = Range.clip(clawOffset, -0.5, 0.5); - leftClaw.setPosition(MID_SERVO + clawOffset); - rightClaw.setPosition(MID_SERVO - clawOffset); - - // Use gamepad buttons to move the arm up (Y) and down (A) - if (gamepad1.y) - leftArm.setPower(ARM_UP_POWER); - else if (gamepad1.a) - leftArm.setPower(ARM_DOWN_POWER); - else - leftArm.setPower(0.0); - - // Send telemetry message to signify robot running; - telemetry.addData("claw", "Offset = %.2f", clawOffset); - telemetry.addData("left", "%.2f", left); - telemetry.addData("right", "%.2f", right); - } - - /* - * Code to run ONCE after the driver hits STOP - */ - @Override - public void stop() { - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SampleRevBlinkinLedDriver.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SampleRevBlinkinLedDriver.java deleted file mode 100644 index bcf5b80e..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SampleRevBlinkinLedDriver.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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; - -/* - * This OpMode demonstrates use of the 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/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java deleted file mode 100644 index 405da1e9..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java +++ /dev/null @@ -1,186 +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.bosch.BNO055IMU; -import com.qualcomm.hardware.bosch.JustLoggingAccelerationIntegrator; -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; -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.Position; -import org.firstinspires.ftc.robotcore.external.navigation.Velocity; - -import java.util.Locale; - -/* - * This OpMode gives a short demo on how to use the BNO055 Inertial Motion Unit (IMU) from AdaFruit. - * - * Note: this is a Legacy example that will not work with newer Control/Expansion Hubs that use a different IMU - * Please use the new SensorIMUOrthogonal or SensorIMUNonOrthogonal samples for a more universal IMU interface. - * - * 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 Adafruit IMU - */ -@TeleOp(name = "Sensor: BNO055 IMU", group = "Sensor") -@Disabled // Comment this out to add to the OpMode list -public class SensorBNO055IMU extends LinearOpMode - { - //---------------------------------------------------------------------------------------------- - // State - //---------------------------------------------------------------------------------------------- - - // The IMU sensor object - BNO055IMU imu; - - // State used for updating telemetry - Orientation angles; - Acceleration gravity; - - //---------------------------------------------------------------------------------------------- - // Main logic - //---------------------------------------------------------------------------------------------- - - @Override public void runOpMode() { - - // Set up the parameters with which we will use our IMU. Note that integration - // algorithm here just reports accelerations to the logcat log; it doesn't actually - // provide positional information. - BNO055IMU.Parameters parameters = new BNO055IMU.Parameters(); - parameters.angleUnit = BNO055IMU.AngleUnit.DEGREES; - parameters.accelUnit = BNO055IMU.AccelUnit.METERS_PERSEC_PERSEC; - parameters.calibrationDataFile = "BNO055IMUCalibration.json"; // see the calibration sample OpMode - parameters.loggingEnabled = true; - parameters.loggingTag = "IMU"; - parameters.accelerationIntegrationAlgorithm = new JustLoggingAccelerationIntegrator(); - - // Retrieve and initialize the IMU. We expect the IMU to be attached to an I2C port - // on a Core Device Interface Module, configured to be a sensor of type "AdaFruit IMU", - // and named "imu". - imu = hardwareMap.get(BNO055IMU.class, "imu"); - imu.initialize(parameters); - - // Set up our telemetry dashboard - composeTelemetry(); - - // Wait until we're told to go - waitForStart(); - - // Start the logging of measured acceleration - imu.startAccelerationIntegration(new Position(), new Velocity(), 1000); - - // Loop and update the dashboard - while (opModeIsActive()) { - telemetry.update(); - } - } - - //---------------------------------------------------------------------------------------------- - // Telemetry Configuration - //---------------------------------------------------------------------------------------------- - - void composeTelemetry() { - - // At the beginning of each telemetry update, grab a bunch of data - // from the IMU that we will then display in separate lines. - telemetry.addAction(new Runnable() { @Override public void run() - { - // Acquiring the angles is relatively expensive; we don't want - // to do that in each of the three items that need that info, as that's - // three times the necessary expense. - angles = imu.getAngularOrientation(AxesReference.INTRINSIC, AxesOrder.ZYX, AngleUnit.DEGREES); - gravity = imu.getGravity(); - } - }); - - telemetry.addLine() - .addData("status", new Func() { - @Override public String value() { - return imu.getSystemStatus().toShortString(); - } - }) - .addData("calib", new Func() { - @Override public String value() { - return imu.getCalibrationStatus().toString(); - } - }); - - telemetry.addLine() - .addData("heading", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.firstAngle); - } - }) - .addData("roll", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.secondAngle); - } - }) - .addData("pitch", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.thirdAngle); - } - }); - - telemetry.addLine() - .addData("grvty", new Func() { - @Override public String value() { - return gravity.toString(); - } - }) - .addData("mag", new Func() { - @Override public String value() { - return String.format(Locale.getDefault(), "%.3f", - Math.sqrt(gravity.xAccel*gravity.xAccel - + gravity.yAccel*gravity.yAccel - + gravity.zAccel*gravity.zAccel)); - } - }); - } - - //---------------------------------------------------------------------------------------------- - // Formatting - //---------------------------------------------------------------------------------------------- - - String formatAngle(AngleUnit angleUnit, double angle) { - return formatDegrees(AngleUnit.DEGREES.fromUnit(angleUnit, angle)); - } - - String formatDegrees(double degrees){ - return String.format(Locale.getDefault(), "%.1f", AngleUnit.DEGREES.normalize(degrees)); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMUCalibration.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMUCalibration.java deleted file mode 100644 index 93f1789d..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMUCalibration.java +++ /dev/null @@ -1,230 +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.bosch.BNO055IMU; -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.ReadWriteFile; -import org.firstinspires.ftc.robotcore.external.Func; -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.internal.system.AppUtil; - -import java.io.File; -import java.util.Locale; - -/* - * This OpMode calibrates a BNO055 IMU per - * "Section 3.11 Calibration" of the BNO055 specification. - * - * Note: this is a Legacy example that will not work with newer Control/Expansion Hubs that use a different IMU - * Please use the new SensorIMUOrthogonal or SensorIMUNonOrthogonal samples for a more universal IMU interface. - * - * Manual calibration of the IMU is definitely NOT necessary: except for the magnetometer (which is not used by the - * default "IMU" SensorMode), the BNO055 is internally self-calibrating and thus can be very successfully used without - * manual intervention. That said, performing a one-time calibration, saving the results persistently, then loading them - * again at each run can help reduce the time that automatic calibration requires. - * - * This summary of the calibration process from Intel is informative: - * http://iotdk.intel.com/docs/master/upm/classupm_1_1_b_n_o055.html - * - * "This device requires calibration in order to operate accurately. [...] Calibration data is - * lost on a power cycle. See one of the examples for a description of how to calibrate the device, - * but in essence: - * - * There is a calibration status register available [...] that returns the calibration status - * of the accelerometer (ACC), magnetometer (MAG), gyroscope (GYR), and overall system (SYS). - * Each of these values range from 0 (uncalibrated) to 3 (fully calibrated). Calibration [ideally] - * involves certain motions to get all 4 values at 3. The motions are as follows (though see the - * datasheet for more information): - * - * 1. GYR: Simply let the sensor sit flat for a few seconds. - * 2. ACC: Move the sensor in various positions. Start flat, then rotate slowly by 45 - * degrees, hold for a few seconds, then continue rotating another 45 degrees and - * hold, etc. 6 or more movements of this type may be required. You can move through - * any axis you desire, but make sure that the device is lying at least once - * perpendicular to the x, y, and z axis. - * 3. MAG: Move slowly in a figure 8 pattern in the air, until the calibration values reaches 3. - * 4. SYS: This will usually reach 3 when the other items have also reached 3. If not, continue - * slowly moving the device though various axes until it does." - * - * To calibrate the IMU, run this sample OpMode with a gamepad attached to the driver station. - * Once the IMU has reached sufficient calibration as reported on telemetry, press the 'A' - * button on the gamepad to write the calibration to a file. That file can then be indicated - * later when running an OpMode which uses the IMU. - * - * Note: if your intended uses of the IMU do not include use of all its sensors (for example, - * you might not use the magnetometer), then it makes little sense for you to wait for full - * calibration of the sensors you are not using before saving the calibration data. Indeed, - * it appears that in a SensorMode that doesn't use the magnetometer (for example), the - * magnetometer cannot actually be calibrated. - * - * References: - * The AdafruitBNO055IMU Javadoc - * The BNO055IMU.Parameters.calibrationDataFile Javadoc - * The BNO055 product page: https://www.bosch-sensortec.com/bst/products/all_products/bno055 - * The BNO055 datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bno055-ds000.pdf - */ -@TeleOp(name = "Sensor: BNO055 IMU Calibration", group = "Sensor") -@Disabled // Uncomment this to add to the OpMode list -public class SensorBNO055IMUCalibration extends LinearOpMode - { - //---------------------------------------------------------------------------------------------- - // State - //---------------------------------------------------------------------------------------------- - - // Our sensors, motors, and other devices go here, along with other long term state - BNO055IMU imu; - - // State used for updating telemetry - Orientation angles; - - //---------------------------------------------------------------------------------------------- - // Main logic - //---------------------------------------------------------------------------------------------- - - @Override public void runOpMode() { - - telemetry.log().setCapacity(12); - telemetry.log().add(""); - telemetry.log().add("Please refer to the calibration instructions"); - telemetry.log().add("contained in the Adafruit IMU calibration"); - telemetry.log().add("sample OpMode."); - telemetry.log().add(""); - telemetry.log().add("When sufficient calibration has been reached,"); - telemetry.log().add("press the 'A' button to write the current"); - telemetry.log().add("calibration data to a file."); - telemetry.log().add(""); - - // We are expecting the IMU to be attached to an I2C port on a Core Device Interface Module and named "imu". - BNO055IMU.Parameters parameters = new BNO055IMU.Parameters(); - parameters.loggingEnabled = true; - parameters.loggingTag = "IMU"; - imu = hardwareMap.get(BNO055IMU.class, "imu"); - imu.initialize(parameters); - - composeTelemetry(); - telemetry.log().add("Waiting for start..."); - - // Wait until we're told to go - while (!isStarted()) { - telemetry.update(); - idle(); - } - - telemetry.log().add("...started..."); - - while (opModeIsActive()) { - - if (gamepad1.a) { - - // Get the calibration data - BNO055IMU.CalibrationData calibrationData = imu.readCalibrationData(); - - // Save the calibration data to a file. You can choose whatever file - // name you wish here, but you'll want to indicate the same file name - // when you initialize the IMU in an OpMode in which it is used. If you - // have more than one IMU on your robot, you'll of course want to use - // different configuration file names for each. - String filename = "AdafruitIMUCalibration.json"; - File file = AppUtil.getInstance().getSettingsFile(filename); - ReadWriteFile.writeFile(file, calibrationData.serialize()); - telemetry.log().add("saved to '%s'", filename); - - // Wait for the button to be released - while (gamepad1.a) { - telemetry.update(); - idle(); - } - } - - telemetry.update(); - } - } - - void composeTelemetry() { - - // At the beginning of each telemetry update, grab a bunch of data - // from the IMU that we will then display in separate lines. - telemetry.addAction(new Runnable() { @Override public void run() - { - // Acquiring the angles is relatively expensive; we don't want - // to do that in each of the three items that need that info, as that's - // three times the necessary expense. - angles = imu.getAngularOrientation(AxesReference.INTRINSIC, AxesOrder.ZYX, AngleUnit.DEGREES); - } - }); - - telemetry.addLine() - .addData("status", new Func() { - @Override public String value() { - return imu.getSystemStatus().toShortString(); - } - }) - .addData("calib", new Func() { - @Override public String value() { - return imu.getCalibrationStatus().toString(); - } - }); - - telemetry.addLine() - .addData("heading", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.firstAngle); - } - }) - .addData("roll", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.secondAngle); - } - }) - .addData("pitch", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.thirdAngle); - } - }); - } - - //---------------------------------------------------------------------------------------------- - // Formatting - //---------------------------------------------------------------------------------------------- - - String formatAngle(AngleUnit angleUnit, double angle) { - return formatDegrees(AngleUnit.DEGREES.fromUnit(angleUnit, angle)); - } - - String formatDegrees(double degrees){ - return String.format(Locale.getDefault(), "%.1f", AngleUnit.DEGREES.normalize(degrees)); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java deleted file mode 100644 index 7546c9de..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright (c) 2017-2020 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.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.DistanceSensor; -import com.qualcomm.robotcore.hardware.NormalizedColorSensor; -import com.qualcomm.robotcore.hardware.NormalizedRGBA; -import com.qualcomm.robotcore.hardware.SwitchableLight; -import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; - -/* - * This OpMode shows how to use a color sensor in a generic - * way, regardless of which particular make or model of color sensor is used. The OpMode - * assumes that the color sensor is configured with a name of "sensor_color". - * - * There will be some variation in the values measured depending on the specific sensor you are using. - * - * You can increase the gain (a multiplier to make the sensor report higher values) by holding down - * the A button on the gamepad, and decrease the gain by holding down the B button on the gamepad. - * - * If the color sensor has a light which is controllable from software, you can use the X button on - * the gamepad to toggle the light on and off. The REV sensors don't support this, but instead have - * a physical switch on them to turn the light on and off, beginning with REV Color Sensor V2. - * - * If the color sensor also supports short-range distance measurements (usually via an infrared - * proximity sensor), the reported distance will be written to telemetry. As of September 2020, - * the only color sensors that support this are the ones from REV Robotics. These infrared proximity - * sensor measurements are only useful at very small distances, and are sensitive to ambient light - * and surface reflectivity. You should use a different sensor if you need precise distance measurements. - * - * 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: Color", group = "Sensor") -@Disabled -public class SensorColor extends LinearOpMode { - - /** The colorSensor field will contain a reference to our color sensor hardware object */ - NormalizedColorSensor colorSensor; - - /** The relativeLayout field is used to aid in providing interesting visual feedback - * in this sample application; you probably *don't* need this when you use a color sensor on your - * robot. Note that you won't see anything change on the Driver Station, only on the Robot Controller. */ - View relativeLayout; - - /* - * The runOpMode() method is the root of this OpMode, as it is in all LinearOpModes. - * Our implementation here, though is a bit unusual: we've decided to put all the actual work - * in the runSample() method rather than directly in runOpMode() itself. The reason we do that is - * that in this sample we're changing the background color of the robot controller screen as the - * OpMode runs, and we want to be able to *guarantee* that we restore it to something reasonable - * and palatable when the OpMode ends. The simplest way to do that is to use a try...finally - * block around the main, core logic, and an easy way to make that all clear was to separate - * the former from the latter in separate methods. - */ - @Override public void runOpMode() { - - // Get a reference to the RelativeLayout so we can later 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()); - relativeLayout = ((Activity) hardwareMap.appContext).findViewById(relativeLayoutId); - - try { - runSample(); // actually execute the sample - } finally { - // On the way out, *guarantee* that the background is reasonable. It doesn't actually start off - // as pure white, but it's too much work to dig out what actually was used, and this is good - // enough to at least make the screen reasonable again. - // Set the panel back to the default color - relativeLayout.post(new Runnable() { - public void run() { - relativeLayout.setBackgroundColor(Color.WHITE); - } - }); - } - } - - protected void runSample() { - // You can give the sensor a gain value, will be multiplied by the sensor's raw value before the - // normalized color values are calculated. Color sensors (especially the REV Color Sensor V3) - // can give very low values (depending on the lighting conditions), which only use a small part - // of the 0-1 range that is available for the red, green, and blue values. In brighter conditions, - // you should use a smaller gain than in dark conditions. If your gain is too high, all of the - // colors will report at or near 1, and you won't be able to determine what color you are - // actually looking at. For this reason, it's better to err on the side of a lower gain - // (but always greater than or equal to 1). - float gain = 2; - - // Once per loop, we will update this hsvValues array. The first element (0) will contain the - // hue, the second element (1) will contain the saturation, and the third element (2) will - // contain the value. See http://web.archive.org/web/20190311170843/https://infohost.nmt.edu/tcc/help/pubs/colortheory/web/hsv.html - // for an explanation of HSV color. - final float[] hsvValues = new float[3]; - - // xButtonPreviouslyPressed and xButtonCurrentlyPressed keep track of the previous and current - // state of the X button on the gamepad - boolean xButtonPreviouslyPressed = false; - boolean xButtonCurrentlyPressed = false; - - // Get a reference to our sensor object. It's recommended to use NormalizedColorSensor over - // ColorSensor, because NormalizedColorSensor consistently gives values between 0 and 1, while - // the values you get from ColorSensor are dependent on the specific sensor you're using. - colorSensor = hardwareMap.get(NormalizedColorSensor.class, "sensor_color"); - - // If possible, turn the light on in the beginning (it might already be on anyway, - // we just make sure it is if we can). - if (colorSensor instanceof SwitchableLight) { - ((SwitchableLight)colorSensor).enableLight(true); - } - - // Wait for the start button to be pressed. - waitForStart(); - - // Loop until we are asked to stop - while (opModeIsActive()) { - // Explain basic gain information via telemetry - telemetry.addLine("Hold the A button on gamepad 1 to increase gain, or B to decrease it.\n"); - telemetry.addLine("Higher gain values mean that the sensor will report larger numbers for Red, Green, and Blue, and Value\n"); - - // Update the gain value if either of the A or B gamepad buttons is being held - if (gamepad1.a) { - // Only increase the gain by a small amount, since this loop will occur multiple times per second. - gain += 0.005; - } else if (gamepad1.b && gain > 1) { // A gain of less than 1 will make the values smaller, which is not helpful. - gain -= 0.005; - } - - // Show the gain value via telemetry - telemetry.addData("Gain", gain); - - // Tell the sensor our desired gain value (normally you would do this during initialization, - // not during the loop) - colorSensor.setGain(gain); - - // Check the status of the X button on the gamepad - xButtonCurrentlyPressed = gamepad1.x; - - // If the button state is different than what it was, then act - if (xButtonCurrentlyPressed != xButtonPreviouslyPressed) { - // If the button is (now) down, then toggle the light - if (xButtonCurrentlyPressed) { - if (colorSensor instanceof SwitchableLight) { - SwitchableLight light = (SwitchableLight)colorSensor; - light.enableLight(!light.isLightOn()); - } - } - } - xButtonPreviouslyPressed = xButtonCurrentlyPressed; - - // Get the normalized colors from the sensor - NormalizedRGBA colors = colorSensor.getNormalizedColors(); - - /* Use telemetry to display feedback on the driver station. We show the red, green, and blue - * normalized values from the sensor (in the range of 0 to 1), as well as the equivalent - * HSV (hue, saturation and value) values. See http://web.archive.org/web/20190311170843/https://infohost.nmt.edu/tcc/help/pubs/colortheory/web/hsv.html - * for an explanation of HSV color. */ - - // Update the hsvValues array by passing it to Color.colorToHSV() - Color.colorToHSV(colors.toColor(), hsvValues); - - telemetry.addLine() - .addData("Red", "%.3f", colors.red) - .addData("Green", "%.3f", colors.green) - .addData("Blue", "%.3f", colors.blue); - telemetry.addLine() - .addData("Hue", "%.3f", hsvValues[0]) - .addData("Saturation", "%.3f", hsvValues[1]) - .addData("Value", "%.3f", hsvValues[2]); - telemetry.addData("Alpha", "%.3f", colors.alpha); - - /* If this color sensor also has a distance sensor, display the measured distance. - * Note that the reported distance is only useful at very close range, and is impacted by - * ambient light and surface reflectivity. */ - if (colorSensor instanceof DistanceSensor) { - telemetry.addData("Distance (cm)", "%.3f", ((DistanceSensor) colorSensor).getDistance(DistanceUnit.CM)); - } - - telemetry.update(); - - // Change the Robot Controller's background color to match the color detected by the color sensor. - relativeLayout.post(new Runnable() { - public void run() { - relativeLayout.setBackgroundColor(Color.HSVToColor(hsvValues)); - } - }); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java deleted file mode 100644 index 44c3ca9c..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2024 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.DigitalChannel; - -/* - * This OpMode demonstrates how to use a digital channel. - * - * The OpMode assumes that the digital channel is configured with a name of "digitalTouch". - * - * 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: digital channel", group = "Sensor") -@Disabled -public class SensorDigitalTouch extends LinearOpMode { - DigitalChannel digitalTouch; // Digital channel Object - - @Override - public void runOpMode() { - - // get a reference to our touchSensor object. - digitalTouch = hardwareMap.get(DigitalChannel.class, "digitalTouch"); - - digitalTouch.setMode(DigitalChannel.Mode.INPUT); - telemetry.addData("DigitalTouchSensorExample", "Press start to continue..."); - telemetry.update(); - - // wait for the start button to be pressed. - waitForStart(); - - // while the OpMode is active, loop and read the digital channel. - // Note we use opModeIsActive() as our loop condition because it is an interruptible method. - while (opModeIsActive()) { - - // button is pressed if value returned is LOW or false. - // send the info back to driver station using telemetry function. - if (digitalTouch.getState() == false) { - telemetry.addData("Button", "PRESSED"); - } else { - telemetry.addData("Button", "NOT PRESSED"); - } - - telemetry.update(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHuskyLens.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHuskyLens.java deleted file mode 100644 index af7ca552..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHuskyLens.java +++ /dev/null @@ -1,160 +0,0 @@ -/* -Copyright (c) 2023 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.dfrobot.HuskyLens; -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.internal.system.Deadline; - -import java.util.concurrent.TimeUnit; - -/* - * This OpMode illustrates how to use the DFRobot HuskyLens. - * - * The HuskyLens is a Vision Sensor with a built-in object detection model. It can - * detect a number of predefined objects and AprilTags in the 36h11 family, can - * recognize colors, and can be trained to detect custom objects. See this website for - * documentation: https://wiki.dfrobot.com/HUSKYLENS_V1.0_SKU_SEN0305_SEN0336 - * - * For detailed instructions on how a HuskyLens is used in FTC, please see this tutorial: - * https://ftc-docs.firstinspires.org/en/latest/devices/huskylens/huskylens.html - * - * This sample illustrates how to detect AprilTags, but can be used to detect other types - * of objects by changing the algorithm. It assumes that the HuskyLens is configured with - * a name of "huskylens". - * - * 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: HuskyLens", group = "Sensor") -@Disabled -public class SensorHuskyLens extends LinearOpMode { - - private final int READ_PERIOD = 1; - - private HuskyLens huskyLens; - - @Override - public void runOpMode() - { - huskyLens = hardwareMap.get(HuskyLens.class, "huskylens"); - - /* - * This sample rate limits the reads solely to allow a user time to observe - * what is happening on the Driver Station telemetry. Typical applications - * would not likely rate limit. - */ - Deadline rateLimit = new Deadline(READ_PERIOD, TimeUnit.SECONDS); - - /* - * Immediately expire so that the first time through we'll do the read. - */ - rateLimit.expire(); - - /* - * Basic check to see if the device is alive and communicating. This is not - * technically necessary here as the HuskyLens class does this in its - * doInitialization() method which is called when the device is pulled out of - * the hardware map. However, sometimes it's unclear why a device reports as - * failing on initialization. In the case of this device, it's because the - * call to knock() failed. - */ - if (!huskyLens.knock()) { - telemetry.addData(">>", "Problem communicating with " + huskyLens.getDeviceName()); - } else { - telemetry.addData(">>", "Press start to continue"); - } - - /* - * The device uses the concept of an algorithm to determine what types of - * objects it will look for and/or what mode it is in. The algorithm may be - * selected using the scroll wheel on the device, or via software as shown in - * the call to selectAlgorithm(). - * - * The SDK itself does not assume that the user wants a particular algorithm on - * startup, and hence does not set an algorithm. - * - * Users, should, in general, explicitly choose the algorithm they want to use - * within the OpMode by calling selectAlgorithm() and passing it one of the values - * found in the enumeration HuskyLens.Algorithm. - * - * Other algorithm choices for FTC might be: OBJECT_RECOGNITION, COLOR_RECOGNITION or OBJECT_CLASSIFICATION. - */ - huskyLens.selectAlgorithm(HuskyLens.Algorithm.TAG_RECOGNITION); - - telemetry.update(); - waitForStart(); - - /* - * Looking for AprilTags per the call to selectAlgorithm() above. A handy grid - * for testing may be found at https://wiki.dfrobot.com/HUSKYLENS_V1.0_SKU_SEN0305_SEN0336#target_20. - * - * Note again that the device only recognizes the 36h11 family of tags out of the box. - */ - while(opModeIsActive()) { - if (!rateLimit.hasExpired()) { - continue; - } - rateLimit.reset(); - - /* - * All algorithms, except for LINE_TRACKING, return a list of Blocks where a - * Block represents the outline of a recognized object along with its ID number. - * ID numbers allow you to identify what the device saw. See the HuskyLens documentation - * referenced in the header comment above for more information on IDs and how to - * assign them to objects. - * - * Returns an empty array if no objects are seen. - */ - HuskyLens.Block[] blocks = huskyLens.blocks(); - telemetry.addData("Block count", blocks.length); - for (int i = 0; i < blocks.length; i++) { - telemetry.addData("Block", blocks[i].toString()); - /* - * Here inside the FOR loop, you could save or evaluate specific info for the currently recognized Bounding Box: - * - blocks[i].width and blocks[i].height (size of box, in pixels) - * - blocks[i].left and blocks[i].top (edges of box) - * - blocks[i].x and blocks[i].y (center location) - * - blocks[i].id (Color ID) - * - * These values have Java type int (integer). - */ - } - - telemetry.update(); - } - } -} \ No newline at end of file diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUNonOrthogonal.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUNonOrthogonal.java deleted file mode 100644 index 70bc8d4a..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUNonOrthogonal.java +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright (c) 2022 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.RevHubOrientationOnRobot; -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.IMU; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.Orientation; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; - -import static com.qualcomm.hardware.rev.RevHubOrientationOnRobot.xyzOrientation; - -/* - * This OpMode shows how to use the new universal IMU interface. This - * interface may be used with the BNO055 IMU or the BHI260 IMU. It assumes that an IMU is configured - * on the robot with the name "imu". - * - * The sample will display the current Yaw, Pitch and Roll of the robot.
- * With the correct orientation parameters selected, pitch/roll/yaw should act as follows: - * Pitch value should INCREASE as the robot is tipped UP at the front. (Rotation about X) - * Roll value should INCREASE as the robot is tipped UP at the left side. (Rotation about Y) - * Yaw value should INCREASE as the robot is rotated Counter Clockwise. (Rotation about Z) - * - * The yaw can be reset (to zero) by pressing the Y button on the gamepad (Triangle on a PS4 controller) - * - * This specific sample DOES NOT assume that the Hub is mounted on one of the three orthogonal - * planes (X/Y, X/Z or Y/Z) OR that the Hub has only been rotated in a range of 90 degree increments. - * - * Note: if your Hub is mounted Orthogonally (on a orthogonal surface, angled at some multiple of - * 90 Degrees) then you should use the simpler SensorIMUOrthogonal sample in this folder. - * - * But... If your Hub is mounted Non-Orthogonally, you must specify one or more rotational angles - * that transform a "Default" Hub orientation into your desired orientation. That is what is - * illustrated here. - * - * 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. - * - * Finally, edit this OpMode to use at least one angle around an axis to orient your Hub. - */ -@TeleOp(name = "Sensor: IMU Non-Orthogonal", group = "Sensor") -@Disabled // Comment this out to add to the OpMode list -public class SensorIMUNonOrthogonal extends LinearOpMode -{ - // The IMU sensor object - IMU imu; - - //---------------------------------------------------------------------------------------------- - // Main logic - //---------------------------------------------------------------------------------------------- - - @Override public void runOpMode() throws InterruptedException { - - // Retrieve and initialize the IMU. - // This sample expects the IMU to be in a REV Hub and named "imu". - imu = hardwareMap.get(IMU.class, "imu"); - - /* Define how the hub is mounted to the robot to get the correct Yaw, Pitch and Roll values. - * - * You can apply up to three axis rotations to orient your Hub according to how it's mounted on the robot. - * - * The starting point for these rotations is the "Default" Hub orientation, which is: - * 1) Hub laying flat on a horizontal surface, with the Printed Logo facing UP - * 2) Rotated such that the USB ports are facing forward on the robot. - * - * If you are using a REV External IMU, the "Default" orientation is the same as for a REV Hub, but instead of - * the USB ports facing forward, the I2C port faces forward. - * - * The order that the rotations are performed matters, so this sample shows doing them in the order X, Y, then Z. - * For specifying non-orthogonal hub mounting orientations, we must temporarily use axes - * defined relative to the Hub itself, instead of the usual Robot Coordinate System axes - * used for the results the IMU gives us. In the starting orientation, the Hub axes are - * aligned with the Robot Coordinate System: - * - * X Axis: Starting at Center of Hub, pointing out towards I2C connectors - * Y Axis: Starting at Center of Hub, pointing out towards USB connectors - * Z Axis: Starting at Center of Hub, pointing Up through LOGO - * - * Positive rotation is defined by right-hand rule with thumb pointing in +ve direction on axis. - * - * Some examples. - * - * ---------------------------------------------------------------------------------------------------------------------------------- - * Example A) Assume that the hub is mounted on a sloped plate at the back of the robot, with the USB ports coming out the top of the hub. - * The plate is tilted UP 60 degrees from horizontal. - * - * To get the "Default" hub into this configuration you would just need a single rotation. - * 1) Rotate the Hub +60 degrees around the X axis to tilt up the front edge. - * 2) No rotation around the Y or Z axes. - * - * So the X,Y,Z rotations would be 60,0,0 - * - * ---------------------------------------------------------------------------------------------------------------------------------- - * Example B) Assume that the hub is laying flat on the chassis, but it has been twisted 30 degrees towards the right front wheel to make - * the USB cable accessible. - * - * To get the "Default" hub into this configuration you would just need a single rotation, but around a different axis. - * 1) No rotation around the X or Y axes. - * 2) Rotate the Hub -30 degrees (Clockwise) around the Z axis, since a positive angle would be Counter Clockwise. - * - * So the X,Y,Z rotations would be 0,0,-30 - * - * ---------------------------------------------------------------------------------------------------------------------------------- - * Example C) Assume that the hub is mounted on a vertical plate on the right side of the robot, with the Logo facing out, and the - * Hub rotated so that the USB ports are facing down 30 degrees towards the back wheels of the robot. - * - * To get the "Default" hub into this configuration will require several rotations. - * 1) Rotate the hub +90 degrees around the X axis to get it standing upright with the logo pointing backwards on the robot - * 2) Next, rotate the hub +90 around the Y axis to get it facing to the right. - * 3) Finally rotate the hub +120 degrees around the Z axis to take the USB ports from vertical to sloping down 30 degrees and - * facing towards the back of the robot. - * - * So the X,Y,Z rotations would be 90,90,120 - */ - - // The next three lines define the desired axis rotations. - // To Do: EDIT these values to match YOUR mounting configuration. - double xRotation = 0; // enter the desired X rotation angle here. - double yRotation = 0; // enter the desired Y rotation angle here. - double zRotation = 0; // enter the desired Z rotation angle here. - - Orientation hubRotation = xyzOrientation(xRotation, yRotation, zRotation); - - // Now initialize the IMU with this mounting orientation - RevHubOrientationOnRobot orientationOnRobot = new RevHubOrientationOnRobot(hubRotation); - imu.initialize(new IMU.Parameters(orientationOnRobot)); - - // Loop and update the dashboard - while (!isStopRequested()) { - telemetry.addData("Hub orientation", "X=%.1f, Y=%.1f, Z=%.1f \n", xRotation, yRotation, zRotation); - - // Check to see if heading reset is requested - if (gamepad1.y) { - telemetry.addData("Yaw", "Resetting\n"); - imu.resetYaw(); - } else { - telemetry.addData("Yaw", "Press Y (triangle) on Gamepad to reset\n"); - } - - // Retrieve Rotational Angles and Velocities - YawPitchRollAngles orientation = imu.getRobotYawPitchRollAngles(); - AngularVelocity angularVelocity = imu.getRobotAngularVelocity(AngleUnit.DEGREES); - - telemetry.addData("Yaw (Z)", "%.2f Deg. (Heading)", orientation.getYaw(AngleUnit.DEGREES)); - telemetry.addData("Pitch (X)", "%.2f Deg.", orientation.getPitch(AngleUnit.DEGREES)); - telemetry.addData("Roll (Y)", "%.2f Deg.\n", orientation.getRoll(AngleUnit.DEGREES)); - telemetry.addData("Yaw (Z) velocity", "%.2f Deg/Sec", angularVelocity.zRotationRate); - telemetry.addData("Pitch (X) velocity", "%.2f Deg/Sec", angularVelocity.xRotationRate); - telemetry.addData("Roll (Y) velocity", "%.2f Deg/Sec", angularVelocity.yRotationRate); - telemetry.update(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUOrthogonal.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUOrthogonal.java deleted file mode 100644 index af4c2028..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUOrthogonal.java +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright (c) 2022 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.RevHubOrientationOnRobot; -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.IMU; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; - -/* - * This OpMode shows how to use the new universal IMU interface. This - * interface may be used with the BNO055 IMU or the BHI260 IMU. It assumes that an IMU is configured - * on the robot with the name "imu". - * - * The sample will display the current Yaw, Pitch and Roll of the robot.
- * With the correct orientation parameters selected, pitch/roll/yaw should act as follows: - * Pitch value should INCREASE as the robot is tipped UP at the front. (Rotation about X)
- * Roll value should INCREASE as the robot is tipped UP at the left side. (Rotation about Y)
- * Yaw value should INCREASE as the robot is rotated Counter Clockwise. (Rotation about Z)
- * - * The yaw can be reset (to zero) by pressing the Y button on the gamepad (Triangle on a PS4 controller) - * - * This specific sample assumes that the Hub is mounted on one of the three orthogonal planes - * (X/Y, X/Z or Y/Z) and that the Hub has only been rotated in a range of 90 degree increments. - * - * Note: if your Hub is mounted on a surface angled at some non-90 Degree multiple (like 30) look at - * the alternative SensorIMUNonOrthogonal sample in this folder. - * - * This "Orthogonal" requirement means that: - * - * 1) The Logo printed on the top of the Hub can ONLY be pointing in one of six directions: - * FORWARD, BACKWARD, UP, DOWN, LEFT and RIGHT. - * - * 2) The USB ports can only be pointing in one of the same six directions:
- * FORWARD, BACKWARD, UP, DOWN, LEFT and RIGHT. - * - * So, To fully define how your Hub is mounted to the robot, you must simply specify:
- * logoFacingDirection
- * usbFacingDirection - * - * 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. - * - * Finally, choose the two correct parameters to define how your Hub is mounted and edit this OpMode - * to use those parameters. - */ -@TeleOp(name = "Sensor: IMU Orthogonal", group = "Sensor") -@Disabled // Comment this out to add to the OpMode list -public class SensorIMUOrthogonal extends LinearOpMode -{ - // The IMU sensor object - IMU imu; - - //---------------------------------------------------------------------------------------------- - // Main logic - //---------------------------------------------------------------------------------------------- - - @Override public void runOpMode() throws InterruptedException { - - // Retrieve and initialize the IMU. - // This sample expects the IMU to be in a REV Hub and named "imu". - imu = hardwareMap.get(IMU.class, "imu"); - - /* Define how the hub is mounted on the robot to get the correct Yaw, Pitch and Roll values. - * - * Two input parameters are required to fully specify the Orientation. - * The first parameter specifies the direction the printed logo on the Hub is pointing. - * The second parameter specifies the direction the USB connector on the Hub is pointing. - * All directions are relative to the robot, and left/right is as-viewed from behind the robot. - * - * If you are using a REV 9-Axis IMU, you can use the Rev9AxisImuOrientationOnRobot class instead of the - * RevHubOrientationOnRobot class, which has an I2cPortFacingDirection instead of a UsbFacingDirection. - */ - - /* The next two lines define Hub orientation. - * The Default Orientation (shown) is when a hub is mounted horizontally with the printed logo pointing UP and the USB port pointing FORWARD. - * - * To Do: EDIT these two lines to match YOUR mounting configuration. - */ - RevHubOrientationOnRobot.LogoFacingDirection logoDirection = RevHubOrientationOnRobot.LogoFacingDirection.UP; - RevHubOrientationOnRobot.UsbFacingDirection usbDirection = RevHubOrientationOnRobot.UsbFacingDirection.FORWARD; - - RevHubOrientationOnRobot orientationOnRobot = new RevHubOrientationOnRobot(logoDirection, usbDirection); - - // Now initialize the IMU with this mounting orientation - // Note: if you choose two conflicting directions, this initialization will cause a code exception. - imu.initialize(new IMU.Parameters(orientationOnRobot)); - - // Loop and update the dashboard - while (!isStopRequested()) { - - telemetry.addData("Hub orientation", "Logo=%s USB=%s\n ", logoDirection, usbDirection); - - // Check to see if heading reset is requested - if (gamepad1.y) { - telemetry.addData("Yaw", "Resetting\n"); - imu.resetYaw(); - } else { - telemetry.addData("Yaw", "Press Y (triangle) on Gamepad to reset\n"); - } - - // Retrieve Rotational Angles and Velocities - YawPitchRollAngles orientation = imu.getRobotYawPitchRollAngles(); - AngularVelocity angularVelocity = imu.getRobotAngularVelocity(AngleUnit.DEGREES); - - telemetry.addData("Yaw (Z)", "%.2f Deg. (Heading)", orientation.getYaw(AngleUnit.DEGREES)); - telemetry.addData("Pitch (X)", "%.2f Deg.", orientation.getPitch(AngleUnit.DEGREES)); - telemetry.addData("Roll (Y)", "%.2f Deg.\n", orientation.getRoll(AngleUnit.DEGREES)); - telemetry.addData("Yaw (Z) velocity", "%.2f Deg/Sec", angularVelocity.zRotationRate); - telemetry.addData("Pitch (X) velocity", "%.2f Deg/Sec", angularVelocity.xRotationRate); - telemetry.addData("Roll (Y) velocity", "%.2f Deg/Sec", angularVelocity.yRotationRate); - telemetry.update(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java deleted file mode 100644 index ccc945ff..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java +++ /dev/null @@ -1,128 +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.kauailabs.NavxMicroNavigationSensor; -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; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.AxesOrder; -import org.firstinspires.ftc.robotcore.external.navigation.AxesReference; -import org.firstinspires.ftc.robotcore.external.navigation.Orientation; - -/* - * This OpMode shows how to use Kauai Labs navX Micro Robotics Navigation - * Sensor. It assumes that the sensor is configured with a name of "navx". - * - * 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: KL navX Micro", group = "Sensor") -@Disabled -public class SensorKLNavxMicro 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 NavxMicroNavigationSensor}, by contrast, provides functionality that - * is unique to the navX Micro sensor. - */ - IntegratingGyroscope gyro; - NavxMicroNavigationSensor navxMicro; - - // A timer helps provide feedback while calibration is taking place - ElapsedTime timer = new ElapsedTime(); - - @Override public void runOpMode() throws InterruptedException { - // Get a reference to a Modern Robotics GyroSensor object. We use several interfaces - // on this object to illustrate which interfaces support which functionality. - navxMicro = hardwareMap.get(NavxMicroNavigationSensor.class, "navx"); - gyro = (IntegratingGyroscope)navxMicro; - // If you're only interested int the IntegratingGyroscope interface, the following will suffice. - // gyro = hardwareMap.get(IntegratingGyroscope.class, "navx"); - - // The gyro automatically starts calibrating. This takes a few seconds. - telemetry.log().add("Gyro Calibrating. Do Not Move!"); - - // Wait until the gyro calibration is complete - timer.reset(); - while (navxMicro.isCalibrating()) { - telemetry.addData("calibrating", "%s", Math.round(timer.seconds())%2==0 ? "|.." : "..|"); - telemetry.update(); - Thread.sleep(50); - } - telemetry.log().clear(); telemetry.log().add("Gyro Calibrated. Press Start."); - telemetry.clear(); telemetry.update(); - - // Wait for the start button to be pressed - waitForStart(); - telemetry.log().clear(); - - while (opModeIsActive()) { - - // Read dimensionalized data from the gyro. This gyro can report angular velocities - // about all three axes. Additionally, it internally integrates the Z axis to - // be able to report an absolute angular Z orientation. - AngularVelocity rates = gyro.getAngularVelocity(AngleUnit.DEGREES); - Orientation angles = gyro.getAngularOrientation(AxesReference.INTRINSIC, AxesOrder.ZYX, AngleUnit.DEGREES); - - telemetry.addLine() - .addData("dx", formatRate(rates.xRotationRate)) - .addData("dy", formatRate(rates.yRotationRate)) - .addData("dz", "%s deg/s", formatRate(rates.zRotationRate)); - - telemetry.addLine() - .addData("heading", formatAngle(angles.angleUnit, angles.firstAngle)) - .addData("roll", formatAngle(angles.angleUnit, angles.secondAngle)) - .addData("pitch", "%s deg", formatAngle(angles.angleUnit, angles.thirdAngle)); - telemetry.update(); - - idle(); // Always call idle() at the bottom of your while(opModeIsActive()) loop - } - } - - String formatRate(float rate) { - return String.format("%.3f", rate); - } - - String formatAngle(AngleUnit angleUnit, double angle) { - return formatDegrees(AngleUnit.DEGREES.fromUnit(angleUnit, angle)); - } - - String formatDegrees(double degrees){ - return String.format("%.1f", AngleUnit.DEGREES.normalize(degrees)); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLimelight3A.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLimelight3A.java deleted file mode 100644 index 6c1f702a..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLimelight3A.java +++ /dev/null @@ -1,159 +0,0 @@ -/* -Copyright (c) 2024 Limelight Vision - -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.limelightvision.LLResult; -import com.qualcomm.hardware.limelightvision.LLResultTypes; -import com.qualcomm.hardware.limelightvision.LLStatus; -import com.qualcomm.hardware.limelightvision.Limelight3A; -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.Pose3D; - -import java.util.List; - -/* - * This OpMode illustrates how to use the Limelight3A Vision Sensor. - * - * @see Limelight - * - * Notes on configuration: - * - * The device presents itself, when plugged into a USB port on a Control Hub as an ethernet - * interface. A DHCP server running on the Limelight automatically assigns the Control Hub an - * ip address for the new ethernet interface. - * - * Since the Limelight is plugged into a USB port, it will be listed on the top level configuration - * activity along with the Control Hub Portal and other USB devices such as webcams. Typically - * serial numbers are displayed below the device's names. In the case of the Limelight device, the - * Control Hub's assigned ip address for that ethernet interface is used as the "serial number". - * - * Tapping the Limelight's name, transitions to a new screen where the user can rename the Limelight - * and specify the Limelight's ip address. Users should take care not to confuse the ip address of - * the Limelight itself, which can be configured through the Limelight settings page via a web browser, - * and the ip address the Limelight device assigned the Control Hub and which is displayed in small text - * below the name of the Limelight on the top level configuration screen. - */ -@TeleOp(name = "Sensor: Limelight3A", group = "Sensor") -@Disabled -public class SensorLimelight3A extends LinearOpMode { - - private Limelight3A limelight; - - @Override - public void runOpMode() throws InterruptedException - { - limelight = hardwareMap.get(Limelight3A.class, "limelight"); - - telemetry.setMsTransmissionInterval(11); - - limelight.pipelineSwitch(0); - - /* - * Starts polling for data. If you neglect to call start(), getLatestResult() will return null. - */ - limelight.start(); - - telemetry.addData(">", "Robot Ready. Press Play."); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) { - LLStatus status = limelight.getStatus(); - telemetry.addData("Name", "%s", - status.getName()); - telemetry.addData("LL", "Temp: %.1fC, CPU: %.1f%%, FPS: %d", - status.getTemp(), status.getCpu(),(int)status.getFps()); - telemetry.addData("Pipeline", "Index: %d, Type: %s", - status.getPipelineIndex(), status.getPipelineType()); - - LLResult result = limelight.getLatestResult(); - if (result != null) { - // Access general information - Pose3D botpose = result.getBotpose(); - double captureLatency = result.getCaptureLatency(); - double targetingLatency = result.getTargetingLatency(); - double parseLatency = result.getParseLatency(); - telemetry.addData("LL Latency", captureLatency + targetingLatency); - telemetry.addData("Parse Latency", parseLatency); - telemetry.addData("PythonOutput", java.util.Arrays.toString(result.getPythonOutput())); - - if (result.isValid()) { - telemetry.addData("tx", result.getTx()); - telemetry.addData("txnc", result.getTxNC()); - telemetry.addData("ty", result.getTy()); - telemetry.addData("tync", result.getTyNC()); - - telemetry.addData("Botpose", botpose.toString()); - - // Access barcode results - List barcodeResults = result.getBarcodeResults(); - for (LLResultTypes.BarcodeResult br : barcodeResults) { - telemetry.addData("Barcode", "Data: %s", br.getData()); - } - - // Access classifier results - List classifierResults = result.getClassifierResults(); - for (LLResultTypes.ClassifierResult cr : classifierResults) { - telemetry.addData("Classifier", "Class: %s, Confidence: %.2f", cr.getClassName(), cr.getConfidence()); - } - - // Access detector results - List detectorResults = result.getDetectorResults(); - for (LLResultTypes.DetectorResult dr : detectorResults) { - telemetry.addData("Detector", "Class: %s, Area: %.2f", dr.getClassName(), dr.getTargetArea()); - } - - // Access fiducial results - List fiducialResults = result.getFiducialResults(); - for (LLResultTypes.FiducialResult fr : fiducialResults) { - telemetry.addData("Fiducial", "ID: %d, Family: %s, X: %.2f, Y: %.2f", fr.getFiducialId(), fr.getFamily(),fr.getTargetXDegrees(), fr.getTargetYDegrees()); - } - - // Access color results - List colorResults = result.getColorResults(); - for (LLResultTypes.ColorResult cr : colorResults) { - telemetry.addData("Color", "X: %.2f, Y: %.2f", cr.getTargetXDegrees(), cr.getTargetYDegrees()); - } - } - } else { - telemetry.addData("Limelight", "No data available"); - } - - telemetry.update(); - } - limelight.stop(); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRColor.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRColor.java deleted file mode 100644 index 32b37e09..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRColor.java +++ /dev/null @@ -1,138 +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.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.ColorSensor; - -/* - * - * This OpMode that shows how to use - * a Modern Robotics Color Sensor. - * - * The OpMode 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 - */ -@TeleOp(name = "Sensor: MR Color", group = "Sensor") -@Disabled -public class SensorMRColor 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.get(ColorSensor.class, "sensor_color"); - - // Set the LED in the beginning - colorSensor.enableLed(bLedOn); - - // wait for the start button to be pressed. - waitForStart(); - - // while the OpMode is active, 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 either gamepad. - bCurrState = gamepad1.x; - - // check for button state transitions. - if (bCurrState && (bCurrState != bPrevState)) { - - // button is transitioning to a pressed state. So Toggle LED - bLedOn = !bLedOn; - colorSensor.enableLed(bLedOn); - } - - // update previous state variable. - bPrevState = bCurrState; - - // convert the RGB values to HSV values. - Color.RGBToHSV(colorSensor.red() * 8, colorSensor.green() * 8, colorSensor.blue() * 8, 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/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRGyro.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRGyro.java deleted file mode 100644 index 91c0062e..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRGyro.java +++ /dev/null @@ -1,160 +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.modernrobotics.ModernRoboticsI2cGyro; -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.IntegratingGyroscope; -import com.qualcomm.robotcore.util.ElapsedTime; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.AxesOrder; -import org.firstinspires.ftc.robotcore.external.navigation.AxesReference; - -/* - * This OpMode shows how to use the Modern Robotics Gyro. - * - * The OpMode assumes that the gyro sensor is attached to a Device Interface Module - * I2C channel and 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 -*/ -@TeleOp(name = "Sensor: MR Gyro", group = "Sensor") -@Disabled -public class SensorMRGyro 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 ModernRoboticsI2cGyro}, by contrast, provides functionality that - * is unique to the Modern Robotics gyro sensor. - */ - IntegratingGyroscope gyro; - ModernRoboticsI2cGyro modernRoboticsI2cGyro; - - // A timer helps provide feedback while calibration is taking place - ElapsedTime timer = new ElapsedTime(); - - @Override - public void runOpMode() { - - boolean lastResetState = false; - boolean curResetState = false; - - // Get a reference to a Modern Robotics gyro object. We use several interfaces - // on this object to illustrate which interfaces support which functionality. - modernRoboticsI2cGyro = hardwareMap.get(ModernRoboticsI2cGyro.class, "gyro"); - gyro = (IntegratingGyroscope)modernRoboticsI2cGyro; - // If you're only interested int the IntegratingGyroscope interface, the following will suffice. - // gyro = hardwareMap.get(IntegratingGyroscope.class, "gyro"); - // A similar approach will work for the Gyroscope interface, if that's all you need. - - // Start calibrating the gyro. This takes a few seconds and is worth performing - // during the initialization phase at the start of each OpMode. - telemetry.log().add("Gyro Calibrating. Do Not Move!"); - modernRoboticsI2cGyro.calibrate(); - - // Wait until the gyro calibration is complete - timer.reset(); - while (!isStopRequested() && modernRoboticsI2cGyro.isCalibrating()) { - telemetry.addData("calibrating", "%s", Math.round(timer.seconds())%2==0 ? "|.." : "..|"); - telemetry.update(); - sleep(50); - } - - telemetry.log().clear(); telemetry.log().add("Gyro Calibrated. Press Start."); - telemetry.clear(); telemetry.update(); - - // Wait for the start button to be pressed - waitForStart(); - telemetry.log().clear(); - telemetry.log().add("Press A & B to reset heading"); - - // Loop until we're asked to stop - while (opModeIsActive()) { - - // If the A and B buttons are pressed just now, reset Z heading. - curResetState = (gamepad1.a && gamepad1.b); - if (curResetState && !lastResetState) { - modernRoboticsI2cGyro.resetZAxisIntegrator(); - } - lastResetState = curResetState; - - // The raw() methods report the angular rate of change about each of the - // three axes directly as reported by the underlying sensor IC. - int rawX = modernRoboticsI2cGyro.rawX(); - int rawY = modernRoboticsI2cGyro.rawY(); - int rawZ = modernRoboticsI2cGyro.rawZ(); - int heading = modernRoboticsI2cGyro.getHeading(); - int integratedZ = modernRoboticsI2cGyro.getIntegratedZValue(); - - // Read dimensionalized data from the gyro. This gyro can report angular velocities - // about all three axes. Additionally, it internally integrates the Z axis to - // be able to report an absolute angular Z orientation. - AngularVelocity rates = gyro.getAngularVelocity(AngleUnit.DEGREES); - float zAngle = gyro.getAngularOrientation(AxesReference.INTRINSIC, AxesOrder.ZYX, AngleUnit.DEGREES).firstAngle; - - // Read administrative information from the gyro - int zAxisOffset = modernRoboticsI2cGyro.getZAxisOffset(); - int zAxisScalingCoefficient = modernRoboticsI2cGyro.getZAxisScalingCoefficient(); - - telemetry.addLine() - .addData("dx", formatRate(rates.xRotationRate)) - .addData("dy", formatRate(rates.yRotationRate)) - .addData("dz", "%s deg/s", formatRate(rates.zRotationRate)); - telemetry.addData("angle", "%s deg", formatFloat(zAngle)); - telemetry.addData("heading", "%3d deg", heading); - telemetry.addData("integrated Z", "%3d", integratedZ); - telemetry.addLine() - .addData("rawX", formatRaw(rawX)) - .addData("rawY", formatRaw(rawY)) - .addData("rawZ", formatRaw(rawZ)); - telemetry.addLine().addData("z offset", zAxisOffset).addData("z coeff", zAxisScalingCoefficient); - telemetry.update(); - } - } - - String formatRaw(int rawValue) { - return String.format("%d", rawValue); - } - - String formatRate(float rate) { - return String.format("%.3f", rate); - } - - String formatFloat(float rate) { - return String.format("%.3f", rate); - } - -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMROpticalDistance.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMROpticalDistance.java deleted file mode 100644 index 6d2dfa39..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMROpticalDistance.java +++ /dev/null @@ -1,70 +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.OpticalDistanceSensor; - -/* - * This OpMode shows how to use a Modern Robotics Optical Distance Sensor - * It assumes that the ODS sensor is configured with a name of "sensor_ods". - * - * 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: MR ODS", group = "Sensor") -@Disabled -public class SensorMROpticalDistance extends LinearOpMode { - - OpticalDistanceSensor odsSensor; // Hardware Device Object - - @Override - public void runOpMode() { - - // get a reference to our Light Sensor object. - odsSensor = hardwareMap.get(OpticalDistanceSensor.class, "sensor_ods"); - - // wait for the start button to be pressed. - waitForStart(); - - // while the OpMode 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. - telemetry.addData("Raw", odsSensor.getRawLightDetected()); - telemetry.addData("Normal", odsSensor.getLightDetected()); - - telemetry.update(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java deleted file mode 100644 index 2039ef97..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java +++ /dev/null @@ -1,70 +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.modernrobotics.ModernRoboticsI2cRangeSensor; -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; - -/* - * This OpMode illustrates how to use the Modern Robotics Range Sensor. - * - * The OpMode 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 MR Range 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 { - - ModernRoboticsI2cRangeSensor rangeSensor; - - @Override public void runOpMode() { - - // get a reference to our compass - rangeSensor = hardwareMap.get(ModernRoboticsI2cRangeSensor.class, "sensor_range"); - - // wait for the start button to be pressed - waitForStart(); - - while (opModeIsActive()) { - telemetry.addData("raw ultrasonic", rangeSensor.rawUltrasonic()); - telemetry.addData("raw optical", rangeSensor.rawOptical()); - telemetry.addData("cm optical", "%.2f cm", rangeSensor.cmOptical()); - telemetry.addData("cm", "%.2f cm", rangeSensor.getDistance(DistanceUnit.CM)); - telemetry.update(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuad.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuad.java deleted file mode 100644 index 2300dd78..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuad.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2024 DigitalChickenLabs - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.hardware.digitalchickenlabs.OctoQuad; -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.Telemetry; - -/* - * This OpMode illustrates how to use the DigitalChickenLabs OctoQuad Quadrature Encoder & Pulse Width Interface Module - * - * The OctoQuad has 8 input channels that can used to read either Relative Quadrature Encoders or Pulse-Width Absolute Encoder inputs. - * Relative Quadrature encoders are found on most FTC motors, and some stand-alone position sensors like the REV Thru-Bore encoder. - * Pulse-Width encoders are less common. The REV Thru-Bore encoder can provide its absolute position via a variable pulse width, - * as can several sonar rangefinders such as the MaxBotix MB1000 series. - * - * This basic sample shows how an OctoQuad can be used to read the position three Odometry pods fitted - * with REV Thru-Bore encoders. For a more advanced example showing additional OctoQuad capabilities, see the SensorOctoQuadAdv sample. - * - * This OpMode assumes that the OctoQuad is attached to an I2C interface named "octoquad" in the robot configuration. - * - * The code assumes the first three OctoQuad inputs are connected as follows - * - Chan 0: for measuring forward motion on the left side of the robot. - * - Chan 1: for measuring forward motion on the right side of the robot. - * - Chan 2: for measuring Lateral (strafing) motion. - * - * The encoder values may be reset to zero by pressing the X (left most) button on Gamepad 1. - * - * This sample does not show how to interpret these readings, just how to obtain and display them. - * - * 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 the sensor's product page: https://www.tindie.com/products/35114/ - */ -@TeleOp(name = "OctoQuad Basic", group="OctoQuad") -@Disabled -public class SensorOctoQuad extends LinearOpMode { - - // Identify which encoder OctoQuad inputs are connected to each odometry pod. - private final int ODO_LEFT = 0; // Facing forward direction on left side of robot (Axial motion) - private final int ODO_RIGHT = 1; // Facing forward direction on right side or robot (Axial motion) - private final int ODO_PERP = 2; // Facing perpendicular direction at the center of the robot (Lateral motion) - - // Declare the OctoQuad object and members to store encoder positions and velocities - private OctoQuad octoquad; - - private int posLeft; - private int posRight; - private int posPerp; - - /** - * This function is executed when this OpMode is selected from the Driver Station. - */ - @Override - public void runOpMode() { - - // Connect to OctoQuad by referring to its name in the Robot Configuration. - octoquad = hardwareMap.get(OctoQuad.class, "octoquad"); - - // Read the Firmware Revision number from the OctoQuad and display it as telemetry. - telemetry.addData("OctoQuad Firmware Version ", octoquad.getFirmwareVersion()); - - // Reverse the count-direction of any encoder that is not what you require. - // e.g. if you push the robot forward and the left encoder counts down, then reverse it so it counts up. - octoquad.setSingleEncoderDirection(ODO_LEFT, OctoQuad.EncoderDirection.REVERSE); - octoquad.setSingleEncoderDirection(ODO_RIGHT, OctoQuad.EncoderDirection.FORWARD); - octoquad.setSingleEncoderDirection(ODO_PERP, OctoQuad.EncoderDirection.FORWARD); - - // Any changes that are made should be saved in FLASH just in case there is a sensor power glitch. - octoquad.saveParametersToFlash(); - - telemetry.addLine("\nPress START to read encoder values"); - telemetry.update(); - - waitForStart(); - - // Configure the telemetry for optimal display of data. - telemetry.setDisplayFormat(Telemetry.DisplayFormat.MONOSPACE); - telemetry.setMsTransmissionInterval(50); - - // Set all the encoder inputs to zero. - octoquad.resetAllPositions(); - - // Loop while displaying the odometry pod positions. - while (opModeIsActive()) { - telemetry.addData(">", "Press X to Reset Encoders\n"); - - // Check for X button to reset encoders. - if (gamepad1.x) { - // Reset the position of all encoders to zero. - octoquad.resetAllPositions(); - } - - // Read all the encoder data. Load into local members. - readOdometryPods(); - - // Display the values. - telemetry.addData("Left ", "%8d counts", posLeft); - telemetry.addData("Right", "%8d counts", posRight); - telemetry.addData("Perp ", "%8d counts", posPerp); - telemetry.update(); - } - } - - private void readOdometryPods() { - // For best performance, we should only perform ONE transaction with the OctoQuad each cycle. - // Since this example only needs to read positions from a few channels, we could use either - // readPositionRange(idxFirst, idxLast) to get a select number of sequential channels - // or - // readAllEncoderData() to get all 8 encoder readings - // - // Since both calls take almost the same amount of time, and the actual channels may not end up - // being sequential, we will read all of the encoder positions, and then pick out the ones we need. - OctoQuad.EncoderDataBlock data = octoquad.readAllEncoderData(); - posLeft = data.positions[ODO_LEFT]; - posRight = data.positions[ODO_RIGHT]; - posPerp = data.positions[ODO_PERP]; - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuadAdv.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuadAdv.java deleted file mode 100644 index 2e807ce0..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuadAdv.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) 2024 DigitalChickenLabs - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.hardware.digitalchickenlabs.OctoQuad; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.util.ElapsedTime; -import com.qualcomm.robotcore.util.MovingStatistics; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; - - -import org.firstinspires.ftc.robotcore.external.Telemetry; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; - -import java.util.ArrayList; -import java.util.List; - -/* - * This OpMode illustrates how to use advanced features of the DigitalChickenLabs OctoQuad Quadrature Encoder & Pulse Width Interface Module - * - * The OctoQuad has 8 input channels that can used to read either Quadrature Encoder signals (like with most FTC motors) - * or Pulse-Width style Absolute Encoder inputs (eg: REV Through Bore encoder pulse width output). - * - * This OpMode illustrates several of the more advanced features of an OctoQuad, including Pulse Width measurement and velocity measurement. - * For a more basic OpMode just showing how to read encoder inputs, see the SensorOctoQuad sample. - * - * This OpMode assumes that the OctoQuad is attached to an I2C interface named "octoquad" in the robot configuration. - * - * One system that requires a lot of encoder inputs is a Swerve Drive system. - * Such a drive requires two encoders per drive module: one for position & velocity of the Drive motor/wheel, and one for position/angle of the Steering motor. - * The Drive motor usually requires a quadrature encoder, and the Steering motor requires an Absolute encoder. - * This quantity and combination of encoder inputs is a challenge, but a single OctoQuad could be used to read them all. - * - * This sample will configure an OctoQuad for a swerve drive, as follows - * - Configure 4 Relative Quadrature Encoder inputs and 4 Absolute Pulse-Width Encoder inputs - * - Configure a velocity sample interval of 25 mSec - * - Configure a pulse width input range of 1-1024 uSec for a REV Through Bore Encoder's Absolute Pulse output. - * - * An OctoSwerveDrive class will be created to initialize the OctoQuad, and manage the 4 swerve modules. - * An OctoSwerveModule class will be created to configure and read a single swerve module. - * - * Wiring: - * The OctoQuad will be configured to accept Quadrature encoders on the first four channels and Absolute (pulse width) encoders on the last four channels. - * - * The standard 4-pin to 4-pin cable can be used to connect each Driver Motor encoder to the OctoQuad. (channels 0-3) - * - * A modified version of the REV 6-4 pin cable (shipped with the encoder) connects the steering encoder to the OctoQuad. (channels 4-7) - * To connect the Absolute position signal from a REV Thru-Bore encoder to the OctoQuad, the Provided 6-pin to 4-pin cable will need to be modified. - * At the 6-pin connector end, move the yellow wire from its initial pin-3 position to the ABS pin-5 position. This can be done easily - * by using a small flathead screwdriver to lift the small white tab holding the metal wire crimp in place and gently pulling the wire out. - * See the OctoSwerveDrive() constructor below for the correct wheel/channel assignment. - * - * 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 - * - * Note: If you prefer, you can move the two support classes from this file, and place them in their own files. - * But leaving them in place is simpler for this example. - * - * See the sensor's product page: https://www.tindie.com/products/35114/ - */ -@TeleOp(name="OctoQuad Advanced", group="OctoQuad") -@Disabled -public class SensorOctoQuadAdv extends LinearOpMode { - - @Override - public void runOpMode() throws InterruptedException { - // Connect to the OctoQuad by looking up its name in the hardwareMap. - OctoQuad octoquad = hardwareMap.get(OctoQuad.class, "octoquad"); - - // Create the interface for the Swerve Drive Encoders - OctoSwerveDrive octoSwerveDrive = new OctoSwerveDrive(octoquad); - - // Display the OctoQuad firmware revision - telemetry.addLine("OctoQuad Firmware v" + octoquad.getFirmwareVersion()); - telemetry.addLine("\nPress START to read encoder values"); - telemetry.update(); - - waitForStart(); - - // Configure the telemetry for optimal display of data. - telemetry.setDisplayFormat(Telemetry.DisplayFormat.MONOSPACE); - telemetry.setMsTransmissionInterval(50); - - // Run stats to determine cycle times. - MovingStatistics avgTime = new MovingStatistics(100); - ElapsedTime elapsedTime = new ElapsedTime(); - - while (opModeIsActive()) { - telemetry.addData(">", "Press X to Reset Encoders\n"); - - if(gamepad1.x) { - octoquad.resetAllPositions(); - } - - // read all the swerve drive encoders and update positions and velocities. - octoSwerveDrive.updateModules(); - octoSwerveDrive.show(telemetry); - - // Update cycle time stats - avgTime.add(elapsedTime.nanoseconds()); - elapsedTime.reset(); - - telemetry.addData("Loop time", "%.1f mS", avgTime.getMean()/1000000); - telemetry.update(); - } - } -} - -// ============================ Internal (Inner) Classes ============================= - -/*** - * OctoSwerveDrive class manages 4 Swerve Modules - * - Performs general OctoQuad initialization - * - Creates 4 module classes, one for each swerve module - * - Updates swerve drive status by reading all data from OctoQuad and Updating each module - * - Displays all swerve drive data as telemetry - */ -class OctoSwerveDrive { - - private final OctoQuad octoquad; - private final List allModules = new ArrayList<>(); - - // members to hold encoder data for each module. - public final OctoSwerveModule LeftFront; - public final OctoSwerveModule RightFront; - public final OctoSwerveModule LeftBack; - public final OctoSwerveModule RightBack; - - // Prepare an object to hold an entire OctoQuad encoder readable register bank (pos and vel) - private final OctoQuad.EncoderDataBlock encoderDataBlock = new OctoQuad.EncoderDataBlock(); - - public OctoSwerveDrive(OctoQuad octoquad) { - this.octoquad = octoquad; - - // Clear out all prior settings and encoder data before setting up desired configuration - octoquad.resetEverything(); - - // Assume first 4 channels are relative encoders and the next 4 are absolute encoders - octoquad.setChannelBankConfig(OctoQuad.ChannelBankConfig.BANK1_QUADRATURE_BANK2_PULSE_WIDTH); - - // Create the four OctoSwerveModules, and add them to a 'list' for easier reference. - - // Note: The wheel/channel order is set here. Ensure your encoder cables match. - // - // Note: The angleOffset must be set for each module so a forward facing wheel shows a steer angle of 0 degrees. - // The process for determining the correct angleOffsets is as follows: - // 1) Set all the angleValues (below) to zero then build and deploy the code. - // 2) Physically rotate all the swerve drives so the wheels are facing forward in the desired 0 degree position - // 3) Run the OpMode, view the telemetry and record the "Degrees" value for each module. - // 4) Update the code by entering the recorded Degrees value for each module as the angleOffset (last) parameter in the lines below. - // - // Rebuild and deploy the new code. Verify that the telemetry now indicates 0 degrees when the wheels are facing forward. - // Also verify that the correct module values change appropriately when you manually spin (drive) and rotate (steer) a wheel. - - allModules.add(LeftFront = new OctoSwerveModule(octoquad, "LF ",0,0));// Drive = 0, Steer = 4 - allModules.add(RightFront = new OctoSwerveModule(octoquad, "RF ",1,0));// Drive = 1, Steer = 5 - allModules.add(LeftBack = new OctoSwerveModule(octoquad, "LB ",2,0));// Drive = 2, Steer = 6 - allModules.add(RightBack = new OctoSwerveModule(octoquad, "RB ",3,0));// Drive = 3, Steer = 7 - - // now make sure the settings persist through any power glitches. - octoquad.saveParametersToFlash(); - } - - /** - * Updates all 4 swerve modules - */ - public void updateModules() { - // Read full OctoQuad data block and then pass DataBlock to each swerve module to update themselves. - octoquad.readAllEncoderData(encoderDataBlock); - for (OctoSwerveModule module : allModules) { - module.updateModule(encoderDataBlock); - } - } - - /** - * Generate telemetry data for all modules. - * @param telemetry OpMode Telemetry object - */ - public void show(Telemetry telemetry) { - // create general header block and then have each module add its own telemetry - telemetry.addData("pos", " Count CPS Degree DPS"); - for (OctoSwerveModule module : allModules) { - module.show(telemetry); - } - } -} - -/*** - * The OctoSwerveModule class manages a single swerve module - */ -class OctoSwerveModule { - - public double driveCounts; - public double driveCountsPerSec; - public double steerDegrees; - public double steerDegreesPerSec; - - private final String name; - private final int channel; - private final double angleOffset; - private final double steerDirMult; - - private static final int VELOCITY_SAMPLE_INTERVAL_MS = 25; // To provide 40 updates per second. - private static final double DEGREES_PER_US = (360.0 / 1024.0); // based on REV Through Bore Encoder - private static final double VELOCITY_SAMPLES_PER_S = (1000.0 / VELOCITY_SAMPLE_INTERVAL_MS); - - // The correct drive and turn directions must be set for the Swerve Module based on the specific hardware geometry. - // Forward motion must generate an increasing drive count. - // Counter Clockwise steer rotation must generate an increasing Steer Angle (degrees) - private static final boolean INVERT_DRIVE_ENCODER = false; // Set true if forward motion decreases drive "Count" - private static final boolean INVERT_STEER_ENCODER = false; // Set true if counter clockwise steer action decreases steer "Degree" - - /*** - * @param octoquad provide access to configure OctoQuad - * @param name name used for telemetry display - * @param quadChannel Quadrature encoder channel. Pulse Width channel is this + 4 - * @param angleOffset Angle to subtract from absolute encoder to calibrate zero position. (see comments above) - */ - public OctoSwerveModule (OctoQuad octoquad, String name, int quadChannel, double angleOffset) { - this.name = name; - this.channel = quadChannel; - this.angleOffset = angleOffset; - this.steerDirMult = INVERT_STEER_ENCODER ? -1 : 1 ; // create a multiplier to flip the steer angle. - - // Set the drive encoder direction. Note the absolute encoder does not have built-in direction inversion. - octoquad.setSingleEncoderDirection(channel, INVERT_DRIVE_ENCODER ? OctoQuad.EncoderDirection.REVERSE : OctoQuad.EncoderDirection.FORWARD); - - // Set the velocity sample interval on both encoders - octoquad.setSingleVelocitySampleInterval(channel, VELOCITY_SAMPLE_INTERVAL_MS); - octoquad.setSingleVelocitySampleInterval(channel + 4, VELOCITY_SAMPLE_INTERVAL_MS); - - // Setup Absolute encoder pulse range to match REV Through Bore encoder. - octoquad.setSingleChannelPulseWidthParams (channel + 4, new OctoQuad.ChannelPulseWidthParams(1,1024)); - } - - /*** - * Calculate the Swerve module's position and velocity values - * @param encoderDataBlock most recent full data block read from OctoQuad. - */ - public void updateModule(OctoQuad.EncoderDataBlock encoderDataBlock) { - driveCounts = encoderDataBlock.positions[channel]; // get Counts. - driveCountsPerSec = encoderDataBlock.velocities[channel] * VELOCITY_SAMPLES_PER_S; // convert counts/interval to counts/sec - - // convert uS to degrees. Add in any possible direction flip. - steerDegrees = AngleUnit.normalizeDegrees((encoderDataBlock.positions[channel+ 4] * DEGREES_PER_US * steerDirMult) - angleOffset); - // convert uS/interval to deg per sec. Add in any possible direction flip. - steerDegreesPerSec = encoderDataBlock.velocities[channel + 4] * DEGREES_PER_US * steerDirMult * VELOCITY_SAMPLES_PER_S; - } - - /** - * Display the Swerve module's state as telemetry - * @param telemetry OpMode Telemetry object - */ - public void show(Telemetry telemetry) { - telemetry.addData(name, "%8.0f %7.0f %7.0f %6.0f", driveCounts, driveCountsPerSec, steerDegrees, steerDegreesPerSec); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREV2mDistance.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREV2mDistance.java deleted file mode 100644 index 13883c34..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREV2mDistance.java +++ /dev/null @@ -1,87 +0,0 @@ -/* -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.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.DistanceSensor; -import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; - -/* - * This OpMode illustrates how to use the REV Robotics 2M Distance Sensor. - * - * The OpMode assumes that the sensor is configured with a name of "sensor_distance". - * - * 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 the sensor's product page: https://www.revrobotics.com/rev-31-1505/ - */ -@TeleOp(name = "Sensor: REV2mDistance", group = "Sensor") -@Disabled -public class SensorREV2mDistance extends LinearOpMode { - - private DistanceSensor sensorDistance; - - @Override - public void runOpMode() { - // you can use this as a regular DistanceSensor. - sensorDistance = hardwareMap.get(DistanceSensor.class, "sensor_distance"); - - // you can also cast this to a Rev2mDistanceSensor if you want to use added - // methods associated with the Rev2mDistanceSensor class. - Rev2mDistanceSensor sensorTimeOfFlight = (Rev2mDistanceSensor) sensorDistance; - - telemetry.addData(">>", "Press start to continue"); - telemetry.update(); - - waitForStart(); - while(opModeIsActive()) { - // generic DistanceSensor methods. - telemetry.addData("deviceName", sensorDistance.getDeviceName() ); - telemetry.addData("range", String.format("%.01f mm", sensorDistance.getDistance(DistanceUnit.MM))); - telemetry.addData("range", String.format("%.01f cm", sensorDistance.getDistance(DistanceUnit.CM))); - telemetry.addData("range", String.format("%.01f m", sensorDistance.getDistance(DistanceUnit.METER))); - telemetry.addData("range", String.format("%.01f in", sensorDistance.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(); - } - } - -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorSparkFunOTOS.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorSparkFunOTOS.java deleted file mode 100644 index 3a25230f..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorSparkFunOTOS.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - SPDX-License-Identifier: MIT - - Copyright (c) 2024 SparkFun Electronics -*/ -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.hardware.sparkfun.SparkFunOTOS; - -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; - -/* - * This OpMode illustrates how to use the SparkFun Qwiic Optical Tracking Odometry Sensor (OTOS) - * - * The OpMode assumes that the sensor is configured with a name of "sensor_otos". - * - * 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 the sensor's product page: https://www.sparkfun.com/products/24904 - */ -@TeleOp(name = "Sensor: SparkFun OTOS", group = "Sensor") -@Disabled -public class SensorSparkFunOTOS extends LinearOpMode { - // Create an instance of the sensor - SparkFunOTOS myOtos; - - @Override - public void runOpMode() throws InterruptedException { - // Get a reference to the sensor - myOtos = hardwareMap.get(SparkFunOTOS.class, "sensor_otos"); - - // All the configuration for the OTOS is done in this helper method, check it out! - configureOtos(); - - // Wait for the start button to be pressed - waitForStart(); - - // Loop until the OpMode ends - while (opModeIsActive()) { - // Get the latest position, which includes the x and y coordinates, plus the - // heading angle - SparkFunOTOS.Pose2D pos = myOtos.getPosition(); - - // Reset the tracking if the user requests it - if (gamepad1.y) { - myOtos.resetTracking(); - } - - // Re-calibrate the IMU if the user requests it - if (gamepad1.x) { - myOtos.calibrateImu(); - } - - // Inform user of available controls - telemetry.addLine("Press Y (triangle) on Gamepad to reset tracking"); - telemetry.addLine("Press X (square) on Gamepad to calibrate the IMU"); - telemetry.addLine(); - - // Log the position to the telemetry - telemetry.addData("X coordinate", pos.x); - telemetry.addData("Y coordinate", pos.y); - telemetry.addData("Heading angle", pos.h); - - // Update the telemetry on the driver station - telemetry.update(); - } - } - - private void configureOtos() { - telemetry.addLine("Configuring OTOS..."); - telemetry.update(); - - // Set the desired units for linear and angular measurements. Can be either - // meters or inches for linear, and radians or degrees for angular. If not - // set, the default is inches and degrees. Note that this setting is not - // persisted in the sensor, so you need to set at the start of all your - // OpModes if using the non-default value. - // myOtos.setLinearUnit(DistanceUnit.METER); - myOtos.setLinearUnit(DistanceUnit.INCH); - // myOtos.setAngularUnit(AnguleUnit.RADIANS); - myOtos.setAngularUnit(AngleUnit.DEGREES); - - // Assuming you've mounted your sensor to a robot and it's not centered, - // you can specify the offset for the sensor relative to the center of the - // robot. The units default to inches and degrees, but if you want to use - // different units, specify them before setting the offset! Note that as of - // firmware version 1.0, these values will be lost after a power cycle, so - // you will need to set them each time you power up the sensor. For example, if - // the sensor is mounted 5 inches to the left (negative X) and 10 inches - // forward (positive Y) of the center of the robot, and mounted 90 degrees - // clockwise (negative rotation) from the robot's orientation, the offset - // would be {-5, 10, -90}. These can be any value, even the angle can be - // tweaked slightly to compensate for imperfect mounting (eg. 1.3 degrees). - SparkFunOTOS.Pose2D offset = new SparkFunOTOS.Pose2D(0, 0, 0); - myOtos.setOffset(offset); - - // Here we can set the linear and angular scalars, which can compensate for - // scaling issues with the sensor measurements. Note that as of firmware - // version 1.0, these values will be lost after a power cycle, so you will - // need to set them each time you power up the sensor. They can be any value - // from 0.872 to 1.127 in increments of 0.001 (0.1%). It is recommended to - // first set both scalars to 1.0, then calibrate the angular scalar, then - // the linear scalar. To calibrate the angular scalar, spin the robot by - // multiple rotations (eg. 10) to get a precise error, then set the scalar - // to the inverse of the error. Remember that the angle wraps from -180 to - // 180 degrees, so for example, if after 10 rotations counterclockwise - // (positive rotation), the sensor reports -15 degrees, the required scalar - // would be 3600/3585 = 1.004. To calibrate the linear scalar, move the - // robot a known distance and measure the error; do this multiple times at - // multiple speeds to get an average, then set the linear scalar to the - // inverse of the error. For example, if you move the robot 100 inches and - // the sensor reports 103 inches, set the linear scalar to 100/103 = 0.971 - myOtos.setLinearScalar(1.0); - myOtos.setAngularScalar(1.0); - - // The IMU on the OTOS includes a gyroscope and accelerometer, which could - // have an offset. Note that as of firmware version 1.0, the calibration - // will be lost after a power cycle; the OTOS performs a quick calibration - // when it powers up, but it is recommended to perform a more thorough - // calibration at the start of all your OpModes. Note that the sensor must - // be completely stationary and flat during calibration! When calling - // calibrateImu(), you can specify the number of samples to take and whether - // to wait until the calibration is complete. If no parameters are provided, - // it will take 255 samples and wait until done; each sample takes about - // 2.4ms, so about 612ms total - myOtos.calibrateImu(); - - // Reset the tracking algorithm - this resets the position to the origin, - // but can also be used to recover from some rare tracking errors - myOtos.resetTracking(); - - // After resetting the tracking, the OTOS will report that the robot is at - // the origin. If your robot does not start at the origin, or you have - // another source of location information (eg. vision odometry), you can set - // the OTOS location to match and it will continue to track from there. - SparkFunOTOS.Pose2D currentPosition = new SparkFunOTOS.Pose2D(0, 0, 0); - myOtos.setPosition(currentPosition); - - // Get the hardware and firmware version - SparkFunOTOS.Version hwVersion = new SparkFunOTOS.Version(); - SparkFunOTOS.Version fwVersion = new SparkFunOTOS.Version(); - myOtos.getVersionInfo(hwVersion, fwVersion); - - telemetry.addLine("OTOS configured! Press start to get position data!"); - telemetry.addLine(); - telemetry.addLine(String.format("OTOS Hardware Version: v%d.%d", hwVersion.major, hwVersion.minor)); - telemetry.addLine(String.format("OTOS Firmware Version: v%d.%d", fwVersion.major, fwVersion.minor)); - telemetry.update(); - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorTouch.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorTouch.java deleted file mode 100644 index 3d794472..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorTouch.java +++ /dev/null @@ -1,78 +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 OpMode demonstrates how to use a REV Robotics Touch Sensor, REV Robotics Magnetic Limit Switch, or other device - * that implements the TouchSensor interface. Any touch sensor that connects its output to ground when pressed - * (known as "active low") can be configured as a "REV Touch Sensor". This includes REV's Magnetic Limit Switch. - * - * The OpMode assumes that the touch sensor is configured with a name of "sensor_touch". - * - * A REV Robotics Touch Sensor must be configured on digital port number 1, 3, 5, or 7. - * A Magnetic Limit Switch can be configured on any digital port. - * - * 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: REV touch sensor", group = "Sensor") -@Disabled -public class SensorTouch extends LinearOpMode { - TouchSensor touchSensor; // Touch sensor Object - - @Override - public void runOpMode() { - - // get a reference to our touchSensor object. - touchSensor = hardwareMap.get(TouchSensor.class, "sensor_touch"); - - // wait for the start button to be pressed. - waitForStart(); - - // while the OpMode is active, loop and read whether the sensor is being pressed. - // 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 Sensor", "Is Pressed"); - } else { - telemetry.addData("Touch Sensor", "Is Not Pressed"); - } - - telemetry.update(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityCameraFrameCapture.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityCameraFrameCapture.java deleted file mode 100644 index 69420cca..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityCameraFrameCapture.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2023 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.util.Size; -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.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; - -import java.util.Locale; - -/* - * This OpMode helps calibrate a webcam or RC phone camera, useful for AprilTag pose estimation - * with the FTC VisionPortal. It captures a camera frame (image) and stores it on the Robot Controller - * (Control Hub or RC phone), with each press of the gamepad button X (or Square). - * Full calibration instructions are here: - * - * https://ftc-docs.firstinspires.org/camera-calibration - * - * In Android Studio, copy this class into your "teamcode" folder with a new name. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list. - * - * In OnBot Java, use "Add File" to add this OpMode from the list of Samples. - */ - -@TeleOp(name = "Utility: Camera Frame Capture", group = "Utility") -@Disabled -public class UtilityCameraFrameCapture extends LinearOpMode -{ - /* - * EDIT THESE PARAMETERS AS NEEDED - */ - final boolean USING_WEBCAM = false; - final BuiltinCameraDirection INTERNAL_CAM_DIR = BuiltinCameraDirection.BACK; - final int RESOLUTION_WIDTH = 640; - final int RESOLUTION_HEIGHT = 480; - - // Internal state - boolean lastX; - int frameCount; - long capReqTime; - - @Override - public void runOpMode() - { - VisionPortal portal; - - if (USING_WEBCAM) - { - portal = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .setCameraResolution(new Size(RESOLUTION_WIDTH, RESOLUTION_HEIGHT)) - .build(); - } - else - { - portal = new VisionPortal.Builder() - .setCamera(INTERNAL_CAM_DIR) - .setCameraResolution(new Size(RESOLUTION_WIDTH, RESOLUTION_HEIGHT)) - .build(); - } - - while (!isStopRequested()) - { - boolean x = gamepad1.x; - - if (x && !lastX) - { - portal.saveNextFrameRaw(String.format(Locale.US, "CameraFrameCapture-%06d", frameCount++)); - capReqTime = System.currentTimeMillis(); - } - - lastX = x; - - telemetry.addLine("######## Camera Capture Utility ########"); - telemetry.addLine(String.format(Locale.US, " > Resolution: %dx%d", RESOLUTION_WIDTH, RESOLUTION_HEIGHT)); - telemetry.addLine(" > Press X (or Square) to capture a frame"); - telemetry.addData(" > Camera Status", portal.getCameraState()); - - if (capReqTime != 0) - { - telemetry.addLine("\nCaptured Frame!"); - } - - if (capReqTime != 0 && System.currentTimeMillis() - capReqTime > 1000) - { - capReqTime = 0; - } - - telemetry.update(); - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityOctoQuadConfigMenu.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityOctoQuadConfigMenu.java deleted file mode 100644 index a962919f..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityOctoQuadConfigMenu.java +++ /dev/null @@ -1,812 +0,0 @@ -/* - * Copyright (c) 2024 DigitalChickenLabs - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.hardware.digitalchickenlabs.OctoQuad; -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.Gamepad; - -import org.firstinspires.ftc.robotcore.external.Telemetry; - -import java.util.ArrayList; -import java.util.Stack; - -/* - * This OpMode illustrates how to use the DigitalChickenLabs OctoQuad Quadrature Encoder & Pulse Width Interface Module. - * - * The OctoQuad has 8 input channels that can used to read either Relative Quadrature Encoders or Pulse-Width Absolute Encoder inputs. - * Relative Quadrature encoders are found on most FTC motors, and some stand-alone position sensors like the REV Thru-Bore encoder. - * Pulse-Width encoders are less common. The REV Thru-Bore encoder can provide its absolute position via a variable pulse width, - * as can several sonar rangefinders such as the MaxBotix MB1000 series. - * - * This OpMode assumes that the OctoQuad is attached to an I2C interface named "octoquad" in the robot configuration. - * - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list - * - * Select, Init and run the "OctoQuad Configuration Tool" OpMode - * Read the blue User-Interface tips at the top of the telemetry screen. - * Use the UI buttons to navigate the menu and make any desired changes to the OctoQuad configuration. - * Use the Program Settings To FLASH option to make any changes permanent. - * - * See the sensor's product page: https://www.tindie.com/products/digitalchickenlabs/octoquad-8ch-quadrature-pulse-width-decoder/ - */ -@TeleOp(name = "OctoQuad Configuration Tool", group="OctoQuad") -@Disabled -public class UtilityOctoQuadConfigMenu extends LinearOpMode -{ - TelemetryMenu.MenuElement rootMenu = new TelemetryMenu.MenuElement("OctoQuad Config Menu", true); - TelemetryMenu.MenuElement menuHwInfo = new TelemetryMenu.MenuElement("Hardware Information", false); - TelemetryMenu.EnumOption optionI2cResetMode; - TelemetryMenu.EnumOption optionChannelBankConfig; - - TelemetryMenu.MenuElement menuEncoderDirections = new TelemetryMenu.MenuElement("Set Encoder Directions", false); - TelemetryMenu.BooleanOption[] optionsEncoderDirections = new TelemetryMenu.BooleanOption[OctoQuad.NUM_ENCODERS]; - - TelemetryMenu.MenuElement menuVelocityIntervals = new TelemetryMenu.MenuElement("Velocity Measurement Intervals", false); - TelemetryMenu.IntegerOption[] optionsVelocityIntervals = new TelemetryMenu.IntegerOption[OctoQuad.NUM_ENCODERS]; - - TelemetryMenu.MenuElement menuAbsParams = new TelemetryMenu.MenuElement("Abs. Encoder Pulse Width Params", false); - TelemetryMenu.IntegerOption[] optionsAbsParamsMax = new TelemetryMenu.IntegerOption[OctoQuad.NUM_ENCODERS]; - TelemetryMenu.IntegerOption[] optionsAbsParamsMin = new TelemetryMenu.IntegerOption[OctoQuad.NUM_ENCODERS]; - - TelemetryMenu.OptionElement optionProgramToFlash; - TelemetryMenu.OptionElement optionSendToRAM; - - TelemetryMenu.StaticClickableOption optionExit; - - OctoQuad octoquad; - - boolean error = false; - - @Override - public void runOpMode() - { - octoquad = hardwareMap.getAll(OctoQuad.class).get(0); - - if(octoquad.getChipId() != OctoQuad.OCTOQUAD_CHIP_ID) - { - telemetry.addLine("Error: cannot communicate with OctoQuad. Check your wiring and configuration and try again"); - telemetry.update(); - - error = true; - } - else - { - if(octoquad.getFirmwareVersion().maj != OctoQuad.SUPPORTED_FW_VERSION_MAJ) - { - telemetry.addLine("Error: The OctoQuad is running a different major firmware version than this driver was built for. Cannot run configuration tool"); - telemetry.update(); - - error = true; - } - } - - if(error) - { - waitForStart(); - return; - } - - telemetry.addLine("Retrieving current configuration from OctoQuad"); - telemetry.update(); - - optionExit = new TelemetryMenu.StaticClickableOption("Exit configuration menu") - { - @Override - void onClick() // called on OpMode thread - { - requestOpModeStop(); - } - }; - - optionI2cResetMode = new TelemetryMenu.EnumOption("I2C Reset Mode", OctoQuad.I2cRecoveryMode.values(), octoquad.getI2cRecoveryMode()); - optionChannelBankConfig = new TelemetryMenu.EnumOption("Channel Bank Modes", OctoQuad.ChannelBankConfig.values(), octoquad.getChannelBankConfig()); - - menuHwInfo.addChild(new TelemetryMenu.StaticItem("Board Firmware: v" + octoquad.getFirmwareVersion())); - //menuHwInfo.addChild(new TelemetryMenu.StaticItem("Board unique ID: FIXME")); - - for(int i = 0; i < OctoQuad.NUM_ENCODERS; i++) - { - optionsEncoderDirections[i] = new TelemetryMenu.BooleanOption( - String.format("Encoder %d direction", i), - octoquad.getSingleEncoderDirection(i) == OctoQuad.EncoderDirection.REVERSE, - "-", - "+"); - } - menuEncoderDirections.addChildren(optionsEncoderDirections); - - for(int i = 0; i < OctoQuad.NUM_ENCODERS; i++) - { - optionsVelocityIntervals[i] = new TelemetryMenu.IntegerOption( - String.format("Chan %d velocity intvl", i), - OctoQuad.MIN_VELOCITY_MEASUREMENT_INTERVAL_MS, - OctoQuad.MAX_VELOCITY_MEASUREMENT_INTERVAL_MS, - octoquad.getSingleVelocitySampleInterval(i)); - } - menuVelocityIntervals.addChildren(optionsVelocityIntervals); - - for(int i = 0; i < OctoQuad.NUM_ENCODERS; i++) - { - OctoQuad.ChannelPulseWidthParams params = octoquad.getSingleChannelPulseWidthParams(i); - - optionsAbsParamsMax[i] = new TelemetryMenu.IntegerOption( - String.format("Chan %d max pulse length", i), - OctoQuad.MIN_PULSE_WIDTH_US, - OctoQuad.MAX_PULSE_WIDTH_US, - params.max_length_us); - - optionsAbsParamsMin[i] = new TelemetryMenu.IntegerOption( - String.format("Chan %d min pulse length", i), - OctoQuad.MIN_PULSE_WIDTH_US, - OctoQuad.MAX_PULSE_WIDTH_US, - params.min_length_us); - } - menuAbsParams.addChildren(optionsAbsParamsMin); - menuAbsParams.addChildren(optionsAbsParamsMax); - - optionProgramToFlash = new TelemetryMenu.OptionElement() - { - String name = "Program Settings to FLASH"; - long lastClickTime = 0; - - @Override - protected String getDisplayText() - { - if(lastClickTime == 0) - { - return name; - } - else - { - if(System.currentTimeMillis() - lastClickTime < 1000) - { - return name + " **OK**"; - } - else - { - lastClickTime = 0; - return name; - } - } - } - - @Override - void onClick() - { - sendSettingsToRam(); - octoquad.saveParametersToFlash(); - lastClickTime = System.currentTimeMillis(); - } - }; - - optionSendToRAM = new TelemetryMenu.OptionElement() - { - String name = "Send Settings to RAM"; - long lastClickTime = 0; - - @Override - protected String getDisplayText() - { - if(lastClickTime == 0) - { - return name; - } - else - { - if(System.currentTimeMillis() - lastClickTime < 1000) - { - return name + " **OK**"; - } - else - { - lastClickTime = 0; - return name; - } - } - } - - @Override - void onClick() - { - sendSettingsToRam(); - lastClickTime = System.currentTimeMillis(); - } - }; - - rootMenu.addChild(menuHwInfo); - rootMenu.addChild(optionI2cResetMode); - rootMenu.addChild(optionChannelBankConfig); - rootMenu.addChild(menuEncoderDirections); - rootMenu.addChild(menuVelocityIntervals); - rootMenu.addChild(menuAbsParams); - rootMenu.addChild(optionProgramToFlash); - rootMenu.addChild(optionSendToRAM); - rootMenu.addChild(optionExit); - - TelemetryMenu menu = new TelemetryMenu(telemetry, rootMenu); - - while (!isStopRequested()) - { - menu.loop(gamepad1); - telemetry.update(); - sleep(20); - } - } - - void sendSettingsToRam() - { - for(int i = 0; i < OctoQuad.NUM_ENCODERS; i++) - { - octoquad.setSingleEncoderDirection(i, optionsEncoderDirections[i].getValue() ? OctoQuad.EncoderDirection.REVERSE : OctoQuad.EncoderDirection.FORWARD); - octoquad.setSingleVelocitySampleInterval(i, optionsVelocityIntervals[i].getValue()); - - OctoQuad.ChannelPulseWidthParams params = new OctoQuad.ChannelPulseWidthParams(); - params.max_length_us = optionsAbsParamsMax[i].getValue(); - params.min_length_us = optionsAbsParamsMin[i].getValue(); - - octoquad.setSingleChannelPulseWidthParams(i, params); - } - - octoquad.setI2cRecoveryMode((OctoQuad.I2cRecoveryMode) optionI2cResetMode.getValue()); - octoquad.setChannelBankConfig((OctoQuad.ChannelBankConfig) optionChannelBankConfig.getValue()); - } - - /* - * Copyright (c) 2023 OpenFTC Team - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - - public static class TelemetryMenu - { - private final MenuElement root; - private MenuElement currentLevel; - - private boolean dpadUpPrev; - private boolean dpadDnPrev; - private boolean dpadRightPrev; - private boolean dpadLeftPrev; - private boolean xPrev; - private boolean lbPrev; - - private int selectedIdx = 0; - private Stack selectedIdxStack = new Stack<>(); - - private final Telemetry telemetry; - - /** - * TelemetryMenu constructor - * @param telemetry pass in 'telemetry' from your OpMode - * @param root the root menu element - */ - public TelemetryMenu(Telemetry telemetry, MenuElement root) - { - this.root = root; - this.currentLevel = root; - this.telemetry = telemetry; - - telemetry.setDisplayFormat(Telemetry.DisplayFormat.HTML); - telemetry.setMsTransmissionInterval(50); - } - - /** - * Call this from inside your loop to put the current menu state into - * telemetry, and process gamepad inputs for navigating the menu - * @param gamepad the gamepad you want to use to navigate the menu - */ - public void loop(Gamepad gamepad) - { - // Capture current state of the gamepad buttons we care about; - // We can only look once or we risk a race condition - boolean dpadUp = gamepad.dpad_up; - boolean dpadDn = gamepad.dpad_down; - boolean dpadRight = gamepad.dpad_right; - boolean dpadLeft = gamepad.dpad_left; - boolean x = gamepad.x; - boolean lb = gamepad.left_bumper; - - // Figure out who our children our at this level - // and figure out which item is currently highlighted - // with the selection pointer - ArrayList children = currentLevel.children(); - Element currentSelection = children.get(selectedIdx); - - // Left and right are inputs to the selected item (if it's an Option) - if (currentSelection instanceof OptionElement) - { - if (dpadRight && !dpadRightPrev) // rising edge - { - ((OptionElement) currentSelection).onRightInput(); - } - else if (dpadLeft && !dpadLeftPrev) // rising edge - { - ((OptionElement) currentSelection).onLeftInput(); - } - } - - // Up and down navigate the current selection pointer - if (dpadUp && !dpadUpPrev) // rising edge - { - selectedIdx--; // Move selection pointer up - } - else if (dpadDn && !dpadDnPrev) // rising edge - { - selectedIdx++; // Move selection pointer down - } - - // Make selected index sane (don't let it go out of bounds) :eyes: - if (selectedIdx >= children.size()) - { - selectedIdx = children.size()-1; - } - else if (selectedIdx < 0) - { - selectedIdx = 0; - } - - // Select: either enter submenu or input to option - else if (x && !xPrev) // rising edge - { - // Select up element - if (currentSelection instanceof SpecialUpElement) - { - // We can only go up if we're not at the root level - if (currentLevel != root) - { - // Restore selection pointer to where it was before - selectedIdx = selectedIdxStack.pop(); - - // Change to the parent level - currentLevel = currentLevel.parent(); - } - } - // Input to option - else if (currentSelection instanceof OptionElement) - { - ((OptionElement) currentSelection).onClick(); - } - // Enter submenu - else if (currentSelection instanceof MenuElement) - { - // Save our current selection pointer so we can restore it - // later if the user navigates back up a level - selectedIdxStack.push(selectedIdx); - - // We have no idea what's in the submenu :monkey: so best to - // just set the selection pointer to the first element - selectedIdx = 0; - - // Now the current level becomes the submenu that the selection - // pointer was on - currentLevel = (MenuElement) currentSelection; - } - } - - // Go up a level - else if (lb && !lbPrev) - { - // We can only go up if we're not at the root level - if (currentLevel != root) - { - // Restore selection pointer to where it was before - selectedIdx = selectedIdxStack.pop(); - - // Change to the parent level - currentLevel = currentLevel.parent(); - } - } - - // Save the current button states so that we can look for - // the rising edge the next time around the loop :) - dpadUpPrev = dpadUp; - dpadDnPrev = dpadDn; - dpadRightPrev = dpadRight; - dpadLeftPrev = dpadLeft; - xPrev = x; - lbPrev = lb; - - // Start building the text display. - // First, we add the static directions for gamepad operation - StringBuilder builder = new StringBuilder(); - builder.append(""); - builder.append("Navigate items.....dpad up/down\n") - .append("Select.............X or Square\n") - .append("Edit option........dpad left/right\n") - .append("Up one level.......left bumper\n"); - builder.append(""); - builder.append("\n"); - - // Now actually add the menu options. We start by adding the name of the current menu level. - builder.append(""); - builder.append("Current Menu: ").append(currentLevel.name).append("\n"); - - // Now we loop through all the child elements of this level and add them - for (int i = 0; i < children.size(); i++) - { - // If the selection pointer is at this index, put a green dot in the box :) - if (selectedIdx == i) - { - builder.append("[] "); - } - // Otherwise, just put an empty box - else - { - builder.append("[ ] "); - } - - // Figure out who the selection pointer is pointing at :eyes: - Element e = children.get(i); - - // If it's pointing at a submenu, indicate that it's a submenu to the user - // by prefixing "> " to the name. - if (e instanceof MenuElement) - { - builder.append("> "); - } - - // Finally, add the element's name - builder.append(e.getDisplayText()); - - // We musn't forget the newline - builder.append("\n"); - } - - // Don't forget to close the font tag either - builder.append(""); - - // Build the string!!!! :nerd: - String menu = builder.toString(); - - // Add it to telemetry - telemetry.addLine(menu); - } - - public static class MenuElement extends Element - { - private String name; - private ArrayList children = new ArrayList<>(); - - /** - * Create a new MenuElement; may either be the root menu, or a submenu (set isRoot accordingly) - * @param name the name for this menu - * @param isRoot whether this is a root menu, or a submenu - */ - public MenuElement(String name, boolean isRoot) - { - this.name = name; - - // If it's not the root menu, we add the up one level option as the first element - if (!isRoot) - { - children.add(new SpecialUpElement()); - } - } - - /** - * Add a child element to this menu (may either be an Option or another menu) - * @param child the child element to add - */ - public void addChild(Element child) - { - child.setParent(this); - children.add(child); - } - - /** - * Add multiple child elements to this menu (may either be option, or another menu) - * @param children the children to add - */ - public void addChildren(Element[] children) - { - for (Element e : children) - { - e.setParent(this); - this.children.add(e); - } - } - - @Override - protected String getDisplayText() - { - return name; - } - - private ArrayList children() - { - return children; - } - } - - public static abstract class OptionElement extends Element - { - /** - * Override this to get notified when the element is clicked - */ - void onClick() {} - - /** - * Override this to get notified when the element gets a "left edit" input - */ - protected void onLeftInput() {} - - /** - * Override this to get notified when the element gets a "right edit" input - */ - protected void onRightInput() {} - } - - public static class EnumOption extends OptionElement - { - protected int idx = 0; - protected Enum[] e; - protected String name; - - public EnumOption(String name, Enum[] e) - { - this.e = e; - this.name = name; - } - - public EnumOption(String name, Enum[] e, Enum def) - { - this(name, e); - idx = def.ordinal(); - } - - @Override - public void onLeftInput() - { - idx++; - - if(idx > e.length-1) - { - idx = 0; - } - } - - @Override - public void onRightInput() - { - idx--; - - if(idx < 0) - { - idx = e.length-1; - } - } - - @Override - public void onClick() - { - //onRightInput(); - } - - @Override - protected String getDisplayText() - { - return String.format("%s: %s", name, e[idx].name()); - } - - public Enum getValue() - { - return e[idx]; - } - } - - public static class IntegerOption extends OptionElement - { - protected int i; - protected int min; - protected int max; - protected String name; - - public IntegerOption(String name, int min, int max, int def) - { - this.name = name; - this.min = min; - this.max = max; - this.i = def; - } - - @Override - public void onLeftInput() - { - i--; - - if(i < min) - { - i = max; - } - } - - @Override - public void onRightInput() - { - i++; - - if(i > max) - { - i = min; - } - } - - @Override - public void onClick() - { - //onRightInput(); - } - - @Override - protected String getDisplayText() - { - return String.format("%s: %d", name, i); - } - - public int getValue() - { - return i; - } - } - - static class BooleanOption extends OptionElement - { - private String name; - private boolean val = true; - - private String customTrue; - private String customFalse; - - BooleanOption(String name, boolean def) - { - this.name = name; - this.val = def; - } - - BooleanOption(String name, boolean def, String customTrue, String customFalse) - { - this(name, def); - this.customTrue = customTrue; - this.customFalse = customFalse; - } - - @Override - public void onLeftInput() - { - val = !val; - } - - @Override - public void onRightInput() - { - val = !val; - } - - @Override - public void onClick() - { - val = !val; - } - - @Override - protected String getDisplayText() - { - String valStr; - - if(customTrue != null && customFalse != null) - { - valStr = val ? customTrue : customFalse; - } - else - { - valStr = val ? "true" : "false"; - } - - return String.format("%s: %s", name, valStr); - } - - public boolean getValue() - { - return val; - } - } - - /** - * - */ - public static class StaticItem extends OptionElement - { - private String name; - - public StaticItem(String name) - { - this.name = name; - } - - @Override - protected String getDisplayText() - { - return name; - } - } - - public static abstract class StaticClickableOption extends OptionElement - { - private String name; - - public StaticClickableOption(String name) - { - this.name = name; - } - - abstract void onClick(); - - @Override - protected String getDisplayText() - { - return name; - } - } - - private static abstract class Element - { - private MenuElement parent; - - protected void setParent(MenuElement parent) - { - this.parent = parent; - } - - protected MenuElement parent() - { - return parent; - } - - protected abstract String getDisplayText(); - } - - private static class SpecialUpElement extends Element - { - @Override - protected String getDisplayText() - { - return ".. ↰ Up One Level"; - } - } - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md deleted file mode 100644 index 326978de..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md +++ /dev/null @@ -1,45 +0,0 @@ - -## Caution -No Team-specific code should be placed or modified in this ``.../samples`` folder. - -Samples should be Copied from here, and then Pasted into the team's -[/TeamCode/src/main/java/org/firstinspires/ftc/teamcode](../../../../../../../../../../TeamCode/src/main/java/org/firstinspires/ftc/teamcode) - folder, using the Android Studio cut and paste commands. This automatically changes all file and -class names to be consistent. From there, the sample can be modified to suit the team's needs. - -For more detailed instructions see the /teamcode readme. - -### Naming of Samples - -To gain a better understanding of how the samples are organized, and how to interpret the -naming system, it will help to understand the conventions that were used during their creation. - -These conventions are described (in detail) in the sample_conventions.md file in this folder. - -To summarize: A range of different samples classes will reside in the java/external/samples. -The class names will follow a naming convention which indicates the purpose of each class. -The prefix of the name will be one of the following: - -Basic: This is a minimally functional OpMode used to illustrate the skeleton/structure - of a particular style of OpMode. These are bare bones examples. - -Sensor: This is a Sample OpMode that shows how to use a specific sensor. - It is not intended to drive a functioning robot, it is simply showing the minimal code - required to read and display the sensor values. - -Robot: This is a Sample OpMode that assumes a simple two-motor (differential) drive base. - It may be used to provide a common baseline driving OpMode, or - to demonstrate how a particular sensor or concept can be used to navigate. - -Concept: This is a sample OpMode that illustrates performing a specific function or concept. - These may be complex, but their operation should be explained clearly in the comments, - or the comments should reference an external doc, guide or tutorial. - Each OpMode should try to only demonstrate a single concept so they are easy to - locate based on their name. These OpModes may not produce a drivable robot. - -After the prefix, other conventions will apply: - -* Sensor class names are constructed as: Sensor - Company - Type -* Robot class names are constructed as: Robot - Mode - Action - OpModetype -* Concept class names are constructed as: Concept - Topic - OpModetype - diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md deleted file mode 100644 index e85e6254..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md +++ /dev/null @@ -1,113 +0,0 @@ -## Sample Class/Opmode conventions -#### V 1.1.0 8/9/2017 - -This document defines the FTC Sample OpMode and Class conventions. - -### OpMode Name - -To gain a better understanding of how the samples are organized, and how to interpret the -naming system, it will help to understand the conventions that were used during their creation. - -To summarize: A range of different samples classes will reside in the java/external/samples. -The class names will follow a naming convention which indicates the purpose of each class. -The prefix of the name will be one of the following: - -Basic: This is a minimally functional OpMode used to illustrate the skeleton/structure - of a particular style of OpMode. These are bare bones examples. - -Sensor: This is a Sample OpMode that shows how to use a specific sensor. - It is not intended to drive a functioning robot, it is simply showing the minimal code - required to read and display the sensor values. - -Robot: This is a Sample OpMode that assumes a simple two-motor (differential) drive base. - It may be used to provide a common baseline driving OpMode, or - to demonstrate how a particular sensor or concept can be used to navigate. - -Concept: This is a sample OpMode that illustrates performing a specific function or concept. - These may be complex, but their operation should be explained clearly in the comments, - or the comments should reference an external doc, guide or tutorial. - Each OpMode should try to only demonstrate a single concept so they are easy to - locate based on their name. These OpModes may not produce a drivable robot. - -Utility: This sample type is provided as a useful tool, or aide, to perform some specific development task. - It is not expected to be something you would include in your own robot code. - To use the tool, comment out the @Disabled annotation and build the App. - Read the comments found in the sample for an explanation of its intended use. - -After the prefix, other conventions will apply: - -* Sensor class names should constructed as: Sensor - Company - Type -* Robot class names should be constructed as: Robot - Mode - Action - OpModetype -* Concept class names should be constructed as: Concept - Topic - OpModetype - -### Sample OpMode Content/Style - -Code is formatted as per the Google Style Guide: - -https://google.github.io/styleguide/javaguide.html - -With “Sensor” and “Hardware” samples, the code should demonstrate the essential function, -and not be embellished with too much additional “clever” code. If a sensor has special -addressing needs, or has a variety of modes or outputs, these should be demonstrated as -simply as possible. - -Special programming methods, or robot control techniques should be reserved for “Concept” Samples, -and where possible, Samples should strive to only demonstrate a single concept, -eg: State machine coding, or a User Menu system, and not combine them into a single “all inclusive” -sample. This will prevent an “all inclusive” Sample being deleted just because one part of it -becomes obsolete. - -### Device Configuration Names - -The following device names are used in the external samples - -** Motors: -left_drive -right_drive -left_arm - -** Servos: -left_hand -right_hand -arm -claw - -** Sensors: -sensor_color -sensor_ir -sensor_light -sensor_ods -sensor_range -sensor_touch -sensor_color_distance -sensor_digital -digin -digout - -** Localization: -compass -gyro -imu -navx - -### Device Object Names - -Device Object names should use the same words as the device’s configuration name, but they -should be re-structured to be a suitable Java variable name. This should keep the same word order, -but adopt the style of beginning with a lower case letter, and then each subsequent word -starting with an upper case letter. - -Eg: from the examples above: tool, leftMotor, rightClawServo, rearLightSensor. - -Note: Sometimes it’s helpful to put the device type first, followed by the variant. -eg: motorLeft and motorRight, but this should only be done if the same word order -is used on the device configuration name. - -### OpMode code Comments - -Sample comments should read like normal code comments, that is, as an explanation of what the -sample code is doing. They should NOT be directives to the user, -like: “insert your joystick code here” as these comments typically aren’t -detailed enough to be useful. They also often get left in the code and become garbage. - -Instead, an example of the joystick code should be shown with a comment describing what it is doing. diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcOpModeRegister.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcOpModeRegister.java deleted file mode 100644 index ceab67db..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcOpModeRegister.java +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2014, 2015 Qualcomm Technologies Inc - -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 Qualcomm Technologies Inc 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 com.qualcomm.robotcore.eventloop.opmode.OpModeManager; -import com.qualcomm.robotcore.eventloop.opmode.OpModeRegister; - -/** - * {@link FtcOpModeRegister} is responsible for registering OpModes for use in an FTC game. - * @see #register(OpModeManager) - */ -public class FtcOpModeRegister implements OpModeRegister { - - /** - * {@link #register(OpModeManager)} is called by the SDK game in order to register - * OpMode classes or instances that will participate in an FTC game. - * - * There are two mechanisms by which an OpMode may be registered. - * - * 1) The preferred method is by means of class annotations in the OpMode itself. - * See, for example the class annotations in {@link org.firstinspires.ftc.robotcontroller.external.samples.ConceptNullOp}. - * - * 2) The other, retired, method is to modify this {@link #register(OpModeManager)} - * method to include explicit calls to OpModeManager.register(). - * This method of modifying this file directly is discouraged, as it - * makes updates to the SDK harder to integrate into your code. - * - * @param manager the object which contains methods for carrying out OpMode registrations - * - * @see com.qualcomm.robotcore.eventloop.opmode.TeleOp - * @see com.qualcomm.robotcore.eventloop.opmode.Autonomous - */ - public void register(OpModeManager manager) { - - /** - * Any manual OpMode class registrations should go here. - */ - } -} diff --git a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java deleted file mode 100644 index 3f1f77ce..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java +++ /dev/null @@ -1,845 +0,0 @@ -/* Copyright (c) 2014, 2015 Qualcomm Technologies Inc - -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 Qualcomm Technologies Inc 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.app.ActionBar; -import android.app.Activity; -import android.app.ActivityManager; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; -import android.net.wifi.WifiManager; -import android.os.Bundle; -import android.os.IBinder; -import android.preference.PreferenceManager; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.view.WindowManager; -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.ProgrammingWebHandlers; -import com.google.blocks.ftcrobotcontroller.runtime.BlocksOpMode; -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; -import com.qualcomm.ftccommon.FtcRobotControllerService.FtcRobotControllerBinder; -import com.qualcomm.ftccommon.FtcRobotControllerSettingsActivity; -import com.qualcomm.ftccommon.LaunchActivityConstantsList; -import com.qualcomm.ftccommon.LaunchActivityConstantsList.RequestCode; -import com.qualcomm.ftccommon.Restarter; -import com.qualcomm.ftccommon.UpdateUI; -import com.qualcomm.ftccommon.configuration.EditParameters; -import com.qualcomm.ftccommon.configuration.FtcLoadFileActivity; -import com.qualcomm.ftccommon.configuration.RobotConfigFile; -import com.qualcomm.ftccommon.configuration.RobotConfigFileManager; -import com.qualcomm.ftcrobotcontroller.BuildConfig; -import com.qualcomm.ftcrobotcontroller.R; -import com.qualcomm.hardware.HardwareFactory; -import com.qualcomm.robotcore.eventloop.EventLoopManager; -import com.qualcomm.robotcore.eventloop.opmode.FtcRobotControllerServiceState; -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.robot.Robot; -import com.qualcomm.robotcore.robot.RobotState; -import com.qualcomm.robotcore.util.ClockWarningSource; -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 org.firstinspires.ftc.ftccommon.external.SoundPlayingRobotMonitor; -import org.firstinspires.ftc.ftccommon.internal.AnnotatedHooksClassFilter; -import org.firstinspires.ftc.ftccommon.internal.FtcRobotControllerWatchdogService; -import org.firstinspires.ftc.ftccommon.internal.ProgramAndManageActivity; -import org.firstinspires.ftc.onbotjava.ExternalLibraries; -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.opmode.OnBotJavaHelper; -import org.firstinspires.ftc.robotcore.internal.system.AppAliveNotifier; -import org.firstinspires.ftc.robotcore.internal.system.AppUtil; -import org.firstinspires.ftc.robotcore.internal.system.Assert; -import org.firstinspires.ftc.robotcore.internal.system.PreferencesHelper; -import org.firstinspires.ftc.robotcore.internal.system.ServiceController; -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.robotserver.internal.programmingmode.ProgrammingModeManager; -import org.firstinspires.inspection.RcInspectionActivity; -import org.threeten.bp.YearMonth; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.FileNotFoundException; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -@SuppressWarnings("WeakerAccess") -public class FtcRobotControllerActivity extends Activity - { - public static final String TAG = "RCActivity"; - public String getTag() { return TAG; } - - private static final int REQUEST_CONFIG_WIFI_CHANNEL = 1; - private static final int NUM_GAMEPADS = 2; - - protected WifiManager.WifiLock wifiLock; - protected RobotConfigFileManager cfgFileMgr; - - private OnBotJavaHelper onBotJavaHelper; - - protected ProgrammingModeManager programmingModeManager; - - protected UpdateUI.Callback callback; - protected Context context; - protected Utility utility; - protected StartResult prefRemoterStartResult = new StartResult(); - protected StartResult deviceNameStartResult = new StartResult(); - protected PreferencesHelper preferencesHelper; - protected final SharedPreferencesListener sharedPreferencesListener = new SharedPreferencesListener(); - - protected ImageButton buttonMenu; - protected TextView textDeviceName; - protected TextView textNetworkConnectionStatus; - protected TextView textRobotStatus; - protected TextView[] textGamepad = new TextView[NUM_GAMEPADS]; - protected TextView textOpMode; - protected TextView textErrorMessage; - protected ImmersiveMode immersion; - - protected UpdateUI updateUI; - protected Dimmer dimmer; - protected LinearLayout entireScreenLayout; - - protected FtcRobotControllerService controllerService; - protected NetworkType networkType; - - 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() { - requestRobotRestart(); - } - - } - - protected boolean serviceShouldUnbind = false; - protected ServiceConnection connection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - FtcRobotControllerBinder binder = (FtcRobotControllerBinder) service; - onServiceBind(binder.getService()); - } - - @Override - public void onServiceDisconnected(ComponentName name) { - RobotLog.vv(FtcRobotControllerService.TAG, "%s.controllerService=null", TAG); - controllerService = null; - } - }; - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - - if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) { - UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - RobotLog.vv(TAG, "ACTION_USB_DEVICE_ATTACHED: %s", usbDevice.getDeviceName()); - - if (usbDevice != null) { // paranoia - // We might get attachment notifications before the event loop is set up, so - // we hold on to them and pass them along only when we're good and ready. - if (receivedUsbAttachmentNotifications != null) { // *total* paranoia - receivedUsbAttachmentNotifications.add(usbDevice); - passReceivedUsbAttachmentsToEventLoop(); - } - } - } - } - - protected void passReceivedUsbAttachmentsToEventLoop() { - if (this.eventLoop != null) { - for (;;) { - UsbDevice usbDevice = receivedUsbAttachmentNotifications.poll(); - if (usbDevice == null) - break; - this.eventLoop.onUsbDeviceAttached(usbDevice); - } - } - else { - // Paranoia: we don't want the pending list to grow without bound when we don't - // (yet) have an event loop - while (receivedUsbAttachmentNotifications.size() > 100) { - receivedUsbAttachmentNotifications.poll(); - } - } - } - - /** - * 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 - - // 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()) { - // Double-sure check that we can talk to the DB over the serial TTY - AndroidBoard.getInstance().getAndroidBoardIsPresentPin().setState(true); - } - - context = this; - utility = new Utility(this); - - DeviceNameManagerFactory.getInstance().start(deviceNameStartResult); - - PreferenceRemoterRC.getInstance().start(prefRemoterStartResult); - - receivedUsbAttachmentNotifications = new ConcurrentLinkedQueue(); - eventLoop = null; - - setContentView(R.layout.activity_ftc_controller); - - preferencesHelper = new PreferencesHelper(TAG, context); - preferencesHelper.writeBooleanPrefIfDifferent(context.getString(R.string.pref_rc_connected), true); - preferencesHelper.getSharedPreferences().registerOnSharedPreferenceChangeListener(sharedPreferencesListener); - - // Check if this RC app is from a later FTC season than what was installed previously - int ftcSeasonYearOfPreviouslyInstalledRc = preferencesHelper.readInt(getString(R.string.pref_ftc_season_year_of_current_rc), 0); - int ftcSeasonYearOfCurrentlyInstalledRc = AppUtil.getInstance().getFtcSeasonYear(AppUtil.getInstance().getLocalSdkBuildMonth()).getValue(); - if (ftcSeasonYearOfCurrentlyInstalledRc > ftcSeasonYearOfPreviouslyInstalledRc) { - preferencesHelper.writeIntPrefIfDifferent(getString(R.string.pref_ftc_season_year_of_current_rc), ftcSeasonYearOfCurrentlyInstalledRc); - // Since it's a new FTC season, we should reset certain settings back to their default values. - preferencesHelper.writeBooleanPrefIfDifferent(getString(R.string.pref_warn_about_2_4_ghz_band), true); - preferencesHelper.writeBooleanPrefIfDifferent(getString(R.string.pref_warn_about_obsolete_software), true); - preferencesHelper.writeBooleanPrefIfDifferent(getString(R.string.pref_warn_about_mismatched_app_versions), true); - preferencesHelper.writeBooleanPrefIfDifferent(getString(R.string.pref_warn_about_incorrect_clocks), true); - } - - entireScreenLayout = (LinearLayout) findViewById(R.id.entire_screen); - buttonMenu = (ImageButton) findViewById(R.id.menu_buttons); - buttonMenu.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - 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); - AnnotatedHooksClassFilter.getInstance().callOnCreateMenuMethods( - FtcRobotControllerActivity.this, popupMenu.getMenu()); - popupMenu.show(); - } - }); - - updateMonitorLayout(getResources().getConfiguration()); - - BlocksOpMode.setActivityAndWebView(this, (WebView) findViewById(R.id.webViewBlocksRuntime)); - - ExternalLibraries.getInstance().onCreate(); - onBotJavaHelper = new OnBotJavaHelperImpl(); - - /* - * 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(onBotJavaHelper); - ClassManagerFactory.registerFilters(); - ClassManagerFactory.processAllClasses(); - } - - cfgFileMgr = new RobotConfigFileManager(this); - - // Clean up 'dirty' status after a possible crash - RobotConfigFile configFile = cfgFileMgr.getActiveConfig(); - if (configFile.isDirty()) { - configFile.markClean(); - cfgFileMgr.setActiveConfig(false, configFile); - } - - textDeviceName = (TextView) findViewById(R.id.textDeviceName); - textNetworkConnectionStatus = (TextView) findViewById(R.id.textNetworkConnectionStatus); - textRobotStatus = (TextView) findViewById(R.id.textRobotStatus); - textOpMode = (TextView) findViewById(R.id.textOpMode); - textErrorMessage = (TextView) findViewById(R.id.textErrorMessage); - textGamepad[0] = (TextView) findViewById(R.id.textGamepad1); - textGamepad[1] = (TextView) findViewById(R.id.textGamepad2); - immersion = new ImmersiveMode(getWindow().getDecorView()); - dimmer = new Dimmer(this); - dimmer.longBright(); - - programmingModeManager = new ProgrammingModeManager(); - programmingModeManager.register(new ProgrammingWebHandlers()); - programmingModeManager.register(new OnBotJavaProgrammingMode()); - - updateUI = createUpdateUI(); - callback = createUICallback(updateUI); - - PreferenceManager.setDefaultValues(this, R.xml.app_settings, false); - - WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); - wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, ""); - - hittingMenuButtonBrightensScreen(); - - wifiLock.acquire(); - callback.networkConnectionUpdate(NetworkConnection.NetworkEvent.DISCONNECTED); - readNetworkType(); - ServiceController.startService(FtcRobotControllerWatchdogService.class); - bindToService(); - RobotLog.logAppInfo(); - RobotLog.logDeviceInfo(); - AndroidBoard.getInstance().logAndroidBoardInfo(); - - if (preferencesHelper.readBoolean(getString(R.string.pref_wifi_automute), false)) { - initWifiMute(true); - } - - FtcAboutActivity.setBuildTimeFromBuildConfig(BuildConfig.APP_BUILD_TIME); - - // check to see if there is a preferred Wi-Fi to use. - checkPreferredChannel(); - - AnnotatedHooksClassFilter.getInstance().callOnCreateMethods(this); - } - - protected UpdateUI createUpdateUI() { - Restarter restarter = new RobotRestarter(); - UpdateUI result = new UpdateUI(this, dimmer); - result.setRestarter(restarter); - result.setTextViews(textNetworkConnectionStatus, textRobotStatus, textGamepad, textOpMode, textErrorMessage, textDeviceName); - return result; - } - - protected UpdateUI.Callback createUICallback(UpdateUI updateUI) { - UpdateUI.Callback result = updateUI.new Callback(); - result.setStateMonitor(new SoundPlayingRobotMonitor()); - return result; - } - - @Override - protected void onStart() { - super.onStart(); - RobotLog.vv(TAG, "onStart()"); - - entireScreenLayout.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - dimmer.handleDimTimer(); - return false; - } - }); - } - - @Override - protected void onResume() { - super.onResume(); - RobotLog.vv(TAG, "onResume()"); - - // In case the user just got back from fixing their clock, refresh ClockWarningSource - ClockWarningSource.getInstance().onPossibleRcClockUpdate(); - } - - @Override - protected void onPause() { - super.onPause(); - RobotLog.vv(TAG, "onPause()"); - } - - @Override - protected void onStop() { - // Note: this gets called even when the configuration editor is launched. That is, it gets - // called surprisingly often. So, we don't actually do much here. - super.onStop(); - RobotLog.vv(TAG, "onStop()"); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - RobotLog.vv(TAG, "onDestroy()"); - - shutdownRobot(); // Ensure the robot is put away to bed - if (callback != null) callback.close(); - - 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); - if (wifiLock != null) wifiLock.release(); - if (preferencesHelper != null) preferencesHelper.getSharedPreferences().unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener); - - RobotLog.cancelWriteLogcatToDisk(); - - AnnotatedHooksClassFilter.getInstance().callOnDestroyMethods(this); - } - - protected void bindToService() { - readNetworkType(); - Intent intent = new Intent(this, FtcRobotControllerService.class); - intent.putExtra(NetworkConnectionFactory.NETWORK_CONNECTION_TYPE, networkType); - serviceShouldUnbind = bindService(intent, connection, Context.BIND_AUTO_CREATE); - } - - protected void unbindFromService() { - if (serviceShouldUnbind) { - unbindService(connection); - serviceShouldUnbind = false; - } - } - - protected void readNetworkType() { - // Control hubs are always running the access point model. Everything else, for the time - // being always runs the Wi-Fi 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_pairing_kind), networkType.toString()); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - - if (hasFocus) { - immersion.hideSystemUI(); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.ftc_robot_controller, menu); - AnnotatedHooksClassFilter.getInstance().callOnCreateMenuMethods(this, menu); - return true; - } - - private boolean isRobotRunning() { - if (controllerService == null) { - return false; - } - - Robot robot = controllerService.getRobot(); - - if ((robot == null) || (robot.eventLoopManager == null)) { - return false; - } - - RobotState robotState = robot.eventLoopManager.state; - - if (robotState != RobotState.RUNNING) { - return false; - } else { - return true; - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - - if (id == R.id.action_program_and_manage) { - if (isRobotRunning()) { - Intent programmingModeIntent = new Intent(AppUtil.getDefContext(), ProgramAndManageActivity.class); - RobotControllerWebInfo webInfo = programmingModeManager.getWebServer().getConnectionInformation(); - programmingModeIntent.putExtra(LaunchActivityConstantsList.RC_WEB_INFO, webInfo.toJson()); - startActivity(programmingModeIntent); - } else { - AppUtil.getInstance().showToast(UILocation.ONLY_LOCAL, context.getString(R.string.toastWifiUpBeforeProgrammingMode)); - } - } else if (id == R.id.action_inspection_mode) { - Intent inspectionModeIntent = new Intent(AppUtil.getDefContext(), RcInspectionActivity.class); - startActivity(inspectionModeIntent); - return true; - } else if (id == R.id.action_restart_robot) { - dimmer.handleDimTimer(); - AppUtil.getInstance().showToast(UILocation.BOTH, context.getString(R.string.toastRestartingRobot)); - requestRobotRestart(); - return true; - } - else if (id == R.id.action_configure_robot) { - EditParameters parameters = new EditParameters(); - Intent intentConfigure = new Intent(AppUtil.getDefContext(), FtcLoadFileActivity.class); - parameters.putIntent(intentConfigure); - startActivityForResult(intentConfigure, RequestCode.CONFIGURE_ROBOT_CONTROLLER.ordinal()); - } - else if (id == R.id.action_settings) { - // historical: this once erroneously used FTC_CONFIGURE_REQUEST_CODE_ROBOT_CONTROLLER - Intent settingsIntent = new Intent(AppUtil.getDefContext(), FtcRobotControllerSettingsActivity.class); - startActivityForResult(settingsIntent, RequestCode.SETTINGS_ROBOT_CONTROLLER.ordinal()); - return true; - } - else if (id == R.id.action_about) { - Intent intent = new Intent(AppUtil.getDefContext(), FtcAboutActivity.class); - startActivity(intent); - return true; - } - else if (id == R.id.action_exit_app) { - - //Clear backstack and everything to prevent edge case where VM might be - //restarted (after it was exited) if more than one activity was on the - //backstack for some reason. - finishAffinity(); - - //For lollipop and up, we can clear ourselves from the recents list too - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); - List tasks = manager.getAppTasks(); - - for (ActivityManager.AppTask task : tasks) { - task.finishAndRemoveTask(); - } - } - - // Allow the user to use the Control Hub operating system's UI, instead of relaunching the app - AppAliveNotifier.getInstance().disableAppWatchdogUntilNextAppStart(); - - //Finally, nuke the VM from orbit - AppUtil.getInstance().exitApplication(); - - return true; - } - - return super.onOptionsItemSelected(item); - } - - @Override - 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) - * 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.getString(R.string.toastWifiConfigurationComplete)); - } - } - // was some historical confusion about launch codes here, so we err safely - if (request == RequestCode.CONFIGURE_ROBOT_CONTROLLER.ordinal() || request == RequestCode.SETTINGS_ROBOT_CONTROLLER.ordinal()) { - // We always do a refresh, whether it was a cancel or an OK, for robustness - shutdownRobot(); - cfgFileMgr.getActiveConfigAndUpdateUI(); - updateUIAndRequestRobotSetup(); - } - } - - public void onServiceBind(final FtcRobotControllerService service) { - RobotLog.vv(FtcRobotControllerService.TAG, "%s.controllerService=bound", TAG); - controllerService = service; - updateUI.setControllerService(controllerService); - - controllerService.setOnBotJavaHelper(onBotJavaHelper); - - updateUIAndRequestRobotSetup(); - programmingModeManager.setState(new FtcRobotControllerServiceState() { - @NonNull - @Override - public WebServer getWebServer() { - return service.getWebServer(); - } - - @Nullable - @Override - public OnBotJavaHelper getOnBotJavaHelper() { - return service.getOnBotJavaHelper(); - } - - @Override - public EventLoopManager getEventLoopManager() { - return service.getRobot().eventLoopManager; - } - }); - - AnnotatedHooksClassFilter.getInstance().callWebHandlerRegistrarMethods(this, - service.getWebServer().getWebHandlerManager()); - } - - private void updateUIAndRequestRobotSetup() { - if (controllerService != null) { - callback.networkConnectionUpdate(controllerService.getNetworkConnectionStatus()); - callback.updateRobotStatus(controllerService.getRobotStatus()); - // 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(@Nullable Runnable runOnComplete) { - if (controllerService == null) return; - - RobotConfigFile file = cfgFileMgr.getActiveConfigAndUpdateUI(); - HardwareFactory hardwareFactory = new HardwareFactory(context); - try { - hardwareFactory.setXmlPullParser(file.getXml()); - } catch (FileNotFoundException | XmlPullParserException e) { - RobotLog.ww(TAG, e, "Unable to set configuration file %s. Falling back on noConfig.", file.getName()); - file = RobotConfigFile.noConfig(cfgFileMgr); - try { - hardwareFactory.setXmlPullParser(file.getXml()); - cfgFileMgr.setActiveConfigAndUpdateUI(false, file); - } catch (FileNotFoundException | XmlPullParserException e1) { - RobotLog.ee(TAG, e1, "Failed to fall back on noConfig"); - } - } - - OpModeRegister userOpModeRegister = createOpModeRegister(); - eventLoop = new FtcEventLoop(hardwareFactory, userOpModeRegister, callback, this); - FtcEventLoopIdle idleLoop = new FtcEventLoopIdle(hardwareFactory, userOpModeRegister, callback, this); - - controllerService.setCallback(callback); - controllerService.setupRobot(eventLoop, idleLoop, runOnComplete); - - passReceivedUsbAttachmentsToEventLoop(); - AndroidBoard.showErrorIfUnknownControlHub(); - - AnnotatedHooksClassFilter.getInstance().callOnCreateEventLoopMethods(this, eventLoop); - } - - protected OpModeRegister createOpModeRegister() { - return new FtcOpModeRegister(); - } - - private void shutdownRobot() { - if (controllerService != null) controllerService.shutdownRobot(); - } - - private void requestRobotRestart() { - AppUtil.getInstance().showToast(UILocation.BOTH, AppUtil.getDefContext().getString(R.string.toastRestartingRobot)); - // - RobotLog.clearGlobalErrorMsg(); - RobotLog.clearGlobalWarningMsg(); - shutdownRobot(); - 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() { - ActionBar actionBar = getActionBar(); - if (actionBar != null) { - actionBar.addOnMenuVisibilityListener(new ActionBar.OnMenuVisibilityListener() { - @Override - public void onMenuVisibilityChanged(boolean isVisible) { - if (isVisible) { - dimmer.handleDimTimer(); - } - } - }); - } - } - - protected class SharedPreferencesListener implements SharedPreferences.OnSharedPreferenceChangeListener { - @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/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/PermissionValidatorWrapper.java b/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/PermissionValidatorWrapper.java deleted file mode 100644 index a0094bc9..00000000 --- a/examples/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/PermissionValidatorWrapper.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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); - add(Manifest.permission.ACCESS_FINE_LOCATION); - add(Manifest.permission.READ_PHONE_STATE); - }}; - - 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.permAccessLocationExplain); - } else if (permission.equals(Manifest.permission.ACCESS_FINE_LOCATION)) { - return Misc.formatForUser(R.string.permAccessLocationExplain); - } else if (permission.equals(Manifest.permission.READ_PHONE_STATE)) { - return Misc.formatForUser(R.string.permReadPhoneState); - } - 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/examples/FtcRobotController/src/main/res/drawable-xhdpi/icon_menu.png b/examples/FtcRobotController/src/main/res/drawable-xhdpi/icon_menu.png deleted file mode 100644 index 6b9e997c..00000000 Binary files a/examples/FtcRobotController/src/main/res/drawable-xhdpi/icon_menu.png and /dev/null differ diff --git a/examples/FtcRobotController/src/main/res/drawable-xhdpi/icon_robotcontroller.png b/examples/FtcRobotController/src/main/res/drawable-xhdpi/icon_robotcontroller.png deleted file mode 100644 index 022552f4..00000000 Binary files a/examples/FtcRobotController/src/main/res/drawable-xhdpi/icon_robotcontroller.png and /dev/null differ diff --git a/examples/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml b/examples/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml deleted file mode 100644 index 6524f948..00000000 --- a/examples/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/FtcRobotController/src/main/res/menu/ftc_robot_controller.xml b/examples/FtcRobotController/src/main/res/menu/ftc_robot_controller.xml deleted file mode 100644 index 657c1aac..00000000 --- a/examples/FtcRobotController/src/main/res/menu/ftc_robot_controller.xml +++ /dev/null @@ -1,78 +0,0 @@ - - -

- - - - - - - - - - - - - - - diff --git a/examples/FtcRobotController/src/main/res/raw/gold.wav b/examples/FtcRobotController/src/main/res/raw/gold.wav deleted file mode 100644 index 3a7baf88..00000000 Binary files a/examples/FtcRobotController/src/main/res/raw/gold.wav and /dev/null differ diff --git a/examples/FtcRobotController/src/main/res/raw/silver.wav b/examples/FtcRobotController/src/main/res/raw/silver.wav deleted file mode 100644 index 25918a72..00000000 Binary files a/examples/FtcRobotController/src/main/res/raw/silver.wav and /dev/null differ diff --git a/examples/FtcRobotController/src/main/res/values/dimens.xml b/examples/FtcRobotController/src/main/res/values/dimens.xml deleted file mode 100644 index 63f1babc..00000000 --- a/examples/FtcRobotController/src/main/res/values/dimens.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - 16dp - 5dp - - \ No newline at end of file diff --git a/examples/FtcRobotController/src/main/res/values/strings.xml b/examples/FtcRobotController/src/main/res/values/strings.xml deleted file mode 100644 index 6ea191ed..00000000 --- a/examples/FtcRobotController/src/main/res/values/strings.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - FTC Robot Controller - - - Self Inspect - Program & Manage - Blocks - Settings - Restart Robot - Configure Robot - About - Exit - - - Configuration Complete - Restarting Robot - The Robot Controller must be fully up and running before entering Program and Manage Mode. - - - - @style/AppThemeRedRC - @style/AppThemeGreenRC - @style/AppThemeBlueRC - @style/AppThemePurpleRC - @style/AppThemeOrangeRC - @style/AppThemeTealRC - - - pref_ftc_season_year_of_current_rc_new - - @string/packageNameRobotController - - diff --git a/examples/FtcRobotController/src/main/res/values/styles.xml b/examples/FtcRobotController/src/main/res/values/styles.xml deleted file mode 100644 index 07689c03..00000000 --- a/examples/FtcRobotController/src/main/res/values/styles.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/FtcRobotController/src/main/res/xml/app_settings.xml b/examples/FtcRobotController/src/main/res/xml/app_settings.xml deleted file mode 100644 index 58d3aa9c..00000000 --- a/examples/FtcRobotController/src/main/res/xml/app_settings.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/FtcRobotController/src/main/res/xml/device_filter.xml b/examples/FtcRobotController/src/main/res/xml/device_filter.xml deleted file mode 100644 index 7b75350c..00000000 --- a/examples/FtcRobotController/src/main/res/xml/device_filter.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - diff --git a/examples/TeamCode/build.gradle b/examples/TeamCode/build.gradle deleted file mode 100644 index ffd499bf..00000000 --- a/examples/TeamCode/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -// -// build.gradle in TeamCode -// -// Most of the definitions for building your module reside in a common, shared -// file 'build.common.gradle'. Being factored in this way makes it easier to -// integrate updates to the FTC into your code. If you really need to customize -// the build definitions, you can place those customizations in this file, but -// please think carefully as to whether such customizations are really necessary -// before doing so. - - -// Custom definitions may go here - -// Include common definitions from above. -apply from: '../build.common.gradle' -apply from: '../build.dependencies.gradle' -apply plugin: 'org.jetbrains.kotlin.android' - -android { - namespace = 'org.firstinspires.ftc.teamcode' - - defaultConfig { - compileSdk = 35 - minSdk = 24 - } - - packagingOptions { - jniLibs.useLegacyPackaging true - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - kotlinOptions { - jvmTarget = '11' - } -} - -repositories { -} - -dependencies { - implementation project(':FtcRobotController') - implementation project(':FullPanels') - implementation project(':ExamplePlugin') -} diff --git a/examples/TeamCode/lib/OpModeAnnotationProcessor.jar b/examples/TeamCode/lib/OpModeAnnotationProcessor.jar deleted file mode 100644 index 4825cc36..00000000 Binary files a/examples/TeamCode/lib/OpModeAnnotationProcessor.jar and /dev/null differ diff --git a/examples/build.common.gradle b/examples/build.common.gradle deleted file mode 100644 index 78f29e83..00000000 --- a/examples/build.common.gradle +++ /dev/null @@ -1,117 +0,0 @@ -/** - * build.common.gradle - * - * Try to avoid editing this file, as it may be updated from time to time as the FTC SDK - * evolves. Rather, if it is necessary to customize the build process, do those edits in - * the build.gradle file in TeamCode. - * - * This file contains the necessary content of the 'build.gradle' files for robot controller - * applications built using the FTC SDK. Each individual 'build.gradle' in those applications - * can simply contain the one line: - * - * apply from: '../build.common.gradle' - * - * which will pick up this file here. This approach allows makes it easier to integrate - * updates to the FTC SDK into your code. - */ - -import java.util.regex.Pattern - -apply plugin: 'com.android.application' - -android { - - compileSdkVersion 30 - - signingConfigs { - release { - def apkStoreFile = System.getenv("APK_SIGNING_STORE_FILE") - if (apkStoreFile != null) { - keyAlias System.getenv("APK_SIGNING_KEY_ALIAS") - keyPassword System.getenv("APK_SIGNING_KEY_PASSWORD") - storeFile file(System.getenv("APK_SIGNING_STORE_FILE")) - storePassword System.getenv("APK_SIGNING_STORE_PASSWORD") - } else { - keyAlias 'androiddebugkey' - keyPassword 'android' - storeFile rootProject.file('libs/ftc.debug.keystore') - storePassword 'android' - } - } - - debug { - keyAlias 'androiddebugkey' - keyPassword 'android' - storeFile rootProject.file('libs/ftc.debug.keystore') - storePassword 'android' - } - } - - defaultConfig { - signingConfig signingConfigs.debug - applicationId 'com.qualcomm.ftcrobotcontroller' - minSdkVersion 25 - //noinspection ExpiredTargetSdkVersion - targetSdkVersion 28 - - /** - * We keep the versionCode and versionName of robot controller applications in sync with - * the master information published in the AndroidManifest.xml file of the FtcRobotController - * module. This helps avoid confusion that might arise from having multiple versions of - * a robot controller app simultaneously installed on a robot controller device. - * - * We accomplish this with the help of a funky little Groovy script that maintains that - * correspondence automatically. - * - * @see Configure Your Build - * @see Versioning Your App - */ - def manifestFile = project(':FtcRobotController').file('src/main/AndroidManifest.xml'); - def manifestText = manifestFile.getText() - // - def vCodePattern = Pattern.compile("versionCode=\"(\\d+(\\.\\d+)*)\"") - def matcher = vCodePattern.matcher(manifestText) - matcher.find() - def vCode = Integer.parseInt(matcher.group(1)) - // - def vNamePattern = Pattern.compile("versionName=\"(.*)\"") - matcher = vNamePattern.matcher(manifestText); - matcher.find() - def vName = matcher.group(1) - // - versionCode vCode - versionName vName - } - - // http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.BuildType.html - buildTypes { - release { - signingConfig signingConfigs.release - - ndk { - abiFilters "armeabi-v7a", "arm64-v8a" - } - } - debug { - debuggable true - jniDebuggable true - ndk { - abiFilters "armeabi-v7a", "arm64-v8a" - } - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - packagingOptions { - pickFirst '**/*.so' - } - ndkVersion '21.3.6528147' -} - -repositories { -} - diff --git a/examples/build.dependencies.gradle b/examples/build.dependencies.gradle deleted file mode 100644 index 1c07e8cb..00000000 --- a/examples/build.dependencies.gradle +++ /dev/null @@ -1,17 +0,0 @@ -repositories { - mavenCentral() - google() // Needed for androidx -} - -dependencies { - implementation 'org.firstinspires.ftc:Inspection:11.0.0' - implementation 'org.firstinspires.ftc:Blocks:11.0.0' - implementation 'org.firstinspires.ftc:RobotCore:11.0.0' - implementation 'org.firstinspires.ftc:RobotServer:11.0.0' - implementation 'org.firstinspires.ftc:OnBotJava:11.0.0' - implementation 'org.firstinspires.ftc:Hardware:11.0.0' - implementation 'org.firstinspires.ftc:FtcCommon:11.0.0' - implementation 'org.firstinspires.ftc:Vision:11.0.0' - implementation 'androidx.appcompat:appcompat:1.2.0' -} - diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index 44ecb6e2..dc622281 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -1,33 +1,11 @@ -/** - * Top-level build file for ftc_app project. - * - * It is extraordinarily rare that you will ever need to edit this file. - */ - -buildscript { - val kotlin_version by extra("2.1.20") - - repositories { - mavenCentral() - google() - } - - dependencies { - // Note for FTC Teams: Do not modify this yourself. - classpath("com.android.tools.build:gradle:8.7.0") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") - } +plugins { + id("dev.frozenmilk.teamcode") version "11.1.0-1.1.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 { - mavenCentral() - google() +ftc { + kotlin() + sdk.TeamCode() + dairy.ftControl { + implementation(fullpanels("")) } } - -repositories { - mavenCentral() -} diff --git a/examples/gradle.properties b/examples/gradle.properties index f5935e91..8867ee4c 100644 --- a/examples/gradle.properties +++ b/examples/gradle.properties @@ -9,4 +9,7 @@ android.enableJetifier=false # Allow Gradle to use up to 1 GB of RAM org.gradle.jvmargs=-Xmx1024M -android.nonTransitiveRClass=false \ No newline at end of file +android.nonTransitiveRClass=false + +org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled +org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true \ No newline at end of file diff --git a/examples/gradlew b/examples/gradlew old mode 100644 new mode 100755 diff --git a/examples/settings.gradle.kts b/examples/settings.gradle.kts index 3ef085d5..bff3fad7 100644 --- a/examples/settings.gradle.kts +++ b/examples/settings.gradle.kts @@ -1,7 +1,9 @@ pluginManagement { - includeBuild("../library/plugin-svelte-assets") repositories { gradlePluginPortal() + mavenCentral() + google() + maven("https://repo.dairy.foundation/releases") } } @@ -28,10 +30,14 @@ val modules = listOf( "CameraStream" ) -modules.forEach { name -> - include(":$name") - project(":$name").projectDir = file("../library/$name") -} +//modules.forEach { name -> +// include(":$name") +// project(":$name").projectDir = file("../library/$name") +//} -include(":FtcRobotController") -include(":TeamCode") \ No newline at end of file +includeBuild("../library") { + dependencySubstitution { + substitute(module("com.bylazar.sloth:fullpanels")).using(project(":FullPanels")) + substitute(module("com.bylazar:fullpanels")).using(project(":FullPanels")) + } +} \ No newline at end of file diff --git a/examples/TeamCode/src/main/AndroidManifest.xml b/examples/src/main/AndroidManifest.xml similarity index 100% rename from examples/TeamCode/src/main/AndroidManifest.xml rename to examples/src/main/AndroidManifest.xml diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/ClawConfig.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/ClawConfig.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/ClawConfig.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/ClawConfig.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/Config.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/Config.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/Config.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/Config.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/Drawing.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/Drawing.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/Drawing.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/Drawing.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/TestConfigurables.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/TestConfigurables.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/TestConfigurables.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/TestConfigurables.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/TestConfigurablesValues.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/TestConfigurablesValues.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/TestConfigurablesValues.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/TestConfigurablesValues.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/TestKotlinObject.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/TestKotlinObject.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/TestKotlinObject.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/TestKotlinObject.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/TestTelemetry.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/TestTelemetry.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/TestTelemetry.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/TestTelemetry.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/battery/BatteryExample.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/battery/BatteryExample.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/battery/BatteryExample.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/battery/BatteryExample.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/camerastream/TestCameraStream.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/camerastream/TestCameraStream.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/camerastream/TestCameraStream.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/camerastream/TestCameraStream.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/ClawConfig.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/ClawConfig.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/ClawConfig.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/ClawConfig.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/JavaRobotConstants.java b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/JavaRobotConstants.java similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/JavaRobotConstants.java rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/JavaRobotConstants.java diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/KotlinRobotConstants.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/KotlinRobotConstants.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/KotlinRobotConstants.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/KotlinRobotConstants.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/SortedConfigurables.java b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/SortedConfigurables.java similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/SortedConfigurables.java rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/SortedConfigurables.java diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestJavaClass.java b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestJavaClass.java similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestJavaClass.java rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestJavaClass.java diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestKotlinClass.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestKotlinClass.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestKotlinClass.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestKotlinClass.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestKotlinObject.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestKotlinObject.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestKotlinObject.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestKotlinObject.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestOpMode.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestOpMode.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestOpMode.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/TestOpMode.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/bad/Example.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/bad/Example.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/bad/Example.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/bad/Example.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/fixed/Example.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/fixed/Example.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/fixed/Example.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/fixed/Example.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/lambda/Example.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/lambda/Example.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/lambda/Example.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/configurables/copysemantics/lambda/Example.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/field/BezierFollower.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/field/BezierFollower.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/field/BezierFollower.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/field/BezierFollower.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/field/CustomPresets.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/field/CustomPresets.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/field/CustomPresets.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/field/CustomPresets.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/field/Drawing.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/field/Drawing.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/field/Drawing.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/field/Drawing.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/field/TestCoords.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/field/TestCoords.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/field/TestCoords.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/field/TestCoords.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/gamepad/TestGamepad.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/gamepad/TestGamepad.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/gamepad/TestGamepad.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/gamepad/TestGamepad.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/graph/TestGraph.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/graph/TestGraph.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/graph/TestGraph.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/graph/TestGraph.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/lights/TestLights.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/lights/TestLights.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/lights/TestLights.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/lights/TestLights.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/opmodecontrol/TimerTest.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/opmodecontrol/TimerTest.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/opmodecontrol/TimerTest.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/opmodecontrol/TimerTest.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/readme.md b/examples/src/main/java/org/firstinspires/ftc/teamcode/readme.md similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/readme.md rename to examples/src/main/java/org/firstinspires/ftc/teamcode/readme.md diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestFormatTelemetry.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestFormatTelemetry.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestFormatTelemetry.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestFormatTelemetry.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestJoinedTelemetry.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestJoinedTelemetry.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestJoinedTelemetry.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestJoinedTelemetry.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestTelemetryFTCStyle.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestTelemetryFTCStyle.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestTelemetryFTCStyle.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestTelemetryFTCStyle.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestTelemetryPanelsStyle.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestTelemetryPanelsStyle.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestTelemetryPanelsStyle.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/telemetry/TestTelemetryPanelsStyle.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/utils/LoopTimerExample.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/utils/LoopTimerExample.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/utils/LoopTimerExample.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/utils/LoopTimerExample.kt diff --git a/examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/utils/MovingAverageExample.kt b/examples/src/main/java/org/firstinspires/ftc/teamcode/utils/MovingAverageExample.kt similarity index 100% rename from examples/TeamCode/src/main/java/org/firstinspires/ftc/teamcode/utils/MovingAverageExample.kt rename to examples/src/main/java/org/firstinspires/ftc/teamcode/utils/MovingAverageExample.kt diff --git a/examples/TeamCode/src/main/res/raw/readme.md b/examples/src/main/res/raw/readme.md similarity index 100% rename from examples/TeamCode/src/main/res/raw/readme.md rename to examples/src/main/res/raw/readme.md diff --git a/examples/TeamCode/src/main/res/values/strings.xml b/examples/src/main/res/values/strings.xml similarity index 100% rename from examples/TeamCode/src/main/res/values/strings.xml rename to examples/src/main/res/values/strings.xml diff --git a/examples/TeamCode/src/main/res/xml/teamwebcamcalibrations.xml b/examples/src/main/res/xml/teamwebcamcalibrations.xml similarity index 100% rename from examples/TeamCode/src/main/res/xml/teamwebcamcalibrations.xml rename to examples/src/main/res/xml/teamwebcamcalibrations.xml diff --git a/library/.gitignore b/library/.gitignore index 8ea3a652..e9b0d3c9 100644 --- a/library/.gitignore +++ b/library/.gitignore @@ -1,5 +1,6 @@ # dependencies (rm -rf bun.lock && bun install --no-cachenstall) node_modules +.bun # output out diff --git a/library/Battery/build.gradle.kts b/library/Battery/build.gradle.kts index f5bbe506..5f7fbbfa 100644 --- a/library/Battery/build.gradle.kts +++ b/library/Battery/build.gradle.kts @@ -2,56 +2,46 @@ val pluginNamespace = "com.bylazar.battery" val pluginVersion = "1.0.3" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Battery" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) + compileOnly(Hardware) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +51,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Battery Plugin") @@ -80,12 +72,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Battery/web/bun.lock b/library/Battery/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/Battery/web/bun.lock +++ b/library/Battery/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/CameraStream/build.gradle.kts b/library/CameraStream/build.gradle.kts index e1f2e0f9..6769911d 100644 --- a/library/CameraStream/build.gradle.kts +++ b/library/CameraStream/build.gradle.kts @@ -1,60 +1,47 @@ -import org.gradle.kotlin.dsl.implementation - val pluginNamespace = "com.bylazar.camerastream" val pluginVersion = "1.0.0" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "CameraStream" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"$version\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"${dairyPublishing.version}\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) + // TODO: remove? implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1") } @@ -64,9 +51,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Camera Stream Plugin") @@ -83,12 +72,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/CameraStream/web/bun.lock b/library/CameraStream/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/CameraStream/web/bun.lock +++ b/library/CameraStream/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Capture/build.gradle.kts b/library/Capture/build.gradle.kts index 221d9a28..b7f98856 100644 --- a/library/Capture/build.gradle.kts +++ b/library/Capture/build.gradle.kts @@ -2,56 +2,44 @@ val pluginNamespace = "com.bylazar.capture" val pluginVersion = "1.0.3" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Capture" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +49,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Capture Plugin") @@ -80,12 +70,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Capture/web/bun.lock b/library/Capture/web/bun.lock index d9b44e64..56b2352a 100644 --- a/library/Capture/web/bun.lock +++ b/library/Capture/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Configurables/build.gradle.kts b/library/Configurables/build.gradle.kts index b47b2f62..18f6aee7 100644 --- a/library/Configurables/build.gradle.kts +++ b/library/Configurables/build.gradle.kts @@ -2,56 +2,48 @@ val pluginNamespace = "com.bylazar.configurables" val pluginVersion = "1.0.5" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace +dairyPublishing { + gitDir = file("..") +} - defaultConfig { - compileSdk = 34 - minSdk = 24 - } +version = "${dairyPublishing.version}+$pluginVersion" - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +meta { + packagePath = pluginNamespace + name = "Configurables" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"${dairyPublishing.version}\"" } +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } - - kotlinOptions { - jvmTarget = "11" - } - - publishing { - singleVariant("release") {} + dairy { + implementation(Sloth) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +53,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaHtmlJar) + artifact(dairyDoc.dokkaJavadocJar) pom { description.set("Panels Configurables Plugin") @@ -80,12 +74,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Configurables/src/main/java/com/bylazar/configurables/ConfigurablesPlugin.kt b/library/Configurables/src/main/java/com/bylazar/configurables/ConfigurablesPlugin.kt index 27665e64..cfe8d059 100644 --- a/library/Configurables/src/main/java/com/bylazar/configurables/ConfigurablesPlugin.kt +++ b/library/Configurables/src/main/java/com/bylazar/configurables/ConfigurablesPlugin.kt @@ -1,40 +1,38 @@ package com.bylazar.configurables -import android.R.attr.type import android.content.Context -import com.bylazar.configurables.GlobalConfigurables +import com.bylazar.configurables.GlobalConfigurables.fieldsMap import com.bylazar.configurables.GlobalConfigurables.jvmFields +import com.bylazar.configurables.GlobalConfigurables.loadedFieldsMap import com.bylazar.configurables.annotations.Configurable import com.bylazar.configurables.annotations.IgnoreConfigurable -import com.bylazar.configurables.variables.MyField +import com.bylazar.configurables.annotations.Sorter import com.bylazar.configurables.variables.generics.GenericField import com.bylazar.panels.Panels import com.bylazar.panels.json.SocketMessage import com.bylazar.panels.plugins.BasePluginConfig import com.bylazar.panels.plugins.Plugin -import com.bylazar.panels.reflection.ClassFinder import com.bylazar.panels.server.Socket import com.qualcomm.ftccommon.FtcEventLoop import com.qualcomm.robotcore.eventloop.opmode.OpMode import com.qualcomm.robotcore.eventloop.opmode.OpModeManagerImpl +import dev.frozenmilk.sinister.Scanner +import dev.frozenmilk.sinister.loaders.RootClassLoader +import dev.frozenmilk.sinister.targeting.WideSearch import java.lang.reflect.Modifier -import kotlin.jvm.java -open class ConfigurablesPluginConfig : BasePluginConfig() { -} +open class ConfigurablesPluginConfig : BasePluginConfig() {} -object Plugin : Plugin(ConfigurablesPluginConfig()) { - var fieldsMap = mutableMapOf() - var configurableClasses: List = listOf() - var allFields: MutableList = mutableListOf() +object Plugin : Plugin(ConfigurablesPluginConfig()), Scanner { + private val allFieldsMap: Map> + get() = jvmFields// + .flatMap { it.value.map(GenericField::toJsonType) }// + .groupBy { it.className }.toSortedMap() - val allFieldsMap: Map> - get() = allFields.groupBy { it.className }.toSortedMap() - - var initialAFieldsMap: Map> = mapOf() + private var initialFieldsMap: Map> = mapOf() override fun onNewClient(client: Socket.ClientSocket) { - sendClient(client, "initialConfigurables", initialAFieldsMap) + sendClient(client, "initialConfigurables", initialFieldsMap) sendClient(client, "configurables", allFieldsMap) } @@ -48,110 +46,72 @@ object Plugin : Plugin(ConfigurablesPluginConfig()) { emptyList() } - if(changes == null) return + if (changes == null) return changes.forEach { - val generalRef = GlobalConfigurables.fieldsMap[it.id] ?: return + val generalRef = fieldsMap[it.id] ?: return log("Field id: ${it.id}, New value: ${it.newValueString}") generalRef.setValue(it.newValueString) it.newValueString = generalRef.getValue().toString() - - allFields = jvmFields.map { it.toJsonType }.toMutableList() } send("newConfigurables", changes) } } - fun refreshClass(className: String) { - allFields.removeAll { it.className == className } - - val fields: MutableList = mutableListOf() - - try { - val clazz = Class.forName(className) - log("Inspecting class $className") - fields.addFieldsFromClass(clazz, className) - try { - val companionClazz = Class.forName("${className}\$Companion") - fields.addFieldsFromClass(companionClazz, className) - } catch (e: ClassNotFoundException) { - // no companion found + fun refreshClass(cls: Class<*>) { + jvmFields.forEach { (loader, fields) -> + if(fields.removeIf { it.reference.declaringClass == cls }) { + scan(loader, cls) + send("configurables", allFieldsMap) + return } - } catch (e: Exception) { - error("Error inspecting class ${className}: ${e.message}") } - - val newFields = fields.map { it.toJsonType }.toMutableList() - - allFields.addAll(newFields) - - send("configurables", allFieldsMap) } override fun onRegister( - panelsInstance: Panels, - context: Context + panelsInstance: Panels, context: Context ) { log("Initializing configurables") - fieldsMap = mutableMapOf() - configurableClasses = listOf() - - GlobalConfigurables.jvmFields = mutableListOf() - GlobalConfigurables.fieldsMap = mutableMapOf() - - configurableClasses = ClassFinder.findClasses( - { clazz -> - val hasConfigurable = - clazz.isAnnotationPresent(Configurable::class.java) - val hasIgnoreConfigurable = - clazz.isAnnotationPresent(IgnoreConfigurable::class.java) - val shouldKeep = - hasConfigurable && !hasIgnoreConfigurable - - shouldKeep - } - ) + } - log("Configurable classes: ${configurableClasses.map { it.className }}") + override fun onAttachEventLoop(eventLoop: FtcEventLoop) { + } - val fields: MutableList = mutableListOf() + override fun onOpModeManager(o: OpModeManagerImpl) { + } - configurableClasses.forEach { - val className = it.className + override fun onOpModePreInit(opMode: OpMode) { + } - try { - val clazz = Class.forName(className) - log("Inspecting class $className") - fields.addFieldsFromClass(clazz, className) - try { - val companionClazz = Class.forName("${className}\$Companion") - fields.addFieldsFromClass(companionClazz, className) - } catch (e: ClassNotFoundException) { - // no companion found - } - } catch (e: Exception) { - error("Error inspecting class ${className}: ${e.message}") - } - } + override fun onOpModePreStart(opMode: OpMode) { + } - log("Configurable fields: ${fields.map { it.name }}") + override fun onOpModePostStop(opMode: OpMode) { + } - allFields = jvmFields.map { it.toJsonType }.filter { it.className != "class java.lang.ClassLoader" && it.className != "class sun.misc.Unsafe" }.toMutableList() - initialAFieldsMap = allFieldsMap + override fun onEnablePanels() { + } - send("initialConfigurables", initialAFieldsMap) - send("configurables", allFieldsMap) + override fun onDisablePanels() { } - private fun MutableList.addFieldsFromClass( - clazz: Class<*>, - originalClassName: String - ) { - log("Sorting fields for class ${clazz.simpleName}") - val fields = clazz.declaredFields.sortedBy { field -> - val sort = field.getAnnotation(com.bylazar.configurables.annotations.Sorter::class.java)?.sort + // + // Scanner + // + + override val loadAdjacencyRule = Scanner.INDEPENDENT + override val unloadAdjacencyRule = Scanner.INDEPENDENT + override val targets = WideSearch() + + override fun scan(loader: ClassLoader, cls: Class<*>) { + if (!cls.isAnnotationPresent(Configurable::class.java)) return + if (cls.isAnnotationPresent(IgnoreConfigurable::class.java)) return + + log("Sorting fields for class ${cls.simpleName}") + val fields = cls.declaredFields.sortedBy { field -> + val sort = field.getAnnotation(Sorter::class.java)?.sort log("Field ${field.name} has sort value: $sort") sort ?: Int.MAX_VALUE } @@ -162,16 +122,6 @@ object Plugin : Plugin(ConfigurablesPluginConfig()) { val isStatic = Modifier.isStatic(field.modifiers) val isIgnored = field.isAnnotationPresent(IgnoreConfigurable::class.java) - val isPrivate = Modifier.isPrivate(field.modifiers) - val isNull = try { - if (field.get(null) == null) { - println("PANELS: Field ${field.name} in $clazz is null") - true - } else false - } catch (t: Throwable) { - false - } - val isJvmField = !isFinal && isStatic && !isIgnored val fieldTypeName = field.type.canonicalName ?: "" @@ -179,38 +129,30 @@ object Plugin : Plugin(ConfigurablesPluginConfig()) { log("Found field of $fieldTypeName / $isJvmField") if (isJvmField) { - val displayClassName = - if (clazz.name.endsWith("\$Companion")) originalClassName else clazz.name - val genericField = GenericField(className = displayClassName, reference = field) + val displayClassName = cls.kotlin.simpleName ?: cls.name + val genericField = GenericField(classLoader = loader, className = displayClassName, reference = field) log("Adding field $genericField / ${genericField.type} / ${genericField.value} / ${genericField.isNull}") - add(genericField) - GlobalConfigurables.jvmFields.add(genericField) + jvmFields.getOrPut(loader, ::mutableListOf).add(genericField) } } catch (t: Throwable) { - error("Error inspecting field ${field.name} in $clazz: ${t.message}") + error("Error inspecting field ${field.name} in $cls: ${t.message}") } } } - override fun onAttachEventLoop(eventLoop: FtcEventLoop) { - } - - override fun onOpModeManager(o: OpModeManagerImpl) { - } - - override fun onOpModePreInit(opMode: OpMode) { - } - - override fun onOpModePreStart(opMode: OpMode) { - } - - override fun onOpModePostStop(opMode: OpMode) { + override fun afterScan(loader: ClassLoader) { + initialFieldsMap = allFieldsMap + send("initialConfigurables", initialFieldsMap) + send("configurables", allFieldsMap) } - - override fun onEnablePanels() { + override fun beforeUnload(loader: ClassLoader) { + jvmFields.remove(loader) + loadedFieldsMap.remove(loader)?.forEach(fieldsMap::remove) + initialFieldsMap = allFieldsMap + send("initialConfigurables", initialFieldsMap) + send("configurables", allFieldsMap) } - override fun onDisablePanels() { - } + override fun unload(loader: ClassLoader, cls: Class<*>) {} } \ No newline at end of file diff --git a/library/Configurables/src/main/java/com/bylazar/configurables/GlobalConfigurables.kt b/library/Configurables/src/main/java/com/bylazar/configurables/GlobalConfigurables.kt index 8f713961..2d97f5e5 100644 --- a/library/Configurables/src/main/java/com/bylazar/configurables/GlobalConfigurables.kt +++ b/library/Configurables/src/main/java/com/bylazar/configurables/GlobalConfigurables.kt @@ -4,7 +4,7 @@ import com.bylazar.configurables.variables.MyField import com.bylazar.configurables.variables.generics.GenericField object GlobalConfigurables { - var jvmFields = mutableListOf() - + var jvmFields = mutableMapOf>() + var loadedFieldsMap = mutableMapOf>() var fieldsMap = mutableMapOf() } \ No newline at end of file diff --git a/library/Configurables/src/main/java/com/bylazar/configurables/PanelsConfigurables.kt b/library/Configurables/src/main/java/com/bylazar/configurables/PanelsConfigurables.kt index c5f8ae87..d9a67545 100644 --- a/library/Configurables/src/main/java/com/bylazar/configurables/PanelsConfigurables.kt +++ b/library/Configurables/src/main/java/com/bylazar/configurables/PanelsConfigurables.kt @@ -1,8 +1,16 @@ package com.bylazar.configurables +import kotlin.reflect.KClass + object PanelsConfigurables { - fun refreshClass(cls: Any) { - val name = cls::class.qualifiedName ?: return - Plugin.refreshClass(name) - } + @Deprecated( + "this function is misleading, instead, use the variants that take a class", + replaceWith = ReplaceWith("refreshClass(cls::class)") + ) + @JvmStatic + fun refreshClass(cls: Any) = refreshClass(cls.javaClass) + @JvmStatic + fun refreshClass(cls: KClass<*>) = Plugin.refreshClass(cls.java) + @JvmStatic + fun refreshClass(cls: Class<*>) = Plugin.refreshClass(cls) } \ No newline at end of file diff --git a/library/Configurables/src/main/java/com/bylazar/configurables/variables/MyField.kt b/library/Configurables/src/main/java/com/bylazar/configurables/variables/MyField.kt index ebfe43d3..d1362538 100644 --- a/library/Configurables/src/main/java/com/bylazar/configurables/variables/MyField.kt +++ b/library/Configurables/src/main/java/com/bylazar/configurables/variables/MyField.kt @@ -10,9 +10,10 @@ import java.util.Locale import java.util.UUID import kotlin.text.* -class MyField( +class MyField constructor( val name: String, val type: Class<*>, + val classLoader: ClassLoader, var isAccessible: Boolean, var get: (instance: Any?) -> Any?, var set: (instance: Any?, newValue: Any?) -> Unit, @@ -32,6 +33,7 @@ class MyField( init { if (ref != null) ref.isAccessible = true GlobalConfigurables.fieldsMap[id] = this + GlobalConfigurables.loadedFieldsMap.getOrPut(classLoader, ::mutableListOf).add(id) } fun getValue(recursionDepth: Int = 0): Any? { @@ -79,10 +81,11 @@ class MyField( } } -fun convertToMyField(field: Field): MyField { +fun convertToMyField(classLoader: ClassLoader, field: Field): MyField { return MyField( name = field.name, type = field.type, + classLoader = classLoader, isAccessible = field.isAccessible, get = field::get, set = field::set, @@ -95,6 +98,7 @@ fun convertToMyField(field: MyField, parentField: MyField?, className: String): return MyField( name = field.name, type = field.type, + classLoader = field.classLoader, isAccessible = field.isAccessible, get = field.get, set = field.set, diff --git a/library/Configurables/src/main/java/com/bylazar/configurables/variables/generics/GenericField.kt b/library/Configurables/src/main/java/com/bylazar/configurables/variables/generics/GenericField.kt index d5dabf42..05d136b8 100644 --- a/library/Configurables/src/main/java/com/bylazar/configurables/variables/generics/GenericField.kt +++ b/library/Configurables/src/main/java/com/bylazar/configurables/variables/generics/GenericField.kt @@ -10,12 +10,13 @@ import com.bylazar.configurables.variables.processValue import java.lang.reflect.Field class GenericField( + classLoader: ClassLoader, var className: String, var reference: Field, ) { - val type = getType(reference.type, convertToMyField(reference), null) - val value: GenericVariable = processValue(0, className, type, convertToMyField(reference), null) + val type = getType(reference.type, convertToMyField(classLoader, reference), null) + val value: GenericVariable = processValue(0, className, classLoader, type, convertToMyField(classLoader, reference), null) val isNull: Boolean get() = toJsonType.type == BaseTypes.JSON_ERROR diff --git a/library/Configurables/src/main/java/com/bylazar/configurables/variables/processValue.kt b/library/Configurables/src/main/java/com/bylazar/configurables/variables/processValue.kt index f30c3370..12fd31e3 100644 --- a/library/Configurables/src/main/java/com/bylazar/configurables/variables/processValue.kt +++ b/library/Configurables/src/main/java/com/bylazar/configurables/variables/processValue.kt @@ -23,6 +23,7 @@ class RecursionDetectedException(val fieldName: String) : RuntimeException() fun processValue( recursionDepth: Int, className: String, + classLoader: ClassLoader, type: BaseTypes, reference: MyField, parentReference: MyField?, @@ -58,7 +59,8 @@ fun processValue( if (type == BaseTypes.CUSTOM) { reference.isAccessible = true val customValues = reference.type.declaredFields.sortedBy { field -> - field.getAnnotation(com.bylazar.configurables.annotations.Sorter::class.java)?.sort ?: Int.MAX_VALUE + field.getAnnotation(com.bylazar.configurables.annotations.Sorter::class.java)?.sort + ?: Int.MAX_VALUE }.mapNotNull { field -> try { field.isAccessible = true @@ -75,13 +77,15 @@ fun processValue( // return@mapNotNull null // } if (field.type == reference.type) { - val newField = GenericField(reference.type.toString(), field) - val alreadyExists = GlobalConfigurables.jvmFields.any { - it.className == newField.className && it.reference.name == newField.reference.name + val newField = GenericField(classLoader, reference.type.toString(), field) + val alreadyExists = GlobalConfigurables.jvmFields.any { (_, fields) -> + fields.any { + it.className == newField.className && it.reference.name == newField.reference.name + } } if (!alreadyExists) { - GlobalConfigurables.jvmFields.add(newField) + GlobalConfigurables.jvmFields.getOrPut(classLoader, ::mutableListOf).add(newField) ConfigurablesLogger.log("Moved field to global configurable: ${reference.name} ${reference.type} ${field.name}") } else { ConfigurablesLogger.log("Skipped duplicate configurable: ${reference.name} ${reference.type} ${field.name}") @@ -90,11 +94,12 @@ fun processValue( return@mapNotNull null } - val customNewField = convertToMyField(field) + val customNewField = convertToMyField(classLoader, field) processValue( recursionDepth + 1, className, + classLoader, getType(field.type, customNewField, reference), customNewField, currentManager, @@ -134,6 +139,7 @@ fun processValue( val currentElementReference = MyField( name = i.toString(), type = cType, + classLoader = classLoader, isAccessible = true, get = { instance -> Array.get(instance, i) @@ -147,6 +153,7 @@ fun processValue( processValue( recursionDepth + 1, className, + classLoader, itemType, currentElementReference, currentManager, @@ -186,6 +193,7 @@ fun processValue( val currentElementReference = MyField( name = index.toString(), type = cType, + classLoader = classLoader, isAccessible = true, get = { instance -> listInstance.getOrNull(index) @@ -203,6 +211,7 @@ fun processValue( processValue( recursionDepth + 1, className, + classLoader, itemType, currentElementReference, currentManager, @@ -228,6 +237,7 @@ fun processValue( val currentElementReference = MyField( name = key.toString(), type = mapInstance[key]?.javaClass ?: Any::class.java, + classLoader = classLoader, isAccessible = true, get = { instance -> mapInstance[key] @@ -241,6 +251,7 @@ fun processValue( processValue( recursionDepth + 1, className, + classLoader, itemType, currentElementReference, currentManager, diff --git a/library/Configurables/web/bun.lock b/library/Configurables/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/Configurables/web/bun.lock +++ b/library/Configurables/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Docs/build.gradle.kts b/library/Docs/build.gradle.kts index 08064e3e..89c69dc2 100644 --- a/library/Docs/build.gradle.kts +++ b/library/Docs/build.gradle.kts @@ -2,56 +2,45 @@ val pluginNamespace = "com.bylazar.docs" val pluginVersion = "1.0.5" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Docs" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +50,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Docs Plugin") @@ -80,12 +71,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Docs/web/bun.lock b/library/Docs/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/Docs/web/bun.lock +++ b/library/Docs/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/ExamplePlugin/build.gradle.kts b/library/ExamplePlugin/build.gradle.kts index ccc2032d..a920a958 100644 --- a/library/ExamplePlugin/build.gradle.kts +++ b/library/ExamplePlugin/build.gradle.kts @@ -2,56 +2,45 @@ val pluginNamespace = "com.bylazar.exampleplugin" val pluginVersion = "0.0.14" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Example" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +50,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Example Plugin") @@ -80,12 +71,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/ExamplePlugin/web/bun.lock b/library/ExamplePlugin/web/bun.lock index d9b44e64..56b2352a 100644 --- a/library/ExamplePlugin/web/bun.lock +++ b/library/ExamplePlugin/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Field/build.gradle.kts b/library/Field/build.gradle.kts index dca32acb..225e8fe8 100644 --- a/library/Field/build.gradle.kts +++ b/library/Field/build.gradle.kts @@ -2,56 +2,45 @@ val pluginNamespace = "com.bylazar.field" val pluginVersion = "1.0.6" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Field" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +50,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Field Plugin") @@ -80,12 +71,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Field/web/bun.lock b/library/Field/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/Field/web/bun.lock +++ b/library/Field/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/FtcRobotController/build.gradle b/library/FtcRobotController/build.gradle deleted file mode 100644 index 86fdd50f..00000000 --- a/library/FtcRobotController/build.gradle +++ /dev/null @@ -1,25 +0,0 @@ -import java.text.SimpleDateFormat - -apply plugin: 'com.android.library' - -apply from: '../build.dependencies.gradle' -android { - - defaultConfig { - minSdkVersion 24 - //noinspection ExpiredTargetSdkVersion - targetSdkVersion 28 - compileSdk = 34 - buildConfigField "String", "APP_BUILD_TIME", '"' + (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.ROOT).format(new Date())) + '"' - } - - buildFeatures { - buildConfig = true - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - namespace = 'com.qualcomm.ftcrobotcontroller' -} diff --git a/library/FtcRobotController/src/main/AndroidManifest.xml b/library/FtcRobotController/src/main/AndroidManifest.xml deleted file mode 100644 index 24038bfa..00000000 --- a/library/FtcRobotController/src/main/AndroidManifest.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOmniOpMode_Linear.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOmniOpMode_Linear.java deleted file mode 100644 index 1d14dfb7..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOmniOpMode_Linear.java +++ /dev/null @@ -1,167 +0,0 @@ -/* Copyright (c) 2021 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.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * This file contains an example of a Linear "OpMode". - * An OpMode is a 'program' that runs in either the autonomous or the teleop period of an FTC match. - * The names of OpModes appear on the menu of the FTC Driver Station. - * When a selection is made from the menu, the corresponding OpMode is executed. - * - * This particular OpMode illustrates driving a 4-motor Omni-Directional (or Holonomic) robot. - * This code will work with either a Mecanum-Drive or an X-Drive train. - * Both of these drives are illustrated at https://gm0.org/en/latest/docs/robot-design/drivetrains/holonomic.html - * Note that a Mecanum drive must display an X roller-pattern when viewed from above. - * - * Also note that it is critical to set the correct rotation direction for each motor. See details below. - * - * Holonomic drives provide the ability for the robot to move in three axes (directions) simultaneously. - * Each motion axis is controlled by one Joystick axis. - * - * 1) Axial: Driving forward and backward Left-joystick Forward/Backward - * 2) Lateral: Strafing right and left Left-joystick Right and Left - * 3) Yaw: Rotating Clockwise and counter clockwise Right-joystick Right and Left - * - * This code is written assuming that the right-side motors need to be reversed for the robot to drive forward. - * When you first test your robot, if it moves backward when you push the left stick forward, then you must flip - * the direction of all 4 motors (see code below). - * - * 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="Basic: Omni Linear OpMode", group="Linear OpMode") -@Disabled -public class BasicOmniOpMode_Linear extends LinearOpMode { - - // Declare OpMode members for each of the 4 motors. - private ElapsedTime runtime = new ElapsedTime(); - private DcMotor leftFrontDrive = null; - private DcMotor leftBackDrive = null; - private DcMotor rightFrontDrive = null; - private DcMotor rightBackDrive = null; - - @Override - public void runOpMode() { - - // Initialize the hardware variables. Note that the strings used here must correspond - // to the names assigned during the robot configuration step on the DS or RC devices. - leftFrontDrive = hardwareMap.get(DcMotor.class, "left_front_drive"); - leftBackDrive = hardwareMap.get(DcMotor.class, "left_back_drive"); - rightFrontDrive = hardwareMap.get(DcMotor.class, "right_front_drive"); - rightBackDrive = hardwareMap.get(DcMotor.class, "right_back_drive"); - - // ######################################################################################## - // !!! IMPORTANT Drive Information. Test your motor directions. !!!!! - // ######################################################################################## - // Most robots need the motors on one side to be reversed to drive forward. - // The motor reversals shown here are for a "direct drive" robot (the wheels turn the same direction as the motor shaft) - // If your robot has additional gear reductions or uses a right-angled drive, it's important to ensure - // that your motors are turning in the correct direction. So, start out with the reversals here, BUT - // when you first test your robot, push the left joystick forward and observe the direction the wheels turn. - // Reverse the direction (flip FORWARD <-> REVERSE ) of any wheel that runs backward - // Keep testing until ALL the wheels move the robot forward when you push the left joystick forward. - leftFrontDrive.setDirection(DcMotor.Direction.REVERSE); - leftBackDrive.setDirection(DcMotor.Direction.REVERSE); - rightFrontDrive.setDirection(DcMotor.Direction.FORWARD); - rightBackDrive.setDirection(DcMotor.Direction.FORWARD); - - // Wait for the game to start (driver presses START) - telemetry.addData("Status", "Initialized"); - telemetry.update(); - - waitForStart(); - runtime.reset(); - - // run until the end of the match (driver presses STOP) - while (opModeIsActive()) { - double max; - - // POV Mode uses left joystick to go forward & strafe, and right joystick to rotate. - double axial = -gamepad1.left_stick_y; // Note: pushing stick forward gives negative value - double lateral = gamepad1.left_stick_x; - double yaw = gamepad1.right_stick_x; - - // Combine the joystick requests for each axis-motion to determine each wheel's power. - // Set up a variable for each drive wheel to save the power level for telemetry. - double leftFrontPower = axial + lateral + yaw; - double rightFrontPower = axial - lateral - yaw; - double leftBackPower = axial - lateral + yaw; - double rightBackPower = axial + lateral - yaw; - - // Normalize the values so no wheel power exceeds 100% - // This ensures that the robot maintains the desired motion. - max = Math.max(Math.abs(leftFrontPower), Math.abs(rightFrontPower)); - max = Math.max(max, Math.abs(leftBackPower)); - max = Math.max(max, Math.abs(rightBackPower)); - - if (max > 1.0) { - leftFrontPower /= max; - rightFrontPower /= max; - leftBackPower /= max; - rightBackPower /= max; - } - - // This is test code: - // - // Uncomment the following code to test your motor directions. - // Each button should make the corresponding motor run FORWARD. - // 1) First get all the motors to take to correct positions on the robot - // by adjusting your Robot Configuration if necessary. - // 2) Then make sure they run in the correct direction by modifying the - // the setDirection() calls above. - // Once the correct motors move in the correct direction re-comment this code. - - /* - leftFrontPower = gamepad1.x ? 1.0 : 0.0; // X gamepad - leftBackPower = gamepad1.a ? 1.0 : 0.0; // A gamepad - rightFrontPower = gamepad1.y ? 1.0 : 0.0; // Y gamepad - rightBackPower = gamepad1.b ? 1.0 : 0.0; // B gamepad - */ - - // Send calculated power to wheels - leftFrontDrive.setPower(leftFrontPower); - rightFrontDrive.setPower(rightFrontPower); - leftBackDrive.setPower(leftBackPower); - rightBackDrive.setPower(rightBackPower); - - // Show the elapsed game time and wheel power. - telemetry.addData("Status", "Run Time: " + runtime.toString()); - telemetry.addData("Front left/Right", "%4.2f, %4.2f", leftFrontPower, rightFrontPower); - telemetry.addData("Back left/Right", "%4.2f, %4.2f", leftBackPower, rightBackPower); - telemetry.update(); - } - }} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Iterative.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Iterative.java deleted file mode 100644 index 6504e58a..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Iterative.java +++ /dev/null @@ -1,140 +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.OpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; -import com.qualcomm.robotcore.util.Range; - -/* - * This file contains an example of an iterative (Non-Linear) "OpMode". - * An OpMode is a 'program' that runs in either the autonomous or the teleop period of an FTC match. - * The names of OpModes appear on the menu of the FTC Driver Station. - * When a selection is made from the menu, the corresponding OpMode - * class is instantiated on the Robot Controller and executed. - * - * This particular OpMode just executes a basic Tank Drive Teleop for a two wheeled robot - * It includes all the skeletal structure that all iterative OpModes contain. - * - * 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="Basic: Iterative OpMode", group="Iterative OpMode") -@Disabled -public class BasicOpMode_Iterative extends OpMode -{ - // Declare OpMode members. - private ElapsedTime runtime = new ElapsedTime(); - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - - /* - * Code to run ONCE when the driver hits INIT - */ - @Override - public void init() { - telemetry.addData("Status", "Initialized"); - - // 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(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left stick forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // Tell the driver that initialization is complete. - telemetry.addData("Status", "Initialized"); - } - - /* - * Code to run REPEATEDLY after the driver hits INIT, but before they hit START - */ - @Override - public void init_loop() { - } - - /* - * Code to run ONCE when the driver hits START - */ - @Override - public void start() { - runtime.reset(); - } - - /* - * Code to run REPEATEDLY after the driver hits START but before they hit STOP - */ - @Override - public void loop() { - // 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); - } - - /* - * Code to run ONCE after the driver hits STOP - */ - @Override - public void stop() { - } - -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Linear.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Linear.java deleted file mode 100644 index ab0bb254..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/BasicOpMode_Linear.java +++ /dev/null @@ -1,115 +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.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; -import com.qualcomm.robotcore.util.Range; - - -/* - * This file contains an minimal example of a Linear "OpMode". An OpMode is a 'program' that runs in either - * the autonomous or the teleop period of an FTC match. The names of OpModes appear on the menu - * of the FTC Driver Station. When a selection is made from the menu, the corresponding OpMode - * class is instantiated on the Robot Controller and executed. - * - * This particular OpMode just executes a basic Tank Drive Teleop for a two wheeled robot - * It includes all the skeletal structure that all linear OpModes contain. - * - * 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="Basic: Linear OpMode", group="Linear OpMode") -@Disabled -public class BasicOpMode_Linear extends LinearOpMode { - - // Declare OpMode members. - private ElapsedTime runtime = new ElapsedTime(); - private DcMotor leftDrive = null; - private DcMotor 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(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left stick forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // Wait for the game to start (driver presses START) - 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/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTag.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTag.java deleted file mode 100644 index 8ec77dd8..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTag.java +++ /dev/null @@ -1,217 +0,0 @@ -/* Copyright (c) 2023 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.util.Size; -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.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; - -/* - * This OpMode illustrates the basics of AprilTag recognition and pose estimation, - * including Java Builder structures for specifying Vision parameters. - * - * For an introduction to AprilTags, see the FTC-DOCS link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * In this sample, any visible tag ID will be detected and displayed, but only tags that are included in the default - * "TagLibrary" will have their position and orientation information displayed. This default TagLibrary contains - * the current Season's AprilTags and a small set of "test Tags" in the high number range. - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the tag, relative to the camera. - * This information is provided in the "ftcPose" member of the returned "detection", and is explained in the ftc-docs page linked below. - * https://ftc-docs.firstinspires.org/apriltag-detection-values - * - * To experiment with using AprilTags to navigate, try out these two driving samples: - * RobotAutoDriveToAprilTagOmni and RobotAutoDriveToAprilTagTank - * - * There are many "default" VisionPortal and AprilTag configuration parameters that may be overridden if desired. - * These default parameters are shown as comments in the code below. - * - * 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 = "Concept: AprilTag", group = "Concept") -@Disabled -public class ConceptAprilTag extends LinearOpMode { - - private static final boolean USE_WEBCAM = true; // true for webcam, false for phone camera - - /** - * The variable to store our instance of the AprilTag processor. - */ - private AprilTagProcessor aprilTag; - - /** - * The variable to store our instance of the vision portal. - */ - private VisionPortal visionPortal; - - @Override - public void runOpMode() { - - initAprilTag(); - - // Wait for the DS start button to be touched. - telemetry.addData("DS preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - if (opModeIsActive()) { - while (opModeIsActive()) { - - telemetryAprilTag(); - - // Push telemetry to the Driver Station. - telemetry.update(); - - // Save CPU resources; can resume streaming when needed. - if (gamepad1.dpad_down) { - visionPortal.stopStreaming(); - } else if (gamepad1.dpad_up) { - visionPortal.resumeStreaming(); - } - - // Share the CPU. - sleep(20); - } - } - - // Save more CPU resources when camera is no longer needed. - visionPortal.close(); - - } // end method runOpMode() - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - - // Create the AprilTag processor. - aprilTag = new AprilTagProcessor.Builder() - - // The following default settings are available to un-comment and edit as needed. - //.setDrawAxes(false) - //.setDrawCubeProjection(false) - //.setDrawTagOutline(true) - //.setTagFamily(AprilTagProcessor.TagFamily.TAG_36h11) - //.setTagLibrary(AprilTagGameDatabase.getCenterStageTagLibrary()) - //.setOutputUnits(DistanceUnit.INCH, AngleUnit.DEGREES) - - // == CAMERA CALIBRATION == - // If you do not manually specify calibration parameters, the SDK will attempt - // to load a predefined calibration for your camera. - //.setLensIntrinsics(578.272, 578.272, 402.145, 221.506) - // ... these parameters are fx, fy, cx, cy. - - .build(); - - // Adjust Image Decimation to trade-off detection-range for detection-rate. - // eg: Some typical detection data using a Logitech C920 WebCam - // Decimation = 1 .. Detect 2" Tag from 10 feet away at 10 Frames per second - // Decimation = 2 .. Detect 2" Tag from 6 feet away at 22 Frames per second - // Decimation = 3 .. Detect 2" Tag from 4 feet away at 30 Frames Per Second (default) - // Decimation = 3 .. Detect 5" Tag from 10 feet away at 30 Frames Per Second (default) - // Note: Decimation can be changed on-the-fly to adapt during a match. - //aprilTag.setDecimation(3); - - // Create the vision portal by using a builder. - VisionPortal.Builder builder = new VisionPortal.Builder(); - - // Set the camera (webcam vs. built-in RC phone camera). - if (USE_WEBCAM) { - builder.setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")); - } else { - builder.setCamera(BuiltinCameraDirection.BACK); - } - - // Choose a camera resolution. Not all cameras support all resolutions. - //builder.setCameraResolution(new Size(640, 480)); - - // Enable the RC preview (LiveView). Set "false" to omit camera monitoring. - //builder.enableLiveView(true); - - // Set the stream format; MJPEG uses less bandwidth than default YUY2. - //builder.setStreamFormat(VisionPortal.StreamFormat.YUY2); - - // Choose whether or not LiveView stops if no processors are enabled. - // If set "true", monitor shows solid orange screen if no processors enabled. - // If set "false", monitor shows camera view without annotations. - //builder.setAutoStopLiveView(false); - - // Set and enable the processor. - builder.addProcessor(aprilTag); - - // Build the Vision Portal, using the above settings. - visionPortal = builder.build(); - - // Disable or re-enable the aprilTag processor at any time. - //visionPortal.setProcessorEnabled(aprilTag, true); - - } // end method initAprilTag() - - - /** - * Add telemetry about AprilTag detections. - */ - private void telemetryAprilTag() { - - List currentDetections = aprilTag.getDetections(); - telemetry.addData("# AprilTags Detected", currentDetections.size()); - - // Step through the list of detections and display info for each one. - for (AprilTagDetection detection : currentDetections) { - if (detection.metadata != null) { - telemetry.addLine(String.format("\n==== (ID %d) %s", detection.id, detection.metadata.name)); - telemetry.addLine(String.format("XYZ %6.1f %6.1f %6.1f (inch)", detection.ftcPose.x, detection.ftcPose.y, detection.ftcPose.z)); - telemetry.addLine(String.format("PRY %6.1f %6.1f %6.1f (deg)", detection.ftcPose.pitch, detection.ftcPose.roll, detection.ftcPose.yaw)); - telemetry.addLine(String.format("RBE %6.1f %6.1f %6.1f (inch, deg, deg)", detection.ftcPose.range, detection.ftcPose.bearing, detection.ftcPose.elevation)); - } else { - telemetry.addLine(String.format("\n==== (ID %d) Unknown", detection.id)); - telemetry.addLine(String.format("Center %6.0f %6.0f (pixels)", detection.center.x, detection.center.y)); - } - } // end for() loop - - // Add "key" information to telemetry - telemetry.addLine("\nkey:\nXYZ = X (Right), Y (Forward), Z (Up) dist."); - telemetry.addLine("PRY = Pitch, Roll & Yaw (XYZ Rotation)"); - telemetry.addLine("RBE = Range, Bearing & Elevation"); - - } // end method telemetryAprilTag() - -} // end class diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagEasy.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagEasy.java deleted file mode 100644 index 12dcf6e9..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagEasy.java +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright (c) 2023 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 org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; - -/* - * This OpMode illustrates the basics of AprilTag recognition and pose estimation, using - * the easy way. - * - * For an introduction to AprilTags, see the FTC-DOCS link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * In this sample, any visible tag ID will be detected and displayed, but only tags that are included in the default - * "TagLibrary" will have their position and orientation information displayed. This default TagLibrary contains - * the current Season's AprilTags and a small set of "test Tags" in the high number range. - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the tag, relative to the camera. - * This information is provided in the "ftcPose" member of the returned "detection", and is explained in the ftc-docs page linked below. - * https://ftc-docs.firstinspires.org/apriltag-detection-values - * - * To experiment with using AprilTags to navigate, try out these two driving samples: - * RobotAutoDriveToAprilTagOmni and RobotAutoDriveToAprilTagTank - * - * 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 = "Concept: AprilTag Easy", group = "Concept") -@Disabled -public class ConceptAprilTagEasy extends LinearOpMode { - - private static final boolean USE_WEBCAM = true; // true for webcam, false for phone camera - - /** - * The variable to store our instance of the AprilTag processor. - */ - private AprilTagProcessor aprilTag; - - /** - * The variable to store our instance of the vision portal. - */ - private VisionPortal visionPortal; - - @Override - public void runOpMode() { - - initAprilTag(); - - // Wait for the DS start button to be touched. - telemetry.addData("DS preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - if (opModeIsActive()) { - while (opModeIsActive()) { - - telemetryAprilTag(); - - // Push telemetry to the Driver Station. - telemetry.update(); - - // Save CPU resources; can resume streaming when needed. - if (gamepad1.dpad_down) { - visionPortal.stopStreaming(); - } else if (gamepad1.dpad_up) { - visionPortal.resumeStreaming(); - } - - // Share the CPU. - sleep(20); - } - } - - // Save more CPU resources when camera is no longer needed. - visionPortal.close(); - - } // end method runOpMode() - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - - // Create the AprilTag processor the easy way. - aprilTag = AprilTagProcessor.easyCreateWithDefaults(); - - // Create the vision portal the easy way. - if (USE_WEBCAM) { - visionPortal = VisionPortal.easyCreateWithDefaults( - hardwareMap.get(WebcamName.class, "Webcam 1"), aprilTag); - } else { - visionPortal = VisionPortal.easyCreateWithDefaults( - BuiltinCameraDirection.BACK, aprilTag); - } - - } // end method initAprilTag() - - /** - * Add telemetry about AprilTag detections. - */ - private void telemetryAprilTag() { - - List currentDetections = aprilTag.getDetections(); - telemetry.addData("# AprilTags Detected", currentDetections.size()); - - // Step through the list of detections and display info for each one. - for (AprilTagDetection detection : currentDetections) { - if (detection.metadata != null) { - telemetry.addLine(String.format("\n==== (ID %d) %s", detection.id, detection.metadata.name)); - telemetry.addLine(String.format("XYZ %6.1f %6.1f %6.1f (inch)", detection.ftcPose.x, detection.ftcPose.y, detection.ftcPose.z)); - telemetry.addLine(String.format("PRY %6.1f %6.1f %6.1f (deg)", detection.ftcPose.pitch, detection.ftcPose.roll, detection.ftcPose.yaw)); - telemetry.addLine(String.format("RBE %6.1f %6.1f %6.1f (inch, deg, deg)", detection.ftcPose.range, detection.ftcPose.bearing, detection.ftcPose.elevation)); - } else { - telemetry.addLine(String.format("\n==== (ID %d) Unknown", detection.id)); - telemetry.addLine(String.format("Center %6.0f %6.0f (pixels)", detection.center.x, detection.center.y)); - } - } // end for() loop - - // Add "key" information to telemetry - telemetry.addLine("\nkey:\nXYZ = X (Right), Y (Forward), Z (Up) dist."); - telemetry.addLine("PRY = Pitch, Roll & Yaw (XYZ Rotation)"); - telemetry.addLine("RBE = Range, Bearing & Elevation"); - - } // end method telemetryAprilTag() - -} // end class diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagLocalization.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagLocalization.java deleted file mode 100644 index d90261ef..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagLocalization.java +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (c) 2024 Dryw Wade. 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 org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; -import org.firstinspires.ftc.robotcore.external.navigation.Position; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; - -/* - * This OpMode illustrates the basics of AprilTag based localization. - * - * For an introduction to AprilTags, see the FTC-DOCS link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * In this sample, any visible tag ID will be detected and displayed, but only tags that are included in the default - * "TagLibrary" will be used to compute the robot's location and orientation. This default TagLibrary contains - * the current Season's AprilTags and a small set of "test Tags" in the high number range. - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the robot, relative to the field origin. - * This information is provided in the "robotPose" member of the returned "detection". - * - * To learn about the Field Coordinate System that is defined for FTC (and used by this OpMode), see the FTC-DOCS link below: - * https://ftc-docs.firstinspires.org/en/latest/game_specific_resources/field_coordinate_system/field-coordinate-system.html - * - * 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 = "Concept: AprilTag Localization", group = "Concept") -@Disabled -public class ConceptAprilTagLocalization extends LinearOpMode { - - private static final boolean USE_WEBCAM = true; // true for webcam, false for phone camera - - /** - * Variables to store the position and orientation of the camera on the robot. Setting these - * values requires a definition of the axes of the camera and robot: - * - * Camera axes: - * Origin location: Center of the lens - * Axes orientation: +x right, +y down, +z forward (from camera's perspective) - * - * Robot axes (this is typical, but you can define this however you want): - * Origin location: Center of the robot at field height - * Axes orientation: +x right, +y forward, +z upward - * - * Position: - * If all values are zero (no translation), that implies the camera is at the center of the - * robot. Suppose your camera is positioned 5 inches to the left, 7 inches forward, and 12 - * inches above the ground - you would need to set the position to (-5, 7, 12). - * - * Orientation: - * If all values are zero (no rotation), that implies the camera is pointing straight up. In - * most cases, you'll need to set the pitch to -90 degrees (rotation about the x-axis), meaning - * the camera is horizontal. Use a yaw of 0 if the camera is pointing forwards, +90 degrees if - * it's pointing straight left, -90 degrees for straight right, etc. You can also set the roll - * to +/-90 degrees if it's vertical, or 180 degrees if it's upside-down. - */ - private Position cameraPosition = new Position(DistanceUnit.INCH, - 0, 0, 0, 0); - private YawPitchRollAngles cameraOrientation = new YawPitchRollAngles(AngleUnit.DEGREES, - 0, -90, 0, 0); - - /** - * The variable to store our instance of the AprilTag processor. - */ - private AprilTagProcessor aprilTag; - - /** - * The variable to store our instance of the vision portal. - */ - private VisionPortal visionPortal; - - @Override - public void runOpMode() { - - initAprilTag(); - - // Wait for the DS start button to be touched. - telemetry.addData("DS preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) { - - telemetryAprilTag(); - - // Push telemetry to the Driver Station. - telemetry.update(); - - // Save CPU resources; can resume streaming when needed. - if (gamepad1.dpad_down) { - visionPortal.stopStreaming(); - } else if (gamepad1.dpad_up) { - visionPortal.resumeStreaming(); - } - - // Share the CPU. - sleep(20); - } - - // Save more CPU resources when camera is no longer needed. - visionPortal.close(); - - } // end method runOpMode() - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - - // Create the AprilTag processor. - aprilTag = new AprilTagProcessor.Builder() - - // The following default settings are available to un-comment and edit as needed. - //.setDrawAxes(false) - //.setDrawCubeProjection(false) - //.setDrawTagOutline(true) - //.setTagFamily(AprilTagProcessor.TagFamily.TAG_36h11) - //.setTagLibrary(AprilTagGameDatabase.getCenterStageTagLibrary()) - //.setOutputUnits(DistanceUnit.INCH, AngleUnit.DEGREES) - .setCameraPose(cameraPosition, cameraOrientation) - - // == CAMERA CALIBRATION == - // If you do not manually specify calibration parameters, the SDK will attempt - // to load a predefined calibration for your camera. - //.setLensIntrinsics(578.272, 578.272, 402.145, 221.506) - // ... these parameters are fx, fy, cx, cy. - - .build(); - - // Adjust Image Decimation to trade-off detection-range for detection-rate. - // eg: Some typical detection data using a Logitech C920 WebCam - // Decimation = 1 .. Detect 2" Tag from 10 feet away at 10 Frames per second - // Decimation = 2 .. Detect 2" Tag from 6 feet away at 22 Frames per second - // Decimation = 3 .. Detect 2" Tag from 4 feet away at 30 Frames Per Second (default) - // Decimation = 3 .. Detect 5" Tag from 10 feet away at 30 Frames Per Second (default) - // Note: Decimation can be changed on-the-fly to adapt during a match. - //aprilTag.setDecimation(3); - - // Create the vision portal by using a builder. - VisionPortal.Builder builder = new VisionPortal.Builder(); - - // Set the camera (webcam vs. built-in RC phone camera). - if (USE_WEBCAM) { - builder.setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")); - } else { - builder.setCamera(BuiltinCameraDirection.BACK); - } - - // Choose a camera resolution. Not all cameras support all resolutions. - //builder.setCameraResolution(new Size(640, 480)); - - // Enable the RC preview (LiveView). Set "false" to omit camera monitoring. - //builder.enableLiveView(true); - - // Set the stream format; MJPEG uses less bandwidth than default YUY2. - //builder.setStreamFormat(VisionPortal.StreamFormat.YUY2); - - // Choose whether or not LiveView stops if no processors are enabled. - // If set "true", monitor shows solid orange screen if no processors enabled. - // If set "false", monitor shows camera view without annotations. - //builder.setAutoStopLiveView(false); - - // Set and enable the processor. - builder.addProcessor(aprilTag); - - // Build the Vision Portal, using the above settings. - visionPortal = builder.build(); - - // Disable or re-enable the aprilTag processor at any time. - //visionPortal.setProcessorEnabled(aprilTag, true); - - } // end method initAprilTag() - - /** - * Add telemetry about AprilTag detections. - */ - private void telemetryAprilTag() { - - List currentDetections = aprilTag.getDetections(); - telemetry.addData("# AprilTags Detected", currentDetections.size()); - - // Step through the list of detections and display info for each one. - for (AprilTagDetection detection : currentDetections) { - if (detection.metadata != null) { - telemetry.addLine(String.format("\n==== (ID %d) %s", detection.id, detection.metadata.name)); - telemetry.addLine(String.format("XYZ %6.1f %6.1f %6.1f (inch)", - detection.robotPose.getPosition().x, - detection.robotPose.getPosition().y, - detection.robotPose.getPosition().z)); - telemetry.addLine(String.format("PRY %6.1f %6.1f %6.1f (deg)", - detection.robotPose.getOrientation().getPitch(AngleUnit.DEGREES), - detection.robotPose.getOrientation().getRoll(AngleUnit.DEGREES), - detection.robotPose.getOrientation().getYaw(AngleUnit.DEGREES))); - } else { - telemetry.addLine(String.format("\n==== (ID %d) Unknown", detection.id)); - telemetry.addLine(String.format("Center %6.0f %6.0f (pixels)", detection.center.x, detection.center.y)); - } - } // end for() loop - - // Add "key" information to telemetry - telemetry.addLine("\nkey:\nXYZ = X (Right), Y (Forward), Z (Up) dist."); - telemetry.addLine("PRY = Pitch, Roll & Yaw (XYZ Rotation)"); - - } // end method telemetryAprilTag() - -} // end class diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagMultiPortal.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagMultiPortal.java deleted file mode 100644 index da5cc3ed..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagMultiPortal.java +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (c) 2024 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 org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -/** - * This OpMode demonstrates the basics of using multiple vision portals simultaneously - */ -@TeleOp(name = "Concept: AprilTagMultiPortal", group = "Concept") -@Disabled -public class ConceptAprilTagMultiPortal extends LinearOpMode -{ - VisionPortal portal1; - VisionPortal portal2; - - AprilTagProcessor aprilTagProcessor1; - AprilTagProcessor aprilTagProcessor2; - - @Override - public void runOpMode() throws InterruptedException - { - // Because we want to show two camera feeds simultaneously, we need to inform - // the SDK that we want it to split the camera monitor area into two smaller - // areas for us. It will then give us View IDs which we can pass to the individual - // vision portals to allow them to properly hook into the UI in tandem. - int[] viewIds = VisionPortal.makeMultiPortalView(2, VisionPortal.MultiPortalLayout.VERTICAL); - - // We extract the two view IDs from the array to make our lives a little easier later. - // NB: the array is 2 long because we asked for 2 portals up above. - int portal1ViewId = viewIds[0]; - int portal2ViewId = viewIds[1]; - - // If we want to run AprilTag detection on two portals simultaneously, - // we need to create two distinct instances of the AprilTag processor, - // one for each portal. If you want to see more detail about different - // options that you have when creating these processors, go check out - // the ConceptAprilTag OpMode. - aprilTagProcessor1 = AprilTagProcessor.easyCreateWithDefaults(); - aprilTagProcessor2 = AprilTagProcessor.easyCreateWithDefaults(); - - // Now we build both portals. The CRITICAL thing to notice here is the call to - // setLiveViewContainerId(), where we pass in the IDs we received earlier from - // makeMultiPortalView(). - portal1 = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .setLiveViewContainerId(portal1ViewId) - .addProcessor(aprilTagProcessor1) - .build(); - portal2 = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 2")) - .setLiveViewContainerId(portal2ViewId) - .addProcessor(aprilTagProcessor2) - .build(); - - waitForStart(); - - // Main Loop - while (opModeIsActive()) - { - // Just show some basic telemetry to demonstrate both processors are working in parallel - // on their respective cameras. If you want to see more detail about the information you - // can get back from the processor, you should look at ConceptAprilTag. - telemetry.addData("Number of tags in Camera 1", aprilTagProcessor1.getDetections().size()); - telemetry.addData("Number of tags in Camera 2", aprilTagProcessor2.getDetections().size()); - telemetry.update(); - sleep(20); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagOptimizeExposure.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagOptimizeExposure.java deleted file mode 100644 index adee952b..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagOptimizeExposure.java +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright (c) 2023 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; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.ExposureControl; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.GainControl; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -/* - * This OpMode determines the best Exposure for minimizing image motion-blur on a Webcam - * Note that it is not possible to control the exposure for a Phone Camera, so if you are using a Phone for the Robot Controller - * this OpMode/Feature only applies to an externally connected Webcam - * - * The goal is to determine the smallest (shortest) Exposure value that still provides reliable Tag Detection. - * Starting with the minimum Exposure and maximum Gain, the exposure is slowly increased until the Tag is - * detected reliably from the likely operational distance. - * - * - * The best way to run this optimization is to view the camera preview screen while changing the exposure and gains. - * - * To do this, you need to view the RobotController screen directly (not from Driver Station) - * This can be done directly from a RC phone screen (if you are using an external Webcam), but for a Control Hub you must either plug an - * HDMI monitor into the Control Hub HDMI port, or use an external viewer program like ScrCpy (https://scrcpy.org/) - * - * Use Android Studio to Copy this Class, and Paste it into the TeamCode/src/main/java/org/firstinspires/ftc/teamcode folder. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list. - */ - -@TeleOp(name="Optimize AprilTag Exposure", group = "Concept") -@Disabled -public class ConceptAprilTagOptimizeExposure extends LinearOpMode -{ - private VisionPortal visionPortal = null; // Used to manage the video source. - private AprilTagProcessor aprilTag; // Used for managing the AprilTag detection process. - private int myExposure ; - private int minExposure ; - private int maxExposure ; - private int myGain ; - private int minGain ; - private int maxGain ; - - boolean thisExpUp = false; - boolean thisExpDn = false; - boolean thisGainUp = false; - boolean thisGainDn = false; - - boolean lastExpUp = false; - boolean lastExpDn = false; - boolean lastGainUp = false; - boolean lastGainDn = false; - @Override public void runOpMode() - { - // Initialize the Apriltag Detection process - initAprilTag(); - - // Establish Min and Max Gains and Exposure. Then set a low exposure with high gain - getCameraSetting(); - myExposure = Math.min(5, minExposure); - myGain = maxGain; - setManualExposure(myExposure, myGain); - - // Wait for the match to begin. - telemetry.addData("Camera preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) - { - telemetry.addLine("Find lowest Exposure that gives reliable detection."); - telemetry.addLine("Use Left bump/trig to adjust Exposure."); - telemetry.addLine("Use Right bump/trig to adjust Gain.\n"); - - // Display how many Tags Detected - List currentDetections = aprilTag.getDetections(); - int numTags = currentDetections.size(); - if (numTags > 0 ) - telemetry.addData("Tag", "####### %d Detected ######", currentDetections.size()); - else - telemetry.addData("Tag", "----------- none - ----------"); - - telemetry.addData("Exposure","%d (%d - %d)", myExposure, minExposure, maxExposure); - telemetry.addData("Gain","%d (%d - %d)", myGain, minGain, maxGain); - telemetry.update(); - - // check to see if we need to change exposure or gain. - thisExpUp = gamepad1.left_bumper; - thisExpDn = gamepad1.left_trigger > 0.25; - thisGainUp = gamepad1.right_bumper; - thisGainDn = gamepad1.right_trigger > 0.25; - - // look for clicks to change exposure - if (thisExpUp && !lastExpUp) { - myExposure = Range.clip(myExposure + 1, minExposure, maxExposure); - setManualExposure(myExposure, myGain); - } else if (thisExpDn && !lastExpDn) { - myExposure = Range.clip(myExposure - 1, minExposure, maxExposure); - setManualExposure(myExposure, myGain); - } - - // look for clicks to change the gain - if (thisGainUp && !lastGainUp) { - myGain = Range.clip(myGain + 1, minGain, maxGain ); - setManualExposure(myExposure, myGain); - } else if (thisGainDn && !lastGainDn) { - myGain = Range.clip(myGain - 1, minGain, maxGain ); - setManualExposure(myExposure, myGain); - } - - lastExpUp = thisExpUp; - lastExpDn = thisExpDn; - lastGainUp = thisGainUp; - lastGainDn = thisGainDn; - - sleep(20); - } - } - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - // Create the AprilTag processor by using a builder. - aprilTag = new AprilTagProcessor.Builder().build(); - - // Create the WEBCAM vision portal by using a builder. - visionPortal = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .addProcessor(aprilTag) - .build(); - } - - /* - Manually set the camera gain and exposure. - Can only be called AFTER calling initAprilTag(); - Returns true if controls are set. - */ - private boolean setManualExposure(int exposureMS, int gain) { - // Ensure Vision Portal has been setup. - if (visionPortal == null) { - return false; - } - - // Wait for the camera to be open - if (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING) { - telemetry.addData("Camera", "Waiting"); - telemetry.update(); - while (!isStopRequested() && (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING)) { - sleep(20); - } - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - - // Set camera controls unless we are stopping. - if (!isStopRequested()) - { - // Set exposure. Make sure we are in Manual Mode for these values to take effect. - ExposureControl exposureControl = visionPortal.getCameraControl(ExposureControl.class); - if (exposureControl.getMode() != ExposureControl.Mode.Manual) { - exposureControl.setMode(ExposureControl.Mode.Manual); - sleep(50); - } - exposureControl.setExposure((long)exposureMS, TimeUnit.MILLISECONDS); - sleep(20); - - // Set Gain. - GainControl gainControl = visionPortal.getCameraControl(GainControl.class); - gainControl.setGain(gain); - sleep(20); - return (true); - } else { - return (false); - } - } - - /* - Read this camera's minimum and maximum Exposure and Gain settings. - Can only be called AFTER calling initAprilTag(); - */ - private void getCameraSetting() { - // Ensure Vision Portal has been setup. - if (visionPortal == null) { - return; - } - - // Wait for the camera to be open - if (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING) { - telemetry.addData("Camera", "Waiting"); - telemetry.update(); - while (!isStopRequested() && (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING)) { - sleep(20); - } - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - - // Get camera control values unless we are stopping. - if (!isStopRequested()) { - ExposureControl exposureControl = visionPortal.getCameraControl(ExposureControl.class); - minExposure = (int)exposureControl.getMinExposure(TimeUnit.MILLISECONDS) + 1; - maxExposure = (int)exposureControl.getMaxExposure(TimeUnit.MILLISECONDS); - - GainControl gainControl = visionPortal.getCameraControl(GainControl.class); - minGain = gainControl.getMinGain(); - maxGain = gainControl.getMaxGain(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagSwitchableCameras.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagSwitchableCameras.java deleted file mode 100644 index 7ee1064b..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptAprilTagSwitchableCameras.java +++ /dev/null @@ -1,196 +0,0 @@ -/* Copyright (c) 2023 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 org.firstinspires.ftc.robotcore.external.ClassFactory; -import org.firstinspires.ftc.robotcore.external.hardware.camera.CameraName; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.VisionPortal.CameraState; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; - -/* - * This OpMode illustrates the basics of AprilTag recognition and pose estimation, using - * two webcams. - * - * 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 = "Concept: AprilTag Switchable Cameras", group = "Concept") -@Disabled -public class ConceptAprilTagSwitchableCameras extends LinearOpMode { - - /* - * Variables used for switching cameras. - */ - private WebcamName webcam1, webcam2; - private boolean oldLeftBumper; - private boolean oldRightBumper; - - /** - * The variable to store our instance of the AprilTag processor. - */ - private AprilTagProcessor aprilTag; - - /** - * The variable to store our instance of the vision portal. - */ - private VisionPortal visionPortal; - - @Override - public void runOpMode() { - - initAprilTag(); - - // Wait for the DS start button to be touched. - telemetry.addData("DS preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - if (opModeIsActive()) { - while (opModeIsActive()) { - - telemetryCameraSwitching(); - telemetryAprilTag(); - - // Push telemetry to the Driver Station. - telemetry.update(); - - // Save CPU resources; can resume streaming when needed. - if (gamepad1.dpad_down) { - visionPortal.stopStreaming(); - } else if (gamepad1.dpad_up) { - visionPortal.resumeStreaming(); - } - - doCameraSwitching(); - - // Share the CPU. - sleep(20); - } - } - - // Save more CPU resources when camera is no longer needed. - visionPortal.close(); - - } // end runOpMode() - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - - // Create the AprilTag processor by using a builder. - aprilTag = new AprilTagProcessor.Builder().build(); - - webcam1 = hardwareMap.get(WebcamName.class, "Webcam 1"); - webcam2 = hardwareMap.get(WebcamName.class, "Webcam 2"); - CameraName switchableCamera = ClassFactory.getInstance() - .getCameraManager().nameForSwitchableCamera(webcam1, webcam2); - - // Create the vision portal by using a builder. - visionPortal = new VisionPortal.Builder() - .setCamera(switchableCamera) - .addProcessor(aprilTag) - .build(); - - } // end method initAprilTag() - - /** - * Add telemetry about camera switching. - */ - private void telemetryCameraSwitching() { - - if (visionPortal.getActiveCamera().equals(webcam1)) { - telemetry.addData("activeCamera", "Webcam 1"); - telemetry.addData("Press RightBumper", "to switch to Webcam 2"); - } else { - telemetry.addData("activeCamera", "Webcam 2"); - telemetry.addData("Press LeftBumper", "to switch to Webcam 1"); - } - - } // end method telemetryCameraSwitching() - - /** - * Add telemetry about AprilTag detections. - */ - private void telemetryAprilTag() { - - List currentDetections = aprilTag.getDetections(); - telemetry.addData("# AprilTags Detected", currentDetections.size()); - - // Step through the list of detections and display info for each one. - for (AprilTagDetection detection : currentDetections) { - if (detection.metadata != null) { - telemetry.addLine(String.format("\n==== (ID %d) %s", detection.id, detection.metadata.name)); - telemetry.addLine(String.format("XYZ %6.1f %6.1f %6.1f (inch)", detection.ftcPose.x, detection.ftcPose.y, detection.ftcPose.z)); - telemetry.addLine(String.format("PRY %6.1f %6.1f %6.1f (deg)", detection.ftcPose.pitch, detection.ftcPose.roll, detection.ftcPose.yaw)); - telemetry.addLine(String.format("RBE %6.1f %6.1f %6.1f (inch, deg, deg)", detection.ftcPose.range, detection.ftcPose.bearing, detection.ftcPose.elevation)); - } else { - telemetry.addLine(String.format("\n==== (ID %d) Unknown", detection.id)); - telemetry.addLine(String.format("Center %6.0f %6.0f (pixels)", detection.center.x, detection.center.y)); - } - } // end for() loop - - // Add "key" information to telemetry - telemetry.addLine("\nkey:\nXYZ = X (Right), Y (Forward), Z (Up) dist."); - telemetry.addLine("PRY = Pitch, Roll & Yaw (XYZ Rotation)"); - telemetry.addLine("RBE = Range, Bearing & Elevation"); - - } // end method telemetryAprilTag() - - /** - * Set the active camera according to input from the gamepad. - */ - private void doCameraSwitching() { - if (visionPortal.getCameraState() == CameraState.STREAMING) { - // If the left bumper is pressed, use Webcam 1. - // If the right bumper is pressed, use Webcam 2. - boolean newLeftBumper = gamepad1.left_bumper; - boolean newRightBumper = gamepad1.right_bumper; - if (newLeftBumper && !oldLeftBumper) { - visionPortal.setActiveCamera(webcam1); - } else if (newRightBumper && !oldRightBumper) { - visionPortal.setActiveCamera(webcam2); - } - oldLeftBumper = newLeftBumper; - oldRightBumper = newRightBumper; - } - - } // end method doCameraSwitching() - -} // end class diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExploringIMUOrientation.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExploringIMUOrientation.java deleted file mode 100644 index 751d54f9..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExploringIMUOrientation.java +++ /dev/null @@ -1,184 +0,0 @@ -/* -Copyright (c) 2022 REV Robotics, 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 REV Robotics 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.RevHubOrientationOnRobot; -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.IMU; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; - -/* - * This OpMode demonstrates the impact of setting the IMU orientation correctly or incorrectly. This - * code assumes there is an IMU configured with the name "imu". - * - * Note: This OpMode is more of a tool than a code sample. The User Interface portion of this code - * goes beyond simply showing how to interface to the IMU.
- * For a minimal example of interfacing to an IMU, please see the SensorIMUOrthogonal or SensorIMUNonOrthogonal sample OpModes. - * - * This OpMode enables you to re-specify the Hub Mounting orientation dynamically by using gamepad controls. - * While doing so, the sample will display how Pitch, Roll and Yaw angles change as the hub is moved. - * - * The gamepad controls let you change the two parameters that specify how the Control/Expansion Hub is mounted.
- * The first parameter specifies which direction the printed logo on the Hub is pointing.
- * The second parameter specifies which direction the USB connector on the Hub is pointing.
- * All directions are relative to the robot, and left/right is as viewed from behind the robot. - * - * How will you know if you have chosen the correct Orientation? With the correct orientation - * parameters selected, pitch/roll/yaw should act as follows: - * - * Pitch value should INCREASE as the robot is tipped UP at the front. (Rotation about X)
- * Roll value should INCREASE as the robot is tipped UP at the left side. (Rotation about Y)
- * Yaw value should INCREASE as the robot is rotated Counter Clockwise. (Rotation about Z)
- * - * The Yaw can be reset (to zero) by pressing the Y button on the gamepad (Triangle on a PS4 controller) - * - * The rotational velocities should follow the change in corresponding axes. - */ - -@TeleOp(name="Concept: IMU Orientation", group="Concept") -@Disabled -public class ConceptExploringIMUOrientation extends LinearOpMode { - static RevHubOrientationOnRobot.LogoFacingDirection[] logoFacingDirections - = RevHubOrientationOnRobot.LogoFacingDirection.values(); - static RevHubOrientationOnRobot.UsbFacingDirection[] usbFacingDirections - = RevHubOrientationOnRobot.UsbFacingDirection.values(); - static int LAST_DIRECTION = logoFacingDirections.length - 1; - static float TRIGGER_THRESHOLD = 0.2f; - - IMU imu; - int logoFacingDirectionPosition; - int usbFacingDirectionPosition; - boolean orientationIsValid = true; - - @Override public void runOpMode() throws InterruptedException { - imu = hardwareMap.get(IMU.class, "imu"); - logoFacingDirectionPosition = 0; // Up - usbFacingDirectionPosition = 2; // Forward - - updateOrientation(); - - boolean justChangedLogoDirection = false; - boolean justChangedUsbDirection = false; - - // Loop until stop requested - while (!isStopRequested()) { - - // Check to see if Yaw reset is requested (Y button) - if (gamepad1.y) { - telemetry.addData("Yaw", "Resetting\n"); - imu.resetYaw(); - } else { - telemetry.addData("Yaw", "Press Y (triangle) on Gamepad to reset.\n"); - } - - // Check to see if new Logo Direction is requested - if (gamepad1.left_bumper || gamepad1.right_bumper) { - if (!justChangedLogoDirection) { - justChangedLogoDirection = true; - if (gamepad1.left_bumper) { - logoFacingDirectionPosition--; - if (logoFacingDirectionPosition < 0) { - logoFacingDirectionPosition = LAST_DIRECTION; - } - } else { - logoFacingDirectionPosition++; - if (logoFacingDirectionPosition > LAST_DIRECTION) { - logoFacingDirectionPosition = 0; - } - } - updateOrientation(); - } - } else { - justChangedLogoDirection = false; - } - - // Check to see if new USB Direction is requested - if (gamepad1.left_trigger > TRIGGER_THRESHOLD || gamepad1.right_trigger > TRIGGER_THRESHOLD) { - if (!justChangedUsbDirection) { - justChangedUsbDirection = true; - if (gamepad1.left_trigger > TRIGGER_THRESHOLD) { - usbFacingDirectionPosition--; - if (usbFacingDirectionPosition < 0) { - usbFacingDirectionPosition = LAST_DIRECTION; - } - } else { - usbFacingDirectionPosition++; - if (usbFacingDirectionPosition > LAST_DIRECTION) { - usbFacingDirectionPosition = 0; - } - } - updateOrientation(); - } - } else { - justChangedUsbDirection = false; - } - - // Display User instructions and IMU data - telemetry.addData("logo Direction (set with bumpers)", logoFacingDirections[logoFacingDirectionPosition]); - telemetry.addData("usb Direction (set with triggers)", usbFacingDirections[usbFacingDirectionPosition] + "\n"); - - if (orientationIsValid) { - YawPitchRollAngles orientation = imu.getRobotYawPitchRollAngles(); - AngularVelocity angularVelocity = imu.getRobotAngularVelocity(AngleUnit.DEGREES); - - telemetry.addData("Yaw (Z)", "%.2f Deg. (Heading)", orientation.getYaw(AngleUnit.DEGREES)); - telemetry.addData("Pitch (X)", "%.2f Deg.", orientation.getPitch(AngleUnit.DEGREES)); - telemetry.addData("Roll (Y)", "%.2f Deg.\n", orientation.getRoll(AngleUnit.DEGREES)); - telemetry.addData("Yaw (Z) velocity", "%.2f Deg/Sec", angularVelocity.zRotationRate); - telemetry.addData("Pitch (X) velocity", "%.2f Deg/Sec", angularVelocity.xRotationRate); - telemetry.addData("Roll (Y) velocity", "%.2f Deg/Sec", angularVelocity.yRotationRate); - } else { - telemetry.addData("Error", "Selected orientation on robot is invalid"); - } - - telemetry.update(); - } - } - - // apply any requested orientation changes. - void updateOrientation() { - RevHubOrientationOnRobot.LogoFacingDirection logo = logoFacingDirections[logoFacingDirectionPosition]; - RevHubOrientationOnRobot.UsbFacingDirection usb = usbFacingDirections[usbFacingDirectionPosition]; - try { - RevHubOrientationOnRobot orientationOnRobot = new RevHubOrientationOnRobot(logo, usb); - imu.initialize(new IMU.Parameters(orientationOnRobot)); - orientationIsValid = true; - } catch (IllegalArgumentException e) { - orientationIsValid = false; - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExternalHardwareClass.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExternalHardwareClass.java deleted file mode 100644 index 7a721fef..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptExternalHardwareClass.java +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (c) 2022 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 illustrates how to use an external "hardware" class to modularize all the robot's sensors and actuators. - * This approach is very efficient because the same hardware class can be used by all of your teleop and autonomous OpModes - * without requiring many copy & paste operations. Once you have defined and tested the hardware class with one OpMode, - * it is instantly available to other OpModes. - * - * The real benefit of this approach is that as you tweak your robot hardware, you only need to make changes in ONE place (the Hardware Class). - * So, to be effective you should put as much or your hardware setup and access code as possible in the hardware class. - * Essentially anything you do with hardware in BOTH Teleop and Auto should likely go in the hardware class. - * - * The Hardware Class is created in a separate file, and then an "instance" of this class is created in each OpMode. - * In order for the class to do typical OpMode things (like send telemetry data) it must be passed a reference to the - * OpMode object when it's created, so it can access all core OpMode functions. This is illustrated below. - * - * In this concept sample, the hardware class file is called RobotHardware.java and it must accompany this sample OpMode. - * So, if you copy ConceptExternalHardwareClass.java into TeamCode (using Android Studio or OnBotJava) then RobotHardware.java - * must also be copied to the same location (maintaining its name). - * - * For comparison purposes, this sample and its accompanying hardware class duplicates the functionality of the - * RobotTelopPOV_Linear OpMode. It assumes three motors (left_drive, right_drive and arm) and two servos (left_hand and right_hand) - * - * View the RobotHardware.java class file for more details - * - * 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 - * - * In OnBot Java, add a new OpMode, select this sample, and select TeleOp. - * Also add another new file named RobotHardware.java, select the sample with that name, and select Not an OpMode. - */ - -@TeleOp(name="Concept: Robot Hardware Class", group="Robot") -@Disabled -public class ConceptExternalHardwareClass extends LinearOpMode { - - // Create a RobotHardware object to be used to access robot hardware. - // Prefix any hardware functions with "robot." to access this class. - RobotHardware robot = new RobotHardware(this); - - @Override - public void runOpMode() { - double drive = 0; - double turn = 0; - double arm = 0; - double handOffset = 0; - - // initialize all the hardware, using the hardware class. See how clean and simple this is? - robot.init(); - - // Send telemetry message to signify robot waiting; - // Wait for the game to start (driver presses START) - waitForStart(); - - // run until the end of the match (driver presses STOP) - while (opModeIsActive()) { - - // Run wheels in POV mode (note: The joystick goes negative when pushed forward, so negate it) - // In this mode the Left stick moves the robot fwd and back, the Right stick turns left and right. - // This way it's also easy to just drive straight, or just turn. - drive = -gamepad1.left_stick_y; - turn = gamepad1.right_stick_x; - - // Combine drive and turn for blended motion. Use RobotHardware class - robot.driveRobot(drive, turn); - - // Use gamepad left & right Bumpers to open and close the claw - // Use the SERVO constants defined in RobotHardware class. - // Each time around the loop, the servos will move by a small amount. - // Limit the total offset to half of the full travel range - if (gamepad1.right_bumper) - handOffset += robot.HAND_SPEED; - else if (gamepad1.left_bumper) - handOffset -= robot.HAND_SPEED; - handOffset = Range.clip(handOffset, -0.5, 0.5); - - // Move both servos to new position. Use RobotHardware class - robot.setHandPositions(handOffset); - - // Use gamepad buttons to move arm up (Y) and down (A) - // Use the MOTOR constants defined in RobotHardware class. - if (gamepad1.y) - arm = robot.ARM_UP_POWER; - else if (gamepad1.a) - arm = robot.ARM_DOWN_POWER; - else - arm = 0; - - robot.setArmPower(arm); - - // Send telemetry messages to explain controls and show robot status - telemetry.addData("Drive", "Left Stick"); - telemetry.addData("Turn", "Right Stick"); - telemetry.addData("Arm Up/Down", "Y & A Buttons"); - telemetry.addData("Hand Open/Closed", "Left and Right Bumpers"); - telemetry.addData("-", "-------"); - - telemetry.addData("Drive Power", "%.2f", drive); - telemetry.addData("Turn Power", "%.2f", turn); - telemetry.addData("Arm Power", "%.2f", arm); - telemetry.addData("Hand Position", "Offset = %.2f", handOffset); - telemetry.update(); - - // Pace this loop so hands move at a reasonable speed. - sleep(50); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadRumble.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadRumble.java deleted file mode 100644 index cf846e18..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadRumble.java +++ /dev/null @@ -1,200 +0,0 @@ -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.Gamepad; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * This OpMode illustrates using the rumble feature of many gamepads. - * - * Note: Some gamepads "rumble" better than others. - * The Xbox & PS4 have a left (rumble1) and right (rumble2) rumble motor. - * These two gamepads have two distinct rumble modes: Large on the left, and small on the right - * The Etpark gamepad may only respond to rumble1, and may only run at full power. - * The Logitech F310 gamepad does not have *any* rumble ability. - * - * Moral: You should use this sample to experiment with your specific gamepads to explore their rumble features. - * - * The rumble motors are accessed through the standard gamepad1 and gamepad2 objects. - * Several new methods were added to the Gamepad class in FTC SDK Rev 7 - * The key methods are as follows: - * - * .rumble(double rumble1, double rumble2, int durationMs) - * This method sets the rumble power of both motors for a specific time duration. - * Both rumble arguments are motor-power levels in the 0.0 to 1.0 range. - * durationMs is the desired length of the rumble action in milliseconds. - * This method returns immediately. - * Note: - * Use a durationMs of Gamepad.RUMBLE_DURATION_CONTINUOUS to provide a continuous rumble - * Use a power of 0, or duration of 0 to stop a rumble. - * - * .rumbleBlips(int count) allows an easy way to signal the driver with a series of rumble blips. - * Just specify how many blips you want. - * This method returns immediately. - * - * .runRumbleEffect(customRumbleEffect) allows you to run a custom rumble sequence that you have - * built using the Gamepad.RumbleEffect.Builder() - * A "custom effect" is a sequence of steps, where each step can rumble any of the - * rumble motors for a specific period at a specific power level. - * The Custom Effect will play as the (un-blocked) OpMode continues to run - * - * .isRumbling() returns true if there is a rumble effect in progress. - * Use this call to prevent stepping on a current rumble. - * - * .stopRumble() Stop any ongoing rumble or custom rumble effect. - * - * .rumble(int durationMs) Full power rumble for fixed duration. - * - * Note: Whenever a new Rumble command is issued, any currently executing rumble action will - * be truncated, and the new action started immediately. Take these precautions: - * 1) Do Not SPAM the rumble motors by issuing rapid fire commands - * 2) Multiple sources for rumble commands must coordinate to avoid tromping on each other. - * - * This can be achieved several possible ways: - * 1) Only having one source for rumble actions - * 2) Issuing rumble commands on transitions, rather than states. - * e.g. The moment a touch sensor is pressed, rather than the entire time it is being pressed. - * 3) Scheduling rumble commands based on timed events. e.g. 10 seconds prior to endgame - * 4) Rumble on non-overlapping mechanical actions. e.g. arm fully-extended or fully-retracted. - * 5) Use isRumbling() to hold off on a new rumble if one is already in progress. - * - * The examples shown here are representstive of how to invoke a gamepad rumble. - * It is assumed that these will be modified to suit the specific robot and team strategy needs. - * - * ######## Read the telemetry display on the Driver Station Screen for instructions. ###### - * - * Ex 1) This example shows a) how to create a custom rumble effect, and then b) how to trigger it based - * on game time. One use for this might be to alert the driver that half-time or End-game is approaching. - * - * Ex 2) This example shows tying the rumble power to a changing sensor value. - * In this case it is the Gamepad trigger, but it could be any sensor output scaled to the 0-1 range. - * Since it takes over the rumble motors, it is only performed when the Left Bumper is pressed. - * Note that this approach MUST include a way to turn OFF the rumble when the button is released. - * - * Ex 3) This example shows a simple way to trigger a 3-blip sequence. In this case it is - * triggered by the gamepad A (Cross) button, but it could be any sensor, like a touch or light sensor. - * Note that this code ensures that it only rumbles once when the input goes true. - * - * Ex 4) This example shows how to trigger a single rumble when an input value gets over a certain value. - * In this case it is reading the Right Trigger, but it could be any variable sensor, like a - * range sensor, or position sensor. The code needs to ensure that it is only triggered once, so - * it waits till the sensor drops back below the threshold before it can trigger again. - * - * 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. - */ - -@Disabled -@TeleOp(name="Concept: Gamepad Rumble", group ="Concept") -public class ConceptGamepadRumble extends LinearOpMode -{ - boolean lastA = false; // Use to track the prior button state. - boolean lastLB = false; // Use to track the prior button state. - boolean highLevel = false; // used to prevent multiple level-based rumbles. - boolean secondHalf = false; // Use to prevent multiple half-time warning rumbles. - - Gamepad.RumbleEffect customRumbleEffect; // Use to build a custom rumble sequence. - ElapsedTime runtime = new ElapsedTime(); // Use to determine when end game is starting. - - final double HALF_TIME = 60.0; // Wait this many seconds before rumble-alert for half-time. - final double TRIGGER_THRESHOLD = 0.75; // Squeeze more than 3/4 to get rumble. - - @Override - public void runOpMode() - { - // Example 1. a) start by creating a three-pulse rumble sequence: right, LEFT, LEFT - customRumbleEffect = new Gamepad.RumbleEffect.Builder() - .addStep(0.0, 1.0, 500) // Rumble right motor 100% for 500 mSec - .addStep(0.0, 0.0, 300) // Pause for 300 mSec - .addStep(1.0, 0.0, 250) // Rumble left motor 100% for 250 mSec - .addStep(0.0, 0.0, 250) // Pause for 250 mSec - .addStep(1.0, 0.0, 250) // Rumble left motor 100% for 250 mSec - .build(); - - telemetry.addData(">", "Press Start"); - telemetry.update(); - - waitForStart(); - runtime.reset(); // Start game timer. - - // Loop while monitoring buttons for rumble triggers - while (opModeIsActive()) - { - // Read and save the current gamepad button states. - boolean currentA = gamepad1.a ; - boolean currentLB = gamepad1.left_bumper ; - - // Display the current Rumble status. Just for interest. - telemetry.addData(">", "Are we RUMBLING? %s\n", gamepad1.isRumbling() ? "YES" : "no" ); - - // ---------------------------------------------------------------------------------------- - // Example 1. b) Watch the runtime timer, and run the custom rumble when we hit half-time. - // Make sure we only signal once by setting "secondHalf" flag to prevent further rumbles. - // ---------------------------------------------------------------------------------------- - if ((runtime.seconds() > HALF_TIME) && !secondHalf) { - gamepad1.runRumbleEffect(customRumbleEffect); - secondHalf =true; - } - - // Display the time remaining while we are still counting down. - if (!secondHalf) { - telemetry.addData(">", "Halftime Alert Countdown: %3.0f Sec \n", (HALF_TIME - runtime.seconds()) ); - } - - - // ---------------------------------------------------------------------------------------- - // Example 2. If Left Bumper is being pressed, power the rumble motors based on the two trigger depressions. - // This is useful to see how the rumble feels at various power levels. - // ---------------------------------------------------------------------------------------- - if (currentLB) { - // Left Bumper is being pressed, so send left and right "trigger" values to left and right rumble motors. - gamepad1.rumble(gamepad1.left_trigger, gamepad1.right_trigger, Gamepad.RUMBLE_DURATION_CONTINUOUS); - - // Show what is being sent to rumbles - telemetry.addData(">", "Squeeze triggers to control rumbles"); - telemetry.addData("> : Rumble", "Left: %.0f%% Right: %.0f%%", gamepad1.left_trigger * 100, gamepad1.right_trigger * 100); - } else { - // Make sure rumble is turned off when Left Bumper is released (only one time each press) - if (lastLB) { - gamepad1.stopRumble(); - } - - // Prompt for manual rumble action - telemetry.addData(">", "Hold Left-Bumper to test Manual Rumble"); - telemetry.addData(">", "Press A (Cross) for three blips"); - telemetry.addData(">", "Squeeze right trigger slowly for 1 blip"); - } - lastLB = currentLB; // remember the current button state for next time around the loop - - - // ---------------------------------------------------------------------------------------- - // Example 3. Blip 3 times at the moment that A (Cross) is pressed. (look for pressed transition) - // BUT !!! Skip it altogether if the Gamepad is already rumbling. - // ---------------------------------------------------------------------------------------- - if (currentA && !lastA) { - if (!gamepad1.isRumbling()) // Check for possible overlap of rumbles. - gamepad1.rumbleBlips(3); - } - lastA = currentA; // remember the current button state for next time around the loop - - - // ---------------------------------------------------------------------------------------- - // Example 4. Rumble once when gamepad right trigger goes above the THRESHOLD. - // ---------------------------------------------------------------------------------------- - if (gamepad1.right_trigger > TRIGGER_THRESHOLD) { - if (!highLevel) { - gamepad1.rumble(0.9, 0, 200); // 200 mSec burst on left motor. - highLevel = true; // Hold off any more triggers - } - } else { - highLevel = false; // We can trigger again now. - } - - // Send the telemetry data to the Driver Station, and then pause to pace the program. - telemetry.update(); - sleep(10); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadTouchpad.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadTouchpad.java deleted file mode 100644 index 84d8cec9..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptGamepadTouchpad.java +++ /dev/null @@ -1,77 +0,0 @@ -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 org.firstinspires.ftc.robotcore.external.Telemetry; - -/* - * This OpMode illustrates using the touchpad feature found on some gamepads. - * - * The Sony PS4 gamepad can detect two distinct touches on the central touchpad. - * Other gamepads with different touchpads may provide mixed results. - * - * The touchpads are accessed through the standard gamepad1 and gamepad2 objects. - * Several new members were added to the Gamepad class in FTC SDK Rev 7 - * - * .touchpad_finger_1 returns true if at least one finger is detected. - * .touchpad_finger_1_x finger 1 X coordinate. Valid if touchpad_finger_1 is true - * .touchpad_finger_1_y finger 1 Y coordinate. Valid if touchpad_finger_1 is true - * - * .touchpad_finger_2 returns true if a second finger is detected - * .touchpad_finger_2_x finger 2 X coordinate. Valid if touchpad_finger_2 is true - * .touchpad_finger_2_y finger 2 Y coordinate. Valid if touchpad_finger_2 is true - * - * Finger touches are reported with an X and Y coordinate in following coordinate system. - * - * 1) X is the Horizontal axis, and Y is the vertical axis - * 2) The 0,0 origin is at the center of the touchpad. - * 3) 1.0, 1.0 is at the top right corner of the touchpad. - * 4) -1.0,-1.0 is at the bottom left corner of the touchpad. - * - * 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. - */ - -@Disabled -@TeleOp(name="Concept: Gamepad Touchpad", group ="Concept") -public class ConceptGamepadTouchpad extends LinearOpMode -{ - @Override - public void runOpMode() - { - telemetry.setDisplayFormat(Telemetry.DisplayFormat.MONOSPACE); - - telemetry.addData(">", "Press Start"); - telemetry.update(); - - waitForStart(); - - while (opModeIsActive()) - { - boolean finger = false; - - // Display finger 1 x & y position if finger detected - if(gamepad1.touchpad_finger_1) - { - finger = true; - telemetry.addLine(String.format("Finger 1: x=%5.2f y=%5.2f\n", gamepad1.touchpad_finger_1_x, gamepad1.touchpad_finger_1_y)); - } - - // Display finger 2 x & y position if finger detected - if(gamepad1.touchpad_finger_2) - { - finger = true; - telemetry.addLine(String.format("Finger 2: x=%5.2f y=%5.2f\n", gamepad1.touchpad_finger_2_x, gamepad1.touchpad_finger_2_y)); - } - - if(!finger) - { - telemetry.addLine("No fingers"); - } - - telemetry.update(); - sleep(10); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptLEDStick.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptLEDStick.java deleted file mode 100644 index 01729bbb..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptLEDStick.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.firstinspires.ftc.robotcontroller.external.samples; -/* - Copyright (c) 2021-24 Alan Smith - - 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 Alan Smith 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 FITNESSFOR 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. -*/ - -import android.graphics.Color; - -import com.qualcomm.hardware.sparkfun.SparkFunLEDStick; -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.Range; - -/* - * This OpMode illustrates how to use the SparkFun QWIIC LED Strip - * - * This is a simple way to add a strip of 10 LEDs to your robot where you can set the color of each - * LED or the whole strip. This allows for driver feedback or even just fun ways to show your team - * colors. - * - * Why? - * Because more LEDs == more fun!! - * - * This OpMode assumes that the QWIIC LED Stick is attached to an I2C interface named "back_leds" in the robot configuration. - * - * 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 - * - * You can buy this product here: https://www.sparkfun.com/products/18354 - * Don't forget to also buy this to make it easy to connect to your Control or Expansion Hub: - * https://www.sparkfun.com/products/25596 - */ -@TeleOp(name = "Concept: LED Stick", group = "Concept") -@Disabled -public class ConceptLEDStick extends OpMode { - private boolean wasUp; - private boolean wasDown; - private int brightness = 5; // this needs to be between 0 and 31 - private final static double END_GAME_TIME = 120 - 30; - - private SparkFunLEDStick ledStick; - - @Override - public void init() { - ledStick = hardwareMap.get(SparkFunLEDStick.class, "back_leds"); - ledStick.setBrightness(brightness); - ledStick.setColor(Color.GREEN); - } - - @Override - public void start() { - resetRuntime(); - } - - @Override - public void loop() { - telemetry.addLine("Hold the A button to turn blue"); - telemetry.addLine("Hold the B button to turn red"); - telemetry.addLine("Hold the left bumper to turn off"); - telemetry.addLine("Use DPAD Up/Down to change brightness"); - - if (getRuntime() > END_GAME_TIME) { - int[] ledColors = {Color.RED, Color.YELLOW, Color.RED, Color.YELLOW, Color.RED, - Color.YELLOW, Color.RED, Color.YELLOW, Color.RED, Color.YELLOW}; - ledStick.setColors(ledColors); - } else if (gamepad1.a) { - ledStick.setColor(Color.BLUE); - } else if (gamepad1.b) { - ledStick.setColor(Color.RED); - } else if (gamepad1.left_bumper) { - ledStick.turnAllOff(); - } else { - ledStick.setColor(Color.GREEN); - } - - /* - * Use DPAD up and down to change brightness - */ - int newBrightness = brightness; - if (gamepad1.dpad_up && !wasUp) { - newBrightness = brightness + 1; - } else if (gamepad1.dpad_down && !wasDown) { - newBrightness = brightness - 1; - } - if (newBrightness != brightness) { - brightness = Range.clip(newBrightness, 0, 31); - ledStick.setBrightness(brightness); - } - telemetry.addData("Brightness", brightness); - - wasDown = gamepad1.dpad_down; - wasUp = gamepad1.dpad_up; - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptMotorBulkRead.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptMotorBulkRead.java deleted file mode 100644 index 5439f780..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptMotorBulkRead.java +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright (c) 2019 Phil Malone. 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.lynx.LynxModule; -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.DcMotorEx; -import com.qualcomm.robotcore.util.ElapsedTime; - -import java.util.List; - -/* - * This OpMode illustrates how to use the Expansion Hub's Bulk-Read feature to speed up control cycle times. - * In this example there are 4 motors that need their encoder positions, and velocities read. - * The sample is written to work with one or two expansion hubs, with no assumption as to where the motors are located. - * - * Three scenarios are tested: - * Cache Mode = OFF This is the normal default, where no cache is used, and every read produces a discrete transaction with - * an expansion hub, which is the slowest approach, but guarentees that the value is as fresh (recent) as possible.. - * - * Cache Mode = AUTO This mode will attempt to minimize the number of discrete read commands, by performing bulk-reads - * and then returning values that have been cached. The cache is updated automatically whenever any specific encoder is re-read. - * This mode will always return new data, but it may perform more bulk-reads than absolutely required. - * Extra reads will be performed if multiple encoder/velocity reads are performed on the same encoder in one control cycle. - * This mode is a good compromise between the OFF and MANUAL modes. - * Note: If there are significant user-program delays between encoder reads, the cached value may not be fresh (recent). - * You can issue a clearBulkCache() call at any time force a fresh bulk-read on the next encoder read. - * - * Cache Mode = MANUAL This mode requires the user's code to determine the best time to clear the cached bulk-read data. - * Well organized code will reset the cache once at the beginning of the control cycle, and then immediately read and store all the encoder values. - * This approach will produce the shortest cycle times, but it does require the user to manually clear the cache. - * Since NO automatic Bulk-Reads are performed, neglecting to clear the bulk cache will result in the same values being returned - * each time an encoder read is performed. - * - * ------------------------------------- - * - * General tip to speed up your control cycles: - * - * No matter what method you use to read encoders and other inputs, you should try to - * avoid reading the same encoder input multiple times around a control loop. - * Under normal conditions, this will slow down the control loop. - * The preferred method is to read all the required inputs ONCE at the beginning of the loop, - * and save the values in variable that can be used by other parts of the control code. - * - * eg: if you are sending encoder positions to your telemetry display, putting a getCurrentPosition() - * call in the telemetry statement will force the code to go and get another copy which will take time. - * It's much better read the position into a variable once, and use that variable for control AND display. - * Reading saved variables takes no time at all. - * - * Once you put all your sensor reads at the beginning of the control cycle, it's very easy to use - * the bulk-read AUTO mode to streamline your cycle timing. - */ -@TeleOp (name = "Motor Bulk Reads", group = "Tests") -@Disabled -public class ConceptMotorBulkRead extends LinearOpMode { - - final int TEST_CYCLES = 500; // Number of control cycles to run to determine cycle times. - - private DcMotorEx m1, m2, m3, m4; // Motor Objects - private long e1, e2, e3, e4; // Encoder Values - private double v1, v2, v3, v4; // Velocities - - // Cycle Times - double t1 = 0; - double t2 = 0; - double t3 = 0; - - @Override - public void runOpMode() { - - int cycles; - - // Important Step 1: Make sure you use DcMotorEx when you instantiate your motors. - m1 = hardwareMap.get(DcMotorEx.class, "m1"); // Configure the robot to use these 4 motor names, - m2 = hardwareMap.get(DcMotorEx.class, "m2"); // or change these strings to match your existing Robot Configuration. - m3 = hardwareMap.get(DcMotorEx.class, "m3"); - m4 = hardwareMap.get(DcMotorEx.class, "m4"); - - // Important Step 2: Get access to a list of Expansion Hub Modules to enable changing caching methods. - List allHubs = hardwareMap.getAll(LynxModule.class); - - ElapsedTime timer = new ElapsedTime(); - - telemetry.addData(">", "Press START to start tests"); - telemetry.addData(">", "Test results will update for each access method."); - telemetry.update(); - waitForStart(); - - // -------------------------------------------------------------------------------------- - // Run control loop using legacy encoder reads - // In this mode, a single read is done for each encoder position, and a bulk read is done for each velocity read. - // This is the worst case scenario. - // This is the same as using LynxModule.BulkCachingMode.OFF - // -------------------------------------------------------------------------------------- - - displayCycleTimes("Test 1 of 3 (Wait for completion)"); - - timer.reset(); - cycles = 0; - while (opModeIsActive() && (cycles++ < TEST_CYCLES)) { - e1 = m1.getCurrentPosition(); - e2 = m2.getCurrentPosition(); - e3 = m3.getCurrentPosition(); - e4 = m4.getCurrentPosition(); - - v1 = m1.getVelocity(); - v2 = m2.getVelocity(); - v3 = m3.getVelocity(); - v4 = m4.getVelocity(); - - // Put Control loop action code here. - - } - // calculate the average cycle time. - t1 = timer.milliseconds() / cycles; - displayCycleTimes("Test 2 of 3 (Wait for completion)"); - - // -------------------------------------------------------------------------------------- - // Run test cycles using AUTO cache mode - // In this mode, only one bulk read is done per cycle, UNLESS you read a specific encoder/velocity item AGAIN in that cycle. - // -------------------------------------------------------------------------------------- - - // Important Step 3: Option A. Set all Expansion hubs to use the AUTO Bulk Caching mode - for (LynxModule module : allHubs) { - module.setBulkCachingMode(LynxModule.BulkCachingMode.AUTO); - } - - timer.reset(); - cycles = 0; - while (opModeIsActive() && (cycles++ < TEST_CYCLES)) { - e1 = m1.getCurrentPosition(); // Uses 1 bulk-read for all 4 encoder/velocity reads, - e2 = m2.getCurrentPosition(); // but don't do any `get` operations more than once per cycle. - e3 = m3.getCurrentPosition(); - e4 = m4.getCurrentPosition(); - - v1 = m1.getVelocity(); - v2 = m2.getVelocity(); - v3 = m3.getVelocity(); - v4 = m4.getVelocity(); - - // Put Control loop action code here. - - } - // calculate the average cycle time. - t2 = timer.milliseconds() / cycles; - displayCycleTimes("Test 3 of 3 (Wait for completion)"); - - // -------------------------------------------------------------------------------------- - // Run test cycles using MANUAL cache mode - // In this mode, only one block read is done each control cycle. - // This is the MOST efficient method, but it does require that the cache is cleared manually each control cycle. - // -------------------------------------------------------------------------------------- - - // Important Step 3: Option B. Set all Expansion hubs to use the MANUAL Bulk Caching mode - for (LynxModule module : allHubs) { - module.setBulkCachingMode(LynxModule.BulkCachingMode.MANUAL); - } - - timer.reset(); - cycles = 0; - while (opModeIsActive() && (cycles++ < TEST_CYCLES)) { - - // Important Step 4: If you are using MANUAL mode, you must clear the BulkCache once per control cycle - for (LynxModule module : allHubs) { - module.clearBulkCache(); - } - - e1 = m1.getCurrentPosition(); // Uses 1 bulk-read to obtain ALL the motor data - e2 = m2.getCurrentPosition(); // There is no penalty for doing more `get` operations in this cycle, - e3 = m3.getCurrentPosition(); // but they will return the same data. - e4 = m4.getCurrentPosition(); - - v1 = m1.getVelocity(); - v2 = m2.getVelocity(); - v3 = m3.getVelocity(); - v4 = m4.getVelocity(); - - // Put Control loop action code here. - - } - // calculate the average cycle time. - t3 = timer.milliseconds() / cycles; - displayCycleTimes("Complete"); - - // wait until op-mode is stopped by user, before clearing display. - while (opModeIsActive()) ; - } - - // Display three comparison times. - void displayCycleTimes(String status) { - telemetry.addData("Testing", status); - telemetry.addData("Cache = OFF", "%5.1f mS/cycle", t1); - telemetry.addData("Cache = AUTO", "%5.1f mS/cycle", t2); - telemetry.addData("Cache = MANUAL", "%5.1f mS/cycle", t3); - telemetry.update(); - } -} - diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java deleted file mode 100644 index 4a887bda..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptNullOp.java +++ /dev/null @@ -1,89 +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.OpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * Demonstrates an empty iterative OpMode - */ -@TeleOp(name = "Concept: NullOp", group = "Concept") -@Disabled -public class ConceptNullOp extends OpMode { - - private ElapsedTime runtime = new ElapsedTime(); - - /** - * This method will be called once, when the INIT button is pressed. - */ - @Override - public void init() { - telemetry.addData("Status", "Initialized"); - } - - /** - * This method will be called repeatedly during the period between when - * the INIT button is pressed and when the START button is pressed (or the - * OpMode is stopped). - */ - @Override - public void init_loop() { - } - - /** - * This method will be called once, when the START button is pressed. - */ - @Override - public void start() { - runtime.reset(); - } - - /** - * This method will be called repeatedly during the period between when - * the START button is pressed and when the OpMode is stopped. - */ - @Override - public void loop() { - telemetry.addData("Status", "Run Time: " + runtime.toString()); - } - - /** - * This method will be called once, when this OpMode is stopped. - *

- * Your ability to control hardware from this method will be limited. - */ - @Override - public void stop() { - - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java deleted file mode 100644 index 6e0be376..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRampMotorSpeed.java +++ /dev/null @@ -1,114 +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.DcMotor; - -/* - * This OpMode ramps a single motor speed up and down repeatedly until Stop is pressed. - * The code is structured as a LinearOpMode - * - * This code assumes a DC motor configured with the name "left_drive" as is found on a Robot. - * - * INCREMENT sets how much to increase/decrease the power each cycle - * CYCLE_MS sets the update period. - * - * 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 = "Concept: Ramp Motor Speed", group = "Concept") -@Disabled -public class ConceptRampMotorSpeed extends LinearOpMode { - - static final double INCREMENT = 0.01; // amount to ramp motor each CYCLE_MS cycle - static final int CYCLE_MS = 50; // period of each cycle - static final double MAX_FWD = 1.0; // Maximum FWD power applied to motor - static final double MAX_REV = -1.0; // Maximum REV power applied to motor - - // Define class members - DcMotor motor; - double power = 0; - boolean rampUp = true; - - - @Override - public void runOpMode() { - - // Connect to motor (Assume standard left wheel) - // Change the text in quotes to match any motor name on your robot. - motor = hardwareMap.get(DcMotor.class, "left_drive"); - - // Wait for the start button - telemetry.addData(">", "Press Start to run Motors." ); - telemetry.update(); - waitForStart(); - - // Ramp motor speeds till stop pressed. - while(opModeIsActive()) { - - // Ramp the motors, according to the rampUp variable. - if (rampUp) { - // Keep stepping up until we hit the max value. - power += INCREMENT ; - if (power >= MAX_FWD ) { - power = MAX_FWD; - rampUp = !rampUp; // Switch ramp direction - } - } - else { - // Keep stepping down until we hit the min value. - power -= INCREMENT ; - if (power <= MAX_REV ) { - power = MAX_REV; - rampUp = !rampUp; // Switch ramp direction - } - } - - // Display the current value - telemetry.addData("Motor Power", "%5.2f", power); - telemetry.addData(">", "Press Stop to end test." ); - telemetry.update(); - - // Set the motor to the new power and pause; - motor.setPower(power); - sleep(CYCLE_MS); - idle(); - } - - // Turn off motor and signal done; - motor.setPower(0); - telemetry.addData(">", "Done"); - telemetry.update(); - - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevLED.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevLED.java deleted file mode 100644 index 9c168d50..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevLED.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (c) 2024 Alan Smith - 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 Alan Smith 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 FITNESSFOR 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; - -/* - * This OpMode illustrates how to use the REV Digital Indicator - * - * This is a simple way to add the REV Digital Indicator which has a red and green LED. - * (and as you may remember, red + green = yellow so when they are both on you can get yellow) - * - * Why? - * You can use this to show information to the driver. For example, green might be that you can - * pick up more game elements and red would be that you already have the possession limit. - * - * This OpMode assumes that the REV Digital Indicator is setup as 2 Digital Channels named - * front_led_green and front_led_red. (the green should be the lower of the 2 channels it is plugged - * into and the red should be the higher) - * - * 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 - * - * You can buy this product here: https://www.revrobotics.com/rev-31-2010/ - */ -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.hardware.LED; - -@TeleOp(name = "Concept: RevLED", group = "Concept") -@Disabled -public class ConceptRevLED extends OpMode { - LED frontLED_red; - LED frontLED_green; - - @Override - public void init() { - frontLED_green = hardwareMap.get(LED.class, "front_led_green"); - frontLED_red = hardwareMap.get(LED.class, "front_led_red"); - } - - @Override - public void loop() { - if (gamepad1.a) { - frontLED_red.on(); - } else { - frontLED_red.off(); - } - if (gamepad1.b) { - frontLED_green.on(); - } else { - frontLED_green.off(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevSPARKMini.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevSPARKMini.java deleted file mode 100644 index 798d6893..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptRevSPARKMini.java +++ /dev/null @@ -1,111 +0,0 @@ -/* 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 demonstrates a POV Drive system, with commented-out code for a Tank Drive system, - * for a two wheeled robot using two REV SPARKminis. - * To use this example, connect two REV SPARKminis into servo ports on the Control Hub. On the - * robot configuration, use the drop down list under 'Servos' to select 'REV SPARKmini Controller' - * and name them 'left_drive' and 'right_drive'. - * - * 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="REV SPARKmini 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 robot configuration. - 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 backward when connected directly to the battery - leftDrive.setDirection(DcMotorSimple.Direction.FORWARD); - rightDrive.setDirection(DcMotorSimple.Direction.REVERSE); - - // Wait for the game to start (driver presses START) - 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/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java deleted file mode 100644 index 2b8ad332..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptScanServo.java +++ /dev/null @@ -1,115 +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.Servo; - -/* - * This OpMode scans a single servo back and forward until Stop is pressed. - * The code is structured as a LinearOpMode - * 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_hand" as is found on a Robot. - * - * 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. - * - * 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 = "Concept: Scan Servo", group = "Concept") -@Disabled -public class ConceptScanServo extends LinearOpMode { - - static final double INCREMENT = 0.01; // amount to slew servo each CYCLE_MS cycle - static final int CYCLE_MS = 50; // period of each cycle - static final double MAX_POS = 1.0; // Maximum rotational position - static final double MIN_POS = 0.0; // Minimum rotational position - - // Define class members - Servo servo; - double position = (MAX_POS - MIN_POS) / 2; // Start at halfway position - boolean rampUp = true; - - - @Override - public void runOpMode() { - - // Connect to servo (Assume Robot Left Hand) - // Change the text in quotes to match any servo name on your robot. - servo = hardwareMap.get(Servo.class, "left_hand"); - - // Wait for the start button - telemetry.addData(">", "Press Start to scan Servo." ); - telemetry.update(); - waitForStart(); - - - // Scan servo till stop pressed. - while(opModeIsActive()){ - - // slew the servo, according to the rampUp (direction) variable. - if (rampUp) { - // Keep stepping up until we hit the max value. - position += INCREMENT ; - if (position >= MAX_POS ) { - position = MAX_POS; - rampUp = !rampUp; // Switch ramp direction - } - } - else { - // Keep stepping down until we hit the min value. - position -= INCREMENT ; - if (position <= MIN_POS ) { - position = MIN_POS; - rampUp = !rampUp; // Switch ramp direction - } - } - - // Display the current value - telemetry.addData("Servo Position", "%5.2f", position); - telemetry.addData(">", "Press Stop to end test." ); - telemetry.update(); - - // Set the servo to the new position and pause; - servo.setPosition(position); - sleep(CYCLE_MS); - idle(); - } - - // Signal done; - telemetry.addData(">", "Done"); - telemetry.update(); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsASJava.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsASJava.java deleted file mode 100644 index 1ceaa17d..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsASJava.java +++ /dev/null @@ -1,133 +0,0 @@ -/* 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; - -/* - * This OpMode 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 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 - * - * 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 START) - 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/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsOnBotJava.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsOnBotJava.java deleted file mode 100644 index fbb7416c..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsOnBotJava.java +++ /dev/null @@ -1,120 +0,0 @@ -/* 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 OpMode 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/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsSKYSTONE.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsSKYSTONE.java deleted file mode 100644 index 983e434f..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptSoundsSKYSTONE.java +++ /dev/null @@ -1,122 +0,0 @@ -/* 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 android.content.Context; -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; - -/* - * This OpMode demonstrates how to play one of the several SKYSTONE/Star Wars sounds loaded into the SDK. - * It does this by creating a simple "chooser" controlled by the gamepad Up Down buttons. - * This code also prevents sounds from stacking up by setting a "playing" flag, which is cleared when the sound finishes playing. - * - * 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 - * - * Operation: - * Use the DPAD to change the selected sound, and the Right Bumper to play it. - */ - -@TeleOp(name="SKYSTONE Sounds", group="Concept") -@Disabled -public class ConceptSoundsSKYSTONE extends LinearOpMode { - - // List of available sound resources - String sounds[] = {"ss_alarm", "ss_bb8_down", "ss_bb8_up", "ss_darth_vader", "ss_fly_by", - "ss_mf_fail", "ss_laser", "ss_laser_burst", "ss_light_saber", "ss_light_saber_long", "ss_light_saber_short", - "ss_light_speed", "ss_mine", "ss_power_up", "ss_r2d2_up", "ss_roger_roger", "ss_siren", "ss_wookie" }; - boolean soundPlaying = false; - - @Override - public void runOpMode() { - - // Variables for choosing from the available sounds - int soundIndex = 0; - int soundID = -1; - boolean was_dpad_up = false; - boolean was_dpad_down = false; - - Context myApp = hardwareMap.appContext; - - // create a sound parameter that holds the desired player parameters. - SoundPlayer.PlaySoundParams params = new SoundPlayer.PlaySoundParams(); - params.loopControl = 0; - params.waitForNonLoopingSoundsToFinish = true; - - // In this sample, we will skip waiting for the user to press play, and start displaying sound choices right away - while (!isStopRequested()) { - - // Look for DPAD presses to change the selection - if (gamepad1.dpad_down && !was_dpad_down) { - // Go to next sound (with list wrap) and display it - soundIndex = (soundIndex + 1) % sounds.length; - } - - if (gamepad1.dpad_up && !was_dpad_up) { - // Go to previous sound (with list wrap) and display it - soundIndex = (soundIndex + sounds.length - 1) % sounds.length; - } - - // Look for trigger to see if we should play sound - // Only start a new sound if we are currently not playing one. - if (gamepad1.right_bumper && !soundPlaying) { - - // Determine Resource IDs for the sounds you want to play, and make sure it's valid. - if ((soundID = myApp.getResources().getIdentifier(sounds[soundIndex], "raw", myApp.getPackageName())) != 0){ - - // Signal that the sound is now playing. - soundPlaying = true; - - // Start playing, and also Create a callback that will clear the playing flag when the sound is complete. - SoundPlayer.getInstance().startPlaying(myApp, soundID, params, null, - new Runnable() { - public void run() { - soundPlaying = false; - }} ); - } - } - - // Remember the last state of the dpad to detect changes. - was_dpad_up = gamepad1.dpad_up; - was_dpad_down = gamepad1.dpad_down; - - // Display the current sound choice, and the playing status. - telemetry.addData("", "Use DPAD up/down to choose sound."); - telemetry.addData("", "Press Right Bumper to play sound."); - telemetry.addData("", ""); - telemetry.addData("Sound >", sounds[soundIndex]); - telemetry.addData("Status >", soundPlaying ? "Playing" : "Stopped"); - telemetry.update(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java deleted file mode 100644 index f2c60970..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptTelemetry.java +++ /dev/null @@ -1,177 +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.VoltageSensor; -import com.qualcomm.robotcore.util.ElapsedTime; -import org.firstinspires.ftc.robotcore.external.Func; -import org.firstinspires.ftc.robotcore.external.Telemetry; - -/* - * This OpMode illustrates various ways in which telemetry can be - * transmitted from the robot controller to the driver station. The sample illustrates - * numeric and text data, formatted output, and optimized evaluation of expensive-to-acquire - * information. The telemetry log is illustrated by scrolling a poem - * to the driver station. - * - * Also see the Telemetry javadocs. - */ -@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 */ - int poemLine = 0; - - /** Keeps track of how long it's been since we last emitted a line of poetry */ - ElapsedTime poemElapsed = new ElapsedTime(); - - static final String[] poem = new String[] { - - "Mary had a little lamb,", - "His fleece was white as snow,", - "And everywhere that Mary went,", - "The lamb was sure to go.", - "", - "He followed her to school one day,", - "Which was against the rule,", - "It made the children laugh and play", - "To see a lamb at school.", - "", - "And so the teacher turned it out,", - "But still it lingered near,", - "And waited patiently about,", - "Till Mary did appear.", - "", - "\"Why does the lamb love Mary so?\"", - "The eager children cry.", - "\"Why, Mary loves the lamb, you know,\"", - "The teacher did reply.", - "", - "" - }; - - @Override public void runOpMode() { - - /* we keep track of how long it's been since the OpMode was started, just - * to have some interesting data to show */ - ElapsedTime opmodeRunTime = new ElapsedTime(); - - // We show the log in oldest-to-newest order, as that's better for poetry - telemetry.log().setDisplayOrder(Telemetry.Log.DisplayOrder.OLDEST_FIRST); - // We can control the number of lines shown in the log - telemetry.log().setCapacity(6); - // The interval between lines of poetry, in seconds - double sPoemInterval = 0.6; - - /* - * Wait until we've been given the ok to go. For something to do, we emit the - * elapsed time as we sit here and wait. If we didn't want to do anything while - * we waited, we would just call waitForStart(). - */ - while (!isStarted()) { - telemetry.addData("time", "%.1f seconds", opmodeRunTime.seconds()); - telemetry.update(); - idle(); - } - - // Ok, we've been given the ok to go - - /* - * As an illustration, the first line on our telemetry display will display the battery voltage. - * The idea here is that it's expensive to compute the voltage (at least for purposes of illustration) - * so you don't want to do it unless the data is _actually_ going to make it to the - * driver station (recall that telemetry transmission is throttled to reduce bandwidth use. - * Note that getBatteryVoltage() below returns 'Infinity' if there's no voltage sensor attached. - * - * @see Telemetry#getMsTransmissionInterval() - */ - telemetry.addData("voltage", "%.1f volts", new Func() { - @Override public Double value() { - return getBatteryVoltage(); - } - }); - - // Reset to keep some timing stats for the post-'start' part of the OpMode - opmodeRunTime.reset(); - int loopCount = 1; - - // Go go gadget robot! - while (opModeIsActive()) { - - // Emit poetry if it's been a while - if (poemElapsed.seconds() > sPoemInterval) { - emitPoemLine(); - } - - // As an illustration, show some loop timing information - telemetry.addData("loop count", loopCount); - telemetry.addData("ms/loop", "%.3f ms", opmodeRunTime.milliseconds() / loopCount); - - // Show joystick information as some other illustrative data - telemetry.addLine("left joystick | ") - .addData("x", gamepad1.left_stick_x) - .addData("y", gamepad1.left_stick_y); - telemetry.addLine("right joystick | ") - .addData("x", gamepad1.right_stick_x) - .addData("y", gamepad1.right_stick_y); - - /* - * Transmit the telemetry to the driver station, subject to throttling. - * See the documentation for Telemetry.getMsTransmissionInterval() for more information. - */ - telemetry.update(); - - // Update loop info - loopCount++; - } - } - - // emits a line of poetry to the telemetry log - void emitPoemLine() { - telemetry.log().add(poem[poemLine]); - poemLine = (poemLine+1) % poem.length; - poemElapsed.reset(); - } - - // Computes the current battery voltage - double getBatteryVoltage() { - double result = Double.POSITIVE_INFINITY; - for (VoltageSensor sensor : hardwareMap.voltageSensor) { - double voltage = sensor.getVoltage(); - if (voltage > 0) { - result = Math.min(result, voltage); - } - } - return result; - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorLocator.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorLocator.java deleted file mode 100644 index 987694db..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorLocator.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2024 Phil Malone - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import android.util.Size; - -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.SortOrder; - -import org.firstinspires.ftc.robotcore.external.Telemetry; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.opencv.ColorBlobLocatorProcessor; -import org.firstinspires.ftc.vision.opencv.ColorRange; -import org.firstinspires.ftc.vision.opencv.ImageRegion; -import org.opencv.core.RotatedRect; - -import java.util.List; - -/* - * This OpMode illustrates how to use a video source (camera) to locate specifically colored regions - * - * Unlike a "color sensor" which determines the color of an object in the field of view, this "color locator" - * will search the Region Of Interest (ROI) in a camera image, and find any "blobs" of color that match the requested color range. - * These blobs can be further filtered and sorted to find the one most likely to be the item the user is looking for. - * - * To perform this function, a VisionPortal runs a ColorBlobLocatorProcessor process. - * The ColorBlobLocatorProcessor process is created first, and then the VisionPortal is built to use this process. - * The ColorBlobLocatorProcessor analyses the ROI and locates pixels that match the ColorRange to form a "mask". - * The matching pixels are then collected into contiguous "blobs" of pixels. The outer boundaries of these blobs are called its "contour". - * For each blob, the process then creates the smallest possible rectangle "boxFit" that will fully encase the contour. - * The user can then call getBlobs() to retrieve the list of Blobs, where each Blob contains the contour and the boxFit data. - * Note: The default sort order for Blobs is ContourArea, in descending order, so the biggest contours are listed first. - * - * To aid the user, a colored boxFit rectangle is drawn on the camera preview to show the location of each Blob - * The original Blob contour can also be added to the preview. This is helpful when configuring the ColorBlobLocatorProcessor parameters. - * - * 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 - */ - -@Disabled -@TeleOp(name = "Concept: Vision Color-Locator", group = "Concept") -public class ConceptVisionColorLocator extends LinearOpMode -{ - @Override - public void runOpMode() - { - /* Build a "Color Locator" vision processor based on the ColorBlobLocatorProcessor class. - * - Specify the color range you are looking for. You can use a predefined color, or create you own color range - * .setTargetColorRange(ColorRange.BLUE) // use a predefined color match - * Available predefined colors are: RED, BLUE YELLOW GREEN - * .setTargetColorRange(new ColorRange(ColorSpace.YCrCb, // or define your own color match - * new Scalar( 32, 176, 0), - * new Scalar(255, 255, 132))) - * - * - Focus the color locator by defining a RegionOfInterest (ROI) which you want to search. - * This can be the entire frame, or a sub-region defined using: - * 1) standard image coordinates or 2) a normalized +/- 1.0 coordinate system. - * Use one form of the ImageRegion class to define the ROI. - * ImageRegion.entireFrame() - * ImageRegion.asImageCoordinates(50, 50, 150, 150) 100x100 pixel square near the upper left corner - * ImageRegion.asUnityCenterCoordinates(-0.5, 0.5, 0.5, -0.5) 50% width/height square centered on screen - * - * - Define which contours are included. - * You can get ALL the contours, or you can skip any contours that are completely inside another contour. - * .setContourMode(ColorBlobLocatorProcessor.ContourMode.ALL_FLATTENED_HIERARCHY) // return all contours - * .setContourMode(ColorBlobLocatorProcessor.ContourMode.EXTERNAL_ONLY) // exclude contours inside other contours - * note: EXTERNAL_ONLY helps to avoid bright reflection spots from breaking up areas of solid color. - * - * - turn the display of contours ON or OFF. Turning this on helps debugging but takes up valuable CPU time. - * .setDrawContours(true) - * - * - include any pre-processing of the image or mask before looking for Blobs. - * There are some extra processing you can include to improve the formation of blobs. Using these features requires - * an understanding of how they may effect the final blobs. The "pixels" argument sets the NxN kernel size. - * .setBlurSize(int pixels) Blurring an image helps to provide a smooth color transition between objects, and smoother contours. - * The higher the number of pixels, the more blurred the image becomes. - * Note: Even "pixels" values will be incremented to satisfy the "odd number" requirement. - * Blurring too much may hide smaller features. A "pixels" size of 5 is good for a 320x240 image. - * .setErodeSize(int pixels) Erosion removes floating pixels and thin lines so that only substantive objects remain. - * Erosion can grow holes inside regions, and also shrink objects. - * "pixels" in the range of 2-4 are suitable for low res images. - * .setDilateSize(int pixels) Dilation makes objects more visible by filling in small holes, making lines appear thicker, - * and making filled shapes appear larger. Dilation is useful for joining broken parts of an - * object, such as when removing noise from an image. - * "pixels" in the range of 2-4 are suitable for low res images. - */ - ColorBlobLocatorProcessor colorLocator = new ColorBlobLocatorProcessor.Builder() - .setTargetColorRange(ColorRange.BLUE) // use a predefined color match - .setContourMode(ColorBlobLocatorProcessor.ContourMode.EXTERNAL_ONLY) // exclude blobs inside blobs - .setRoi(ImageRegion.asUnityCenterCoordinates(-0.5, 0.5, 0.5, -0.5)) // search central 1/4 of camera view - .setDrawContours(true) // Show contours on the Stream Preview - .setBlurSize(5) // Smooth the transitions between different colors in image - .build(); - - /* - * Build a vision portal to run the Color Locator process. - * - * - Add the colorLocator process created above. - * - Set the desired video resolution. - * Since a high resolution will not improve this process, choose a lower resolution that is - * supported by your camera. This will improve overall performance and reduce latency. - * - Choose your video source. This may be - * .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) ..... for a webcam - * or - * .setCamera(BuiltinCameraDirection.BACK) ... for a Phone Camera - */ - VisionPortal portal = new VisionPortal.Builder() - .addProcessor(colorLocator) - .setCameraResolution(new Size(320, 240)) - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .build(); - - telemetry.setMsTransmissionInterval(50); // Speed up telemetry updates, Just use for debugging. - telemetry.setDisplayFormat(Telemetry.DisplayFormat.MONOSPACE); - - // WARNING: To be able to view the stream preview on the Driver Station, this code runs in INIT mode. - while (opModeIsActive() || opModeInInit()) - { - telemetry.addData("preview on/off", "... Camera Stream\n"); - - // Read the current list - List blobs = colorLocator.getBlobs(); - - /* - * The list of Blobs can be filtered to remove unwanted Blobs. - * Note: All contours will be still displayed on the Stream Preview, but only those that satisfy the filter - * conditions will remain in the current list of "blobs". Multiple filters may be used. - * - * Use any of the following filters. - * - * ColorBlobLocatorProcessor.Util.filterByArea(minArea, maxArea, blobs); - * A Blob's area is the number of pixels contained within the Contour. Filter out any that are too big or small. - * Start with a large range and then refine the range based on the likely size of the desired object in the viewfinder. - * - * ColorBlobLocatorProcessor.Util.filterByDensity(minDensity, maxDensity, blobs); - * A blob's density is an indication of how "full" the contour is. - * If you put a rubber band around the contour you would get the "Convex Hull" of the contour. - * The density is the ratio of Contour-area to Convex Hull-area. - * - * ColorBlobLocatorProcessor.Util.filterByAspectRatio(minAspect, maxAspect, blobs); - * A blob's Aspect ratio is the ratio of boxFit long side to short side. - * A perfect Square has an aspect ratio of 1. All others are > 1 - */ - ColorBlobLocatorProcessor.Util.filterByArea(50, 20000, blobs); // filter out very small blobs. - - /* - * The list of Blobs can be sorted using the same Blob attributes as listed above. - * No more than one sort call should be made. Sorting can use ascending or descending order. - * ColorBlobLocatorProcessor.Util.sortByArea(SortOrder.DESCENDING, blobs); // Default - * ColorBlobLocatorProcessor.Util.sortByDensity(SortOrder.DESCENDING, blobs); - * ColorBlobLocatorProcessor.Util.sortByAspectRatio(SortOrder.DESCENDING, blobs); - */ - - telemetry.addLine(" Area Density Aspect Center"); - - // Display the size (area) and center location for each Blob. - for(ColorBlobLocatorProcessor.Blob b : blobs) - { - RotatedRect boxFit = b.getBoxFit(); - telemetry.addLine(String.format("%5d %4.2f %5.2f (%3d,%3d)", - b.getContourArea(), b.getDensity(), b.getAspectRatio(), (int) boxFit.center.x, (int) boxFit.center.y)); - } - - telemetry.update(); - sleep(50); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorSensor.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorSensor.java deleted file mode 100644 index 6be2bc4e..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/ConceptVisionColorSensor.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2024 Phil Malone - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import android.graphics.Color; -import android.util.Size; - -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.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.opencv.ImageRegion; -import org.firstinspires.ftc.vision.opencv.PredominantColorProcessor; - -/* - * This OpMode illustrates how to use a video source (camera) as a color sensor - * - * A "color sensor" will typically determine the color of the object that it is pointed at. - * - * This sample performs the same function, except it uses a video camera to inspect an object or scene. - * The user may choose to inspect all, or just a Region of Interest (ROI), of the active camera view. - * The user must also provide a list of "acceptable colors" (Swatches) from which the closest matching color will be selected. - * - * To perform this function, a VisionPortal runs a PredominantColorProcessor process. - * The PredominantColorProcessor process is created first, and then the VisionPortal is built to use this process. - * The PredominantColorProcessor analyses the ROI and splits the colored pixels into several color-clusters. - * The largest of these clusters is then considered to be the "Predominant Color" - * The process then matches the Predominant Color with the closest Swatch and returns that match. - * - * To aid the user, a colored rectangle is drawn on the camera preview to show the RegionOfInterest, - * The Predominant Color is used to paint the rectangle border, so the user can verify that the color is reasonable. - * - * 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 - */ - -@Disabled -@TeleOp(name = "Concept: Vision Color-Sensor", group = "Concept") -public class ConceptVisionColorSensor extends LinearOpMode -{ - @Override - public void runOpMode() - { - /* Build a "Color Sensor" vision processor based on the PredominantColorProcessor class. - * - * - Focus the color sensor by defining a RegionOfInterest (ROI) which you want to inspect. - * This can be the entire frame, or a sub-region defined using: - * 1) standard image coordinates or 2) a normalized +/- 1.0 coordinate system. - * Use one form of the ImageRegion class to define the ROI. - * ImageRegion.entireFrame() - * ImageRegion.asImageCoordinates(50, 50, 150, 150) 100x100 pixel square near the upper left corner - * ImageRegion.asUnityCenterCoordinates(-0.1, 0.1, 0.1, -0.1) 10% width/height square centered on screen - * - * - Set the list of "acceptable" color swatches (matches). - * Only colors that you assign here will be returned. - * If you know the sensor will be pointing to one of a few specific colors, enter them here. - * Or, if the sensor may be pointed randomly, provide some additional colors that may match the surrounding. - * Possible choices are: - * RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, PURPLE, MAGENTA, BLACK, WHITE; - * - * Note that in the example shown below, only some of the available colors are included. - * This will force any other colored region into one of these colors. - * eg: Green may be reported as YELLOW, as this may be the "closest" match. - */ - PredominantColorProcessor colorSensor = new PredominantColorProcessor.Builder() - .setRoi(ImageRegion.asUnityCenterCoordinates(-0.1, 0.1, 0.1, -0.1)) - .setSwatches( - PredominantColorProcessor.Swatch.RED, - PredominantColorProcessor.Swatch.BLUE, - PredominantColorProcessor.Swatch.YELLOW, - PredominantColorProcessor.Swatch.BLACK, - PredominantColorProcessor.Swatch.WHITE) - .build(); - - /* - * Build a vision portal to run the Color Sensor process. - * - * - Add the colorSensor process created above. - * - Set the desired video resolution. - * Since a high resolution will not improve this process, choose a lower resolution that is - * supported by your camera. This will improve overall performance and reduce latency. - * - Choose your video source. This may be - * .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) ..... for a webcam - * or - * .setCamera(BuiltinCameraDirection.BACK) ... for a Phone Camera - */ - VisionPortal portal = new VisionPortal.Builder() - .addProcessor(colorSensor) - .setCameraResolution(new Size(320, 240)) - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .build(); - - telemetry.setMsTransmissionInterval(50); // Speed up telemetry updates, Just use for debugging. - - // WARNING: To be able to view the stream preview on the Driver Station, this code runs in INIT mode. - while (opModeIsActive() || opModeInInit()) - { - telemetry.addData("DS preview on/off", "3 dots, Camera Stream\n"); - - // Request the most recent color analysis. - // This will return the closest matching colorSwatch and the predominant RGB color. - // Note: to take actions based on the detected color, simply use the colorSwatch in a comparison or switch. - // eg: - // if (result.closestSwatch == PredominantColorProcessor.Swatch.RED) {... some code ...} - PredominantColorProcessor.Result result = colorSensor.getAnalysis(); - - // Display the Color Sensor result. - telemetry.addData("Best Match:", result.closestSwatch); - telemetry.addLine(String.format("R %3d, G %3d, B %3d", Color.red(result.rgb), Color.green(result.rgb), Color.blue(result.rgb))); - telemetry.update(); - - sleep(20); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByEncoder_Linear.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByEncoder_Linear.java deleted file mode 100644 index 63293d0c..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByEncoder_Linear.java +++ /dev/null @@ -1,187 +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.Autonomous; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * This OpMode illustrates the concept of driving a path based on encoder counts. - * The code is structured as a LinearOpMode - * - * The code REQUIRES that you DO have encoders on the wheels, - * otherwise you would use: RobotAutoDriveByTime; - * - * This code ALSO requires that the drive Motors have been configured such that a positive - * power command moves them forward, and causes the encoders to count UP. - * - * The desired path in this example is: - * - Drive forward for 48 inches - * - Spin right for 12 Inches - * - Drive Backward for 24 inches - * - Stop and close the claw. - * - * The code is written using a method called: encoderDrive(speed, leftInches, rightInches, timeoutS) - * that performs the actual movement. - * This method assumes that each movement is relative to the last stopping place. - * There are other ways to perform encoder based moves, but this method is probably the simplest. - * This code uses the RUN_TO_POSITION mode to enable the Motor controllers to generate the run profile - * - * 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="Robot: Auto Drive By Encoder", group="Robot") -@Disabled -public class RobotAutoDriveByEncoder_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - - private ElapsedTime runtime = new ElapsedTime(); - - // Calculate the COUNTS_PER_INCH for your specific drive train. - // Go to your motor vendor website to determine your motor's COUNTS_PER_MOTOR_REV - // For external drive gearing, set DRIVE_GEAR_REDUCTION as needed. - // For example, use a value of 2.0 for a 12-tooth spur gear driving a 24-tooth spur gear. - // This is gearing DOWN for less speed and more torque. - // For gearing UP, use a gear ratio less than 1.0. Note this will affect the direction of wheel rotation. - static final double COUNTS_PER_MOTOR_REV = 1440 ; // eg: TETRIX Motor Encoder - static final double DRIVE_GEAR_REDUCTION = 1.0 ; // No External Gearing. - static final double WHEEL_DIAMETER_INCHES = 4.0 ; // For figuring circumference - static final double COUNTS_PER_INCH = (COUNTS_PER_MOTOR_REV * DRIVE_GEAR_REDUCTION) / - (WHEEL_DIAMETER_INCHES * 3.1415); - static final double DRIVE_SPEED = 0.6; - static final double TURN_SPEED = 0.5; - - @Override - public void runOpMode() { - - // Initialize the drive system variables. - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - leftDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); - rightDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); - - leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Send telemetry message to indicate successful Encoder reset - telemetry.addData("Starting at", "%7d :%7d", - leftDrive.getCurrentPosition(), - rightDrive.getCurrentPosition()); - telemetry.update(); - - // Wait for the game to start (driver presses START) - waitForStart(); - - // Step through each leg of the path, - // Note: Reverse movement is obtained by setting a negative distance (not speed) - encoderDrive(DRIVE_SPEED, 48, 48, 5.0); // S1: Forward 47 Inches with 5 Sec timeout - encoderDrive(TURN_SPEED, 12, -12, 4.0); // S2: Turn Right 12 Inches with 4 Sec timeout - encoderDrive(DRIVE_SPEED, -24, -24, 4.0); // S3: Reverse 24 Inches with 4 Sec timeout - - telemetry.addData("Path", "Complete"); - telemetry.update(); - sleep(1000); // pause to display final telemetry message. - } - - /* - * Method to perform a relative move, based on encoder counts. - * Encoders are not reset as the move is based on the current position. - * Move will stop if any of three conditions occur: - * 1) Move gets to the desired position - * 2) Move runs out of time - * 3) Driver stops the OpMode running. - */ - public void encoderDrive(double speed, - double leftInches, double rightInches, - double timeoutS) { - int newLeftTarget; - int newRightTarget; - - // Ensure that the OpMode is still active - if (opModeIsActive()) { - - // Determine new target position, and pass to motor controller - newLeftTarget = leftDrive.getCurrentPosition() + (int)(leftInches * COUNTS_PER_INCH); - newRightTarget = rightDrive.getCurrentPosition() + (int)(rightInches * COUNTS_PER_INCH); - leftDrive.setTargetPosition(newLeftTarget); - rightDrive.setTargetPosition(newRightTarget); - - // Turn On RUN_TO_POSITION - leftDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION); - rightDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION); - - // reset the timeout time and start motion. - runtime.reset(); - leftDrive.setPower(Math.abs(speed)); - rightDrive.setPower(Math.abs(speed)); - - // keep looping while we are still active, and there is time left, and both motors are running. - // Note: We use (isBusy() && isBusy()) in the loop test, which means that when EITHER motor hits - // its target position, the motion will stop. This is "safer" in the event that the robot will - // always end the motion as soon as possible. - // However, if you require that BOTH motors have finished their moves before the robot continues - // onto the next step, use (isBusy() || isBusy()) in the loop test. - while (opModeIsActive() && - (runtime.seconds() < timeoutS) && - (leftDrive.isBusy() && rightDrive.isBusy())) { - - // Display it for the driver. - telemetry.addData("Running to", " %7d :%7d", newLeftTarget, newRightTarget); - telemetry.addData("Currently at", " at %7d :%7d", - leftDrive.getCurrentPosition(), rightDrive.getCurrentPosition()); - telemetry.update(); - } - - // Stop all motion; - leftDrive.setPower(0); - rightDrive.setPower(0); - - // Turn off RUN_TO_POSITION - leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - sleep(250); // optional pause after each move. - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByGyro_Linear.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByGyro_Linear.java deleted file mode 100644 index ab709344..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByGyro_Linear.java +++ /dev/null @@ -1,429 +0,0 @@ -/* Copyright (c) 2022 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.RevHubOrientationOnRobot; -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.DcMotor; -import com.qualcomm.robotcore.hardware.IMU; -import com.qualcomm.robotcore.util.ElapsedTime; -import com.qualcomm.robotcore.util.Range; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; - -/* - * This OpMode illustrates the concept of driving an autonomous path based on Gyro (IMU) heading and encoder counts. - * The code is structured as a LinearOpMode - * - * The path to be followed by the robot is built from a series of drive, turn or pause steps. - * Each step on the path is defined by a single function call, and these can be strung together in any order. - * - * The code REQUIRES that you have encoders on the drive motors, otherwise you should use: RobotAutoDriveByTime; - * - * This code uses the Universal IMU interface so it will work with either the BNO055, or BHI260 IMU. - * To run as written, the Control/Expansion hub should be mounted horizontally on a flat part of the robot chassis. - * The REV Logo should be facing UP, and the USB port should be facing forward. - * If this is not the configuration of your REV Control Hub, then the code should be modified to reflect the correct orientation. - * - * This sample requires that the drive Motors have been configured with names : left_drive and right_drive. - * It also requires that a positive power command moves both motors forward, and causes the encoders to count UP. - * So please verify that both of your motors move the robot forward on the first move. If not, make the required correction. - * See the beginning of runOpMode() to set the FORWARD/REVERSE option for each motor. - * - * This code uses RUN_TO_POSITION mode for driving straight, and RUN_USING_ENCODER mode for turning and holding. - * Note: This code implements the requirement of calling setTargetPosition() at least once before switching to RUN_TO_POSITION mode. - * - * Notes: - * - * All angles are referenced to the coordinate-frame that is set whenever resetHeading() is called. - * In this sample, the heading is reset when the Start button is touched on the Driver Station. - * Note: It would be possible to reset the heading after each move, but this would accumulate steering errors. - * - * The angle of movement/rotation is assumed to be a standardized rotation around the robot Z axis, - * which means that a Positive rotation is Counter Clockwise, looking down on the field. - * This is consistent with the FTC field coordinate conventions set out in the document: - * https://ftc-docs.firstinspires.org/field-coordinate-system - * - * Control Approach. - * - * To reach, or maintain a required heading, this code implements a basic Proportional Controller where: - * - * Steering power = Heading Error * Proportional Gain. - * - * "Heading Error" is calculated by taking the difference between the desired heading and the actual heading, - * and then "normalizing" it by converting it to a value in the +/- 180 degree range. - * - * "Proportional Gain" is a constant that YOU choose to set the "strength" of the steering response. - * - * Use Android Studio to Copy this Class, and Paste it into your "TeamCode" folder with a new name. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list - */ - -@Autonomous(name="Robot: Auto Drive By Gyro", group="Robot") -@Disabled -public class RobotAutoDriveByGyro_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - private IMU imu = null; // Control/Expansion Hub IMU - - private double headingError = 0; - - // These variable are declared here (as class members) so they can be updated in various methods, - // but still be displayed by sendTelemetry() - private double targetHeading = 0; - private double driveSpeed = 0; - private double turnSpeed = 0; - private double leftSpeed = 0; - private double rightSpeed = 0; - private int leftTarget = 0; - private int rightTarget = 0; - - // Calculate the COUNTS_PER_INCH for your specific drive train. - // Go to your motor vendor website to determine your motor's COUNTS_PER_MOTOR_REV - // For external drive gearing, set DRIVE_GEAR_REDUCTION as needed. - // For example, use a value of 2.0 for a 12-tooth spur gear driving a 24-tooth spur gear. - // This is gearing DOWN for less speed and more torque. - // For gearing UP, use a gear ratio less than 1.0. Note this will affect the direction of wheel rotation. - static final double COUNTS_PER_MOTOR_REV = 537.7 ; // eg: GoBILDA 312 RPM Yellow Jacket - static final double DRIVE_GEAR_REDUCTION = 1.0 ; // No External Gearing. - static final double WHEEL_DIAMETER_INCHES = 4.0 ; // For figuring circumference - static final double COUNTS_PER_INCH = (COUNTS_PER_MOTOR_REV * DRIVE_GEAR_REDUCTION) / - (WHEEL_DIAMETER_INCHES * 3.1415); - - // These constants define the desired driving/control characteristics - // They can/should be tweaked to suit the specific robot drive train. - static final double DRIVE_SPEED = 0.4; // Max driving speed for better distance accuracy. - static final double TURN_SPEED = 0.2; // Max turn speed to limit turn rate. - static final double HEADING_THRESHOLD = 1.0 ; // How close must the heading get to the target before moving to next step. - // Requiring more accuracy (a smaller number) will often make the turn take longer to get into the final position. - // Define the Proportional control coefficient (or GAIN) for "heading control". - // We define one value when Turning (larger errors), and the other is used when Driving straight (smaller errors). - // Increase these numbers if the heading does not correct strongly enough (eg: a heavy robot or using tracks) - // Decrease these numbers if the heading does not settle on the correct value (eg: very agile robot with omni wheels) - static final double P_TURN_GAIN = 0.02; // Larger is more responsive, but also less stable. - static final double P_DRIVE_GAIN = 0.03; // Larger is more responsive, but also less stable. - - - @Override - public void runOpMode() { - - // Initialize the drive system variables. - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - /* The next two lines define Hub orientation. - * The Default Orientation (shown) is when a hub is mounted horizontally with the printed logo pointing UP and the USB port pointing FORWARD. - * - * To Do: EDIT these two lines to match YOUR mounting configuration. - */ - RevHubOrientationOnRobot.LogoFacingDirection logoDirection = RevHubOrientationOnRobot.LogoFacingDirection.UP; - RevHubOrientationOnRobot.UsbFacingDirection usbDirection = RevHubOrientationOnRobot.UsbFacingDirection.FORWARD; - RevHubOrientationOnRobot orientationOnRobot = new RevHubOrientationOnRobot(logoDirection, usbDirection); - - // Now initialize the IMU with this mounting orientation - // This sample expects the IMU to be in a REV Hub and named "imu". - imu = hardwareMap.get(IMU.class, "imu"); - imu.initialize(new IMU.Parameters(orientationOnRobot)); - - // Ensure the robot is stationary. Reset the encoders and set the motors to BRAKE mode - leftDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); - rightDrive.setMode(DcMotor.RunMode.STOP_AND_RESET_ENCODER); - leftDrive.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE); - rightDrive.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE); - - // Wait for the game to start (Display Gyro value while waiting) - while (opModeInInit()) { - telemetry.addData(">", "Robot Heading = %4.0f", getHeading()); - telemetry.update(); - } - - // Set the encoders for closed loop speed control, and reset the heading. - leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - imu.resetYaw(); - - // Step through each leg of the path, - // Notes: Reverse movement is obtained by setting a negative distance (not speed) - // holdHeading() is used after turns to let the heading stabilize - // Add a sleep(2000) after any step to keep the telemetry data visible for review - - driveStraight(DRIVE_SPEED, 24.0, 0.0); // Drive Forward 24" - turnToHeading( TURN_SPEED, -45.0); // Turn CW to -45 Degrees - holdHeading( TURN_SPEED, -45.0, 0.5); // Hold -45 Deg heading for a 1/2 second - - driveStraight(DRIVE_SPEED, 17.0, -45.0); // Drive Forward 17" at -45 degrees (12"x and 12"y) - turnToHeading( TURN_SPEED, 45.0); // Turn CCW to 45 Degrees - holdHeading( TURN_SPEED, 45.0, 0.5); // Hold 45 Deg heading for a 1/2 second - - driveStraight(DRIVE_SPEED, 17.0, 45.0); // Drive Forward 17" at 45 degrees (-12"x and 12"y) - turnToHeading( TURN_SPEED, 0.0); // Turn CW to 0 Degrees - holdHeading( TURN_SPEED, 0.0, 1.0); // Hold 0 Deg heading for 1 second - - driveStraight(DRIVE_SPEED,-48.0, 0.0); // Drive in Reverse 48" (should return to approx. staring position) - - telemetry.addData("Path", "Complete"); - telemetry.update(); - sleep(1000); // Pause to display last telemetry message. - } - - /* - * ==================================================================================================== - * Driving "Helper" functions are below this line. - * These provide the high and low level methods that handle driving straight and turning. - * ==================================================================================================== - */ - - // ********** HIGH Level driving functions. ******************** - - /** - * Drive in a straight line, on a fixed compass heading (angle), based on encoder counts. - * Move will stop if either of these conditions occur: - * 1) Move gets to the desired position - * 2) Driver stops the OpMode running. - * - * @param maxDriveSpeed MAX Speed for forward/rev motion (range 0 to +1.0) . - * @param distance Distance (in inches) to move from current position. Negative distance means move backward. - * @param heading Absolute Heading Angle (in Degrees) relative to last gyro reset. - * 0 = fwd. +ve is CCW from fwd. -ve is CW from forward. - * If a relative angle is required, add/subtract from the current robotHeading. - */ - public void driveStraight(double maxDriveSpeed, - double distance, - double heading) { - - // Ensure that the OpMode is still active - if (opModeIsActive()) { - - // Determine new target position, and pass to motor controller - int moveCounts = (int)(distance * COUNTS_PER_INCH); - leftTarget = leftDrive.getCurrentPosition() + moveCounts; - rightTarget = rightDrive.getCurrentPosition() + moveCounts; - - // Set Target FIRST, then turn on RUN_TO_POSITION - leftDrive.setTargetPosition(leftTarget); - rightDrive.setTargetPosition(rightTarget); - - leftDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION); - rightDrive.setMode(DcMotor.RunMode.RUN_TO_POSITION); - - // Set the required driving speed (must be positive for RUN_TO_POSITION) - // Start driving straight, and then enter the control loop - maxDriveSpeed = Math.abs(maxDriveSpeed); - moveRobot(maxDriveSpeed, 0); - - // keep looping while we are still active, and BOTH motors are running. - while (opModeIsActive() && - (leftDrive.isBusy() && rightDrive.isBusy())) { - - // Determine required steering to keep on heading - turnSpeed = getSteeringCorrection(heading, P_DRIVE_GAIN); - - // if driving in reverse, the motor correction also needs to be reversed - if (distance < 0) - turnSpeed *= -1.0; - - // Apply the turning correction to the current driving speed. - moveRobot(driveSpeed, turnSpeed); - - // Display drive status for the driver. - sendTelemetry(true); - } - - // Stop all motion & Turn off RUN_TO_POSITION - moveRobot(0, 0); - leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - } - } - - /** - * Spin on the central axis to point in a new direction. - *

- * Move will stop if either of these conditions occur: - *

- * 1) Move gets to the heading (angle) - *

- * 2) Driver stops the OpMode running. - * - * @param maxTurnSpeed Desired MAX speed of turn. (range 0 to +1.0) - * @param heading Absolute Heading Angle (in Degrees) relative to last gyro reset. - * 0 = fwd. +ve is CCW from fwd. -ve is CW from forward. - * If a relative angle is required, add/subtract from current heading. - */ - public void turnToHeading(double maxTurnSpeed, double heading) { - - // Run getSteeringCorrection() once to pre-calculate the current error - getSteeringCorrection(heading, P_DRIVE_GAIN); - - // keep looping while we are still active, and not on heading. - while (opModeIsActive() && (Math.abs(headingError) > HEADING_THRESHOLD)) { - - // Determine required steering to keep on heading - turnSpeed = getSteeringCorrection(heading, P_TURN_GAIN); - - // Clip the speed to the maximum permitted value. - turnSpeed = Range.clip(turnSpeed, -maxTurnSpeed, maxTurnSpeed); - - // Pivot in place by applying the turning correction - moveRobot(0, turnSpeed); - - // Display drive status for the driver. - sendTelemetry(false); - } - - // Stop all motion; - moveRobot(0, 0); - } - - /** - * Obtain & hold a heading for a finite amount of time - *

- * Move will stop once the requested time has elapsed - *

- * This function is useful for giving the robot a moment to stabilize its heading between movements. - * - * @param maxTurnSpeed Maximum differential turn speed (range 0 to +1.0) - * @param heading Absolute Heading Angle (in Degrees) relative to last gyro reset. - * 0 = fwd. +ve is CCW from fwd. -ve is CW from forward. - * If a relative angle is required, add/subtract from current heading. - * @param holdTime Length of time (in seconds) to hold the specified heading. - */ - public void holdHeading(double maxTurnSpeed, double heading, double holdTime) { - - ElapsedTime holdTimer = new ElapsedTime(); - holdTimer.reset(); - - // keep looping while we have time remaining. - while (opModeIsActive() && (holdTimer.time() < holdTime)) { - // Determine required steering to keep on heading - turnSpeed = getSteeringCorrection(heading, P_TURN_GAIN); - - // Clip the speed to the maximum permitted value. - turnSpeed = Range.clip(turnSpeed, -maxTurnSpeed, maxTurnSpeed); - - // Pivot in place by applying the turning correction - moveRobot(0, turnSpeed); - - // Display drive status for the driver. - sendTelemetry(false); - } - - // Stop all motion; - moveRobot(0, 0); - } - - // ********** LOW Level driving functions. ******************** - - /** - * Use a Proportional Controller to determine how much steering correction is required. - * - * @param desiredHeading The desired absolute heading (relative to last heading reset) - * @param proportionalGain Gain factor applied to heading error to obtain turning power. - * @return Turning power needed to get to required heading. - */ - public double getSteeringCorrection(double desiredHeading, double proportionalGain) { - targetHeading = desiredHeading; // Save for telemetry - - // Determine the heading current error - headingError = targetHeading - getHeading(); - - // Normalize the error to be within +/- 180 degrees - while (headingError > 180) headingError -= 360; - while (headingError <= -180) headingError += 360; - - // Multiply the error by the gain to determine the required steering correction/ Limit the result to +/- 1.0 - return Range.clip(headingError * proportionalGain, -1, 1); - } - - /** - * Take separate drive (fwd/rev) and turn (right/left) requests, - * combines them, and applies the appropriate speed commands to the left and right wheel motors. - * @param drive forward motor speed - * @param turn clockwise turning motor speed. - */ - public void moveRobot(double drive, double turn) { - driveSpeed = drive; // save this value as a class member so it can be used by telemetry. - turnSpeed = turn; // save this value as a class member so it can be used by telemetry. - - leftSpeed = drive - turn; - rightSpeed = drive + turn; - - // Scale speeds down if either one exceeds +/- 1.0; - double max = Math.max(Math.abs(leftSpeed), Math.abs(rightSpeed)); - if (max > 1.0) - { - leftSpeed /= max; - rightSpeed /= max; - } - - leftDrive.setPower(leftSpeed); - rightDrive.setPower(rightSpeed); - } - - /** - * Display the various control parameters while driving - * - * @param straight Set to true if we are driving straight, and the encoder positions should be included in the telemetry. - */ - private void sendTelemetry(boolean straight) { - - if (straight) { - telemetry.addData("Motion", "Drive Straight"); - telemetry.addData("Target Pos L:R", "%7d:%7d", leftTarget, rightTarget); - telemetry.addData("Actual Pos L:R", "%7d:%7d", leftDrive.getCurrentPosition(), - rightDrive.getCurrentPosition()); - } else { - telemetry.addData("Motion", "Turning"); - } - - telemetry.addData("Heading- Target : Current", "%5.2f : %5.0f", targetHeading, getHeading()); - telemetry.addData("Error : Steer Pwr", "%5.1f : %5.1f", headingError, turnSpeed); - telemetry.addData("Wheel Speeds L : R", "%5.2f : %5.2f", leftSpeed, rightSpeed); - telemetry.update(); - } - - /** - * read the Robot heading directly from the IMU (in degrees) - */ - public double getHeading() { - YawPitchRollAngles orientation = imu.getRobotYawPitchRollAngles(); - return orientation.getYaw(AngleUnit.DEGREES); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByTime_Linear.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByTime_Linear.java deleted file mode 100644 index a7147481..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveByTime_Linear.java +++ /dev/null @@ -1,128 +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.Autonomous; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.util.ElapsedTime; - -/* - * This OpMode illustrates the concept of driving a path based on time. - * The code is structured as a LinearOpMode - * - * The code assumes that you do NOT have encoders on the wheels, - * otherwise you would use: RobotAutoDriveByEncoder; - * - * The desired path in this example is: - * - Drive forward for 3 seconds - * - Spin right for 1.3 seconds - * - Drive Backward for 1 Second - * - * The code is written in a simple form with no optimizations. - * However, there are several ways that this type of sequence could be streamlined, - * - * 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="Robot: Auto Drive By Time", group="Robot") -@Disabled -public class RobotAutoDriveByTime_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - - private ElapsedTime runtime = new ElapsedTime(); - - - static final double FORWARD_SPEED = 0.6; - static final double TURN_SPEED = 0.5; - - @Override - public void runOpMode() { - - // Initialize the drive system variables. - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // Send telemetry message to signify robot waiting; - telemetry.addData("Status", "Ready to run"); // - telemetry.update(); - - // Wait for the game to start (driver presses START) - waitForStart(); - - // Step through each leg of the path, ensuring that the OpMode has not been stopped along the way. - - // Step 1: Drive forward for 3 seconds - leftDrive.setPower(FORWARD_SPEED); - rightDrive.setPower(FORWARD_SPEED); - runtime.reset(); - while (opModeIsActive() && (runtime.seconds() < 3.0)) { - telemetry.addData("Path", "Leg 1: %4.1f S Elapsed", runtime.seconds()); - telemetry.update(); - } - - // Step 2: Spin right for 1.3 seconds - leftDrive.setPower(TURN_SPEED); - rightDrive.setPower(-TURN_SPEED); - runtime.reset(); - while (opModeIsActive() && (runtime.seconds() < 1.3)) { - telemetry.addData("Path", "Leg 2: %4.1f S Elapsed", runtime.seconds()); - telemetry.update(); - } - - // Step 3: Drive Backward for 1 Second - leftDrive.setPower(-FORWARD_SPEED); - rightDrive.setPower(-FORWARD_SPEED); - runtime.reset(); - while (opModeIsActive() && (runtime.seconds() < 1.0)) { - telemetry.addData("Path", "Leg 3: %4.1f S Elapsed", runtime.seconds()); - telemetry.update(); - } - - // Step 4: Stop - leftDrive.setPower(0); - rightDrive.setPower(0); - - telemetry.addData("Path", "Complete"); - telemetry.update(); - sleep(1000); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagOmni.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagOmni.java deleted file mode 100644 index 9bac0069..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagOmni.java +++ /dev/null @@ -1,321 +0,0 @@ -/* Copyright (c) 2023 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.DcMotor; -import com.qualcomm.robotcore.util.Range; -import org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.ExposureControl; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.GainControl; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -/* - * This OpMode illustrates using a camera to locate and drive towards a specific AprilTag. - * The code assumes a Holonomic (Mecanum or X Drive) Robot. - * - * For an introduction to AprilTags, see the ftc-docs link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the tag, relative to the camera. - * This information is provided in the "ftcPose" member of the returned "detection", and is explained in the ftc-docs page linked below. - * https://ftc-docs.firstinspires.org/apriltag-detection-values - * - * The drive goal is to rotate to keep the Tag centered in the camera, while strafing to be directly in front of the tag, and - * driving towards the tag to achieve the desired distance. - * To reduce any motion blur (which will interrupt the detection process) the Camera exposure is reduced to a very low value (5mS) - * You can determine the best Exposure and Gain values by using the ConceptAprilTagOptimizeExposure OpMode in this Samples folder. - * - * The code assumes a Robot Configuration with motors named: leftfront_drive and rightfront_drive, leftback_drive and rightback_drive. - * The motor directions must be set so a positive power goes forward on all wheels. - * This sample assumes that the current game AprilTag Library (usually for the current season) is being loaded by default, - * so you should choose to approach a valid tag ID. - * - * Under manual control, the left stick will move forward/back & left/right. The right stick will rotate the robot. - * Manually drive the robot until it displays Target data on the Driver Station. - * - * Press and hold the *Left Bumper* to enable the automatic "Drive to target" mode. - * Release the Left Bumper to return to manual driving mode. - * - * Under "Drive To Target" mode, the robot has three goals: - * 1) Turn the robot to always keep the Tag centered on the camera frame. (Use the Target Bearing to turn the robot.) - * 2) Strafe the robot towards the centerline of the Tag, so it approaches directly in front of the tag. (Use the Target Yaw to strafe the robot) - * 3) Drive towards the Tag to get to the desired distance. (Use Tag Range to drive the robot forward/backward) - * - * Use DESIRED_DISTANCE to set how close you want the robot to get to the target. - * Speed and Turn sensitivity can be adjusted using the SPEED_GAIN, STRAFE_GAIN and TURN_GAIN constants. - * - * Use Android Studio to Copy this Class, and Paste it into the TeamCode/src/main/java/org/firstinspires/ftc/teamcode folder. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list. - * - */ - -@TeleOp(name="Omni Drive To AprilTag", group = "Concept") -@Disabled -public class RobotAutoDriveToAprilTagOmni extends LinearOpMode -{ - // Adjust these numbers to suit your robot. - final double DESIRED_DISTANCE = 12.0; // this is how close the camera should get to the target (inches) - - // Set the GAIN constants to control the relationship between the measured position error, and how much power is - // applied to the drive motors to correct the error. - // Drive = Error * Gain Make these values smaller for smoother control, or larger for a more aggressive response. - final double SPEED_GAIN = 0.02 ; // Forward Speed Control "Gain". e.g. Ramp up to 50% power at a 25 inch error. (0.50 / 25.0) - final double STRAFE_GAIN = 0.015 ; // Strafe Speed Control "Gain". e.g. Ramp up to 37% power at a 25 degree Yaw error. (0.375 / 25.0) - final double TURN_GAIN = 0.01 ; // Turn Control "Gain". e.g. Ramp up to 25% power at a 25 degree error. (0.25 / 25.0) - - final double MAX_AUTO_SPEED = 0.5; // Clip the approach speed to this max value (adjust for your robot) - final double MAX_AUTO_STRAFE= 0.5; // Clip the strafing speed to this max value (adjust for your robot) - final double MAX_AUTO_TURN = 0.3; // Clip the turn speed to this max value (adjust for your robot) - - private DcMotor leftFrontDrive = null; // Used to control the left front drive wheel - private DcMotor rightFrontDrive = null; // Used to control the right front drive wheel - private DcMotor leftBackDrive = null; // Used to control the left back drive wheel - private DcMotor rightBackDrive = null; // Used to control the right back drive wheel - - private static final boolean USE_WEBCAM = true; // Set true to use a webcam, or false for a phone camera - private static final int DESIRED_TAG_ID = -1; // Choose the tag you want to approach or set to -1 for ANY tag. - private VisionPortal visionPortal; // Used to manage the video source. - private AprilTagProcessor aprilTag; // Used for managing the AprilTag detection process. - private AprilTagDetection desiredTag = null; // Used to hold the data for a detected AprilTag - - @Override public void runOpMode() - { - boolean targetFound = false; // Set to true when an AprilTag target is detected - double drive = 0; // Desired forward power/speed (-1 to +1) - double strafe = 0; // Desired strafe power/speed (-1 to +1) - double turn = 0; // Desired turning power/speed (-1 to +1) - - // Initialize the Apriltag Detection process - initAprilTag(); - - // Initialize the hardware variables. Note that the strings used here as parameters - // to 'get' must match the names assigned during the robot configuration. - // step (using the FTC Robot Controller app on the phone). - leftFrontDrive = hardwareMap.get(DcMotor.class, "leftfront_drive"); - rightFrontDrive = hardwareMap.get(DcMotor.class, "rightfront_drive"); - leftBackDrive = hardwareMap.get(DcMotor.class, "leftback_drive"); - rightBackDrive = hardwareMap.get(DcMotor.class, "rightback_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftFrontDrive.setDirection(DcMotor.Direction.REVERSE); - leftBackDrive.setDirection(DcMotor.Direction.REVERSE); - rightFrontDrive.setDirection(DcMotor.Direction.FORWARD); - rightBackDrive.setDirection(DcMotor.Direction.FORWARD); - - if (USE_WEBCAM) - setManualExposure(6, 250); // Use low exposure time to reduce motion blur - - // Wait for driver to press start - telemetry.addData("Camera preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) - { - targetFound = false; - desiredTag = null; - - // Step through the list of detected tags and look for a matching tag - List currentDetections = aprilTag.getDetections(); - for (AprilTagDetection detection : currentDetections) { - // Look to see if we have size info on this tag. - if (detection.metadata != null) { - // Check to see if we want to track towards this tag. - if ((DESIRED_TAG_ID < 0) || (detection.id == DESIRED_TAG_ID)) { - // Yes, we want to use this tag. - targetFound = true; - desiredTag = detection; - break; // don't look any further. - } else { - // This tag is in the library, but we do not want to track it right now. - telemetry.addData("Skipping", "Tag ID %d is not desired", detection.id); - } - } else { - // This tag is NOT in the library, so we don't have enough information to track to it. - telemetry.addData("Unknown", "Tag ID %d is not in TagLibrary", detection.id); - } - } - - // Tell the driver what we see, and what to do. - if (targetFound) { - telemetry.addData("\n>","HOLD Left-Bumper to Drive to Target\n"); - telemetry.addData("Found", "ID %d (%s)", desiredTag.id, desiredTag.metadata.name); - telemetry.addData("Range", "%5.1f inches", desiredTag.ftcPose.range); - telemetry.addData("Bearing","%3.0f degrees", desiredTag.ftcPose.bearing); - telemetry.addData("Yaw","%3.0f degrees", desiredTag.ftcPose.yaw); - } else { - telemetry.addData("\n>","Drive using joysticks to find valid target\n"); - } - - // If Left Bumper is being pressed, AND we have found the desired target, Drive to target Automatically . - if (gamepad1.left_bumper && targetFound) { - - // Determine heading, range and Yaw (tag image rotation) error so we can use them to control the robot automatically. - double rangeError = (desiredTag.ftcPose.range - DESIRED_DISTANCE); - double headingError = desiredTag.ftcPose.bearing; - double yawError = desiredTag.ftcPose.yaw; - - // Use the speed and turn "gains" to calculate how we want the robot to move. - drive = Range.clip(rangeError * SPEED_GAIN, -MAX_AUTO_SPEED, MAX_AUTO_SPEED); - turn = Range.clip(headingError * TURN_GAIN, -MAX_AUTO_TURN, MAX_AUTO_TURN) ; - strafe = Range.clip(-yawError * STRAFE_GAIN, -MAX_AUTO_STRAFE, MAX_AUTO_STRAFE); - - telemetry.addData("Auto","Drive %5.2f, Strafe %5.2f, Turn %5.2f ", drive, strafe, turn); - } else { - - // drive using manual POV Joystick mode. Slow things down to make the robot more controlable. - drive = -gamepad1.left_stick_y / 2.0; // Reduce drive rate to 50%. - strafe = -gamepad1.left_stick_x / 2.0; // Reduce strafe rate to 50%. - turn = -gamepad1.right_stick_x / 3.0; // Reduce turn rate to 33%. - telemetry.addData("Manual","Drive %5.2f, Strafe %5.2f, Turn %5.2f ", drive, strafe, turn); - } - telemetry.update(); - - // Apply desired axes motions to the drivetrain. - moveRobot(drive, strafe, turn); - sleep(10); - } - } - - /** - * Move robot according to desired axes motions - *

- * Positive X is forward - *

- * Positive Y is strafe left - *

- * Positive Yaw is counter-clockwise - */ - public void moveRobot(double x, double y, double yaw) { - // Calculate wheel powers. - double leftFrontPower = x -y -yaw; - double rightFrontPower = x +y +yaw; - double leftBackPower = x +y -yaw; - double rightBackPower = x -y +yaw; - - // Normalize wheel powers to be less than 1.0 - double max = Math.max(Math.abs(leftFrontPower), Math.abs(rightFrontPower)); - max = Math.max(max, Math.abs(leftBackPower)); - max = Math.max(max, Math.abs(rightBackPower)); - - if (max > 1.0) { - leftFrontPower /= max; - rightFrontPower /= max; - leftBackPower /= max; - rightBackPower /= max; - } - - // Send powers to the wheels. - leftFrontDrive.setPower(leftFrontPower); - rightFrontDrive.setPower(rightFrontPower); - leftBackDrive.setPower(leftBackPower); - rightBackDrive.setPower(rightBackPower); - } - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - // Create the AprilTag processor by using a builder. - aprilTag = new AprilTagProcessor.Builder().build(); - - // Adjust Image Decimation to trade-off detection-range for detection-rate. - // e.g. Some typical detection data using a Logitech C920 WebCam - // Decimation = 1 .. Detect 2" Tag from 10 feet away at 10 Frames per second - // Decimation = 2 .. Detect 2" Tag from 6 feet away at 22 Frames per second - // Decimation = 3 .. Detect 2" Tag from 4 feet away at 30 Frames Per Second - // Decimation = 3 .. Detect 5" Tag from 10 feet away at 30 Frames Per Second - // Note: Decimation can be changed on-the-fly to adapt during a match. - aprilTag.setDecimation(2); - - // Create the vision portal by using a builder. - if (USE_WEBCAM) { - visionPortal = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .addProcessor(aprilTag) - .build(); - } else { - visionPortal = new VisionPortal.Builder() - .setCamera(BuiltinCameraDirection.BACK) - .addProcessor(aprilTag) - .build(); - } - } - - /* - Manually set the camera gain and exposure. - This can only be called AFTER calling initAprilTag(), and only works for Webcams; - */ - private void setManualExposure(int exposureMS, int gain) { - // Wait for the camera to be open, then use the controls - - if (visionPortal == null) { - return; - } - - // Make sure camera is streaming before we try to set the exposure controls - if (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING) { - telemetry.addData("Camera", "Waiting"); - telemetry.update(); - while (!isStopRequested() && (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING)) { - sleep(20); - } - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - - // Set camera controls unless we are stopping. - if (!isStopRequested()) - { - ExposureControl exposureControl = visionPortal.getCameraControl(ExposureControl.class); - if (exposureControl.getMode() != ExposureControl.Mode.Manual) { - exposureControl.setMode(ExposureControl.Mode.Manual); - sleep(50); - } - exposureControl.setExposure((long)exposureMS, TimeUnit.MILLISECONDS); - sleep(20); - GainControl gainControl = visionPortal.getCameraControl(GainControl.class); - gainControl.setGain(gain); - sleep(20); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagTank.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagTank.java deleted file mode 100644 index ba3eb4f9..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToAprilTagTank.java +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (c) 2023 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.DcMotor; -import com.qualcomm.robotcore.util.Range; -import org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.ExposureControl; -import org.firstinspires.ftc.robotcore.external.hardware.camera.controls.GainControl; -import org.firstinspires.ftc.vision.VisionPortal; -import org.firstinspires.ftc.vision.apriltag.AprilTagDetection; -import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -/* - * This OpMode illustrates using a camera to locate and drive towards a specific AprilTag. - * The code assumes a basic two-wheel (Tank) Robot Drivetrain - * - * For an introduction to AprilTags, see the ftc-docs link below: - * https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/apriltag_intro/apriltag-intro.html - * - * When an AprilTag in the TagLibrary is detected, the SDK provides location and orientation of the tag, relative to the camera. - * This information is provided in the "ftcPose" member of the returned "detection", and is explained in the ftc-docs page linked below. - * https://ftc-docs.firstinspires.org/apriltag-detection-values - * - * The driving goal is to rotate to keep the tag centered in the camera, while driving towards the tag to achieve the desired distance. - * To reduce any motion blur (which will interrupt the detection process) the Camera exposure is reduced to a very low value (5mS) - * You can determine the best exposure and gain values by using the ConceptAprilTagOptimizeExposure OpMode in this Samples folder. - * - * The code assumes a Robot Configuration with motors named left_drive and right_drive. - * The motor directions must be set so a positive power goes forward on both wheels; - * This sample assumes that the default AprilTag Library (usually for the current season) is being loaded by default - * so you should choose to approach a valid tag ID. - * - * Under manual control, the left stick will move forward/back, and the right stick will rotate the robot. - * This is called POV Joystick mode, different than Tank Drive (where each joystick controls a wheel). - * - * Manually drive the robot until it displays Target data on the Driver Station. - * Press and hold the *Left Bumper* to enable the automatic "Drive to target" mode. - * Release the Left Bumper to return to manual driving mode. - * - * Under "Drive To Target" mode, the robot has two goals: - * 1) Turn the robot to always keep the Tag centered on the camera frame. (Use the Target Bearing to turn the robot.) - * 2) Drive towards the Tag to get to the desired distance. (Use Tag Range to drive the robot forward/backward) - * - * Use DESIRED_DISTANCE to set how close you want the robot to get to the target. - * Speed and Turn sensitivity can be adjusted using the SPEED_GAIN and TURN_GAIN constants. - * - * Use Android Studio to Copy this Class, and Paste it into the TeamCode/src/main/java/org/firstinspires/ftc/teamcode folder. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list. - * - */ - -@TeleOp(name="Tank Drive To AprilTag", group = "Concept") -@Disabled -public class RobotAutoDriveToAprilTagTank extends LinearOpMode -{ - // Adjust these numbers to suit your robot. - final double DESIRED_DISTANCE = 12.0; // this is how close the camera should get to the target (inches) - - // Set the GAIN constants to control the relationship between the measured position error, and how much power is - // applied to the drive motors to correct the error. - // Drive = Error * Gain Make these values smaller for smoother control, or larger for a more aggressive response. - final double SPEED_GAIN = 0.02 ; // Speed Control "Gain". e.g. Ramp up to 50% power at a 25 inch error. (0.50 / 25.0) - final double TURN_GAIN = 0.01 ; // Turn Control "Gain". e.g. Ramp up to 25% power at a 25 degree error. (0.25 / 25.0) - - final double MAX_AUTO_SPEED = 0.5; // Clip the approach speed to this max value (adjust for your robot) - final double MAX_AUTO_TURN = 0.25; // Clip the turn speed to this max value (adjust for your robot) - - private DcMotor leftDrive = null; // Used to control the left drive wheel - private DcMotor rightDrive = null; // Used to control the right drive wheel - - private static final boolean USE_WEBCAM = true; // Set true to use a webcam, or false for a phone camera - private static final int DESIRED_TAG_ID = -1; // Choose the tag you want to approach or set to -1 for ANY tag. - private VisionPortal visionPortal; // Used to manage the video source. - private AprilTagProcessor aprilTag; // Used for managing the AprilTag detection process. - private AprilTagDetection desiredTag = null; // Used to hold the data for a detected AprilTag - - @Override public void runOpMode() - { - boolean targetFound = false; // Set to true when an AprilTag target is detected - double drive = 0; // Desired forward power/speed (-1 to +1) +ve is forward - double turn = 0; // Desired turning power/speed (-1 to +1) +ve is CounterClockwise - - // Initialize the Apriltag Detection process - initAprilTag(); - - // Initialize the hardware variables. Note that the strings used here as parameters - // to 'get' must match the names assigned during the robot configuration. - // step (using the FTC Robot Controller app on the phone). - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Single Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - if (USE_WEBCAM) - setManualExposure(6, 250); // Use low exposure time to reduce motion blur - - // Wait for the driver to press Start - telemetry.addData("Camera preview on/off", "3 dots, Camera Stream"); - telemetry.addData(">", "Touch START to start OpMode"); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) - { - targetFound = false; - desiredTag = null; - - // Step through the list of detected tags and look for a matching tag - List currentDetections = aprilTag.getDetections(); - for (AprilTagDetection detection : currentDetections) { - // Look to see if we have size info on this tag. - if (detection.metadata != null) { - // Check to see if we want to track towards this tag. - if ((DESIRED_TAG_ID < 0) || (detection.id == DESIRED_TAG_ID)) { - // Yes, we want to use this tag. - targetFound = true; - desiredTag = detection; - break; // don't look any further. - } else { - // This tag is in the library, but we do not want to track it right now. - telemetry.addData("Skipping", "Tag ID %d is not desired", detection.id); - } - } else { - // This tag is NOT in the library, so we don't have enough information to track to it. - telemetry.addData("Unknown", "Tag ID %d is not in TagLibrary", detection.id); - } - } - - // Tell the driver what we see, and what to do. - if (targetFound) { - telemetry.addData("\n>","HOLD Left-Bumper to Drive to Target\n"); - telemetry.addData("Found", "ID %d (%s)", desiredTag.id, desiredTag.metadata.name); - telemetry.addData("Range", "%5.1f inches", desiredTag.ftcPose.range); - telemetry.addData("Bearing","%3.0f degrees", desiredTag.ftcPose.bearing); - } else { - telemetry.addData("\n>","Drive using joysticks to find valid target\n"); - } - - // If Left Bumper is being pressed, AND we have found the desired target, Drive to target Automatically . - if (gamepad1.left_bumper && targetFound) { - - // Determine heading and range error so we can use them to control the robot automatically. - double rangeError = (desiredTag.ftcPose.range - DESIRED_DISTANCE); - double headingError = desiredTag.ftcPose.bearing; - - // Use the speed and turn "gains" to calculate how we want the robot to move. Clip it to the maximum - drive = Range.clip(rangeError * SPEED_GAIN, -MAX_AUTO_SPEED, MAX_AUTO_SPEED); - turn = Range.clip(headingError * TURN_GAIN, -MAX_AUTO_TURN, MAX_AUTO_TURN) ; - - telemetry.addData("Auto","Drive %5.2f, Turn %5.2f", drive, turn); - } else { - - // drive using manual POV Joystick mode. - drive = -gamepad1.left_stick_y / 2.0; // Reduce drive rate to 50%. - turn = -gamepad1.right_stick_x / 4.0; // Reduce turn rate to 25%. - telemetry.addData("Manual","Drive %5.2f, Turn %5.2f", drive, turn); - } - telemetry.update(); - - // Apply desired axes motions to the drivetrain. - moveRobot(drive, turn); - sleep(10); - } - } - - /** - * Move robot according to desired axes motions - *

- * Positive X is forward - *

- * Positive Yaw is counter-clockwise - */ - public void moveRobot(double x, double yaw) { - // Calculate left and right wheel powers. - double leftPower = x - yaw; - double rightPower = x + yaw; - - // Normalize wheel powers to be less than 1.0 - double max = Math.max(Math.abs(leftPower), Math.abs(rightPower)); - if (max >1.0) { - leftPower /= max; - rightPower /= max; - } - - // Send powers to the wheels. - leftDrive.setPower(leftPower); - rightDrive.setPower(rightPower); - } - - /** - * Initialize the AprilTag processor. - */ - private void initAprilTag() { - // Create the AprilTag processor by using a builder. - aprilTag = new AprilTagProcessor.Builder().build(); - - // Adjust Image Decimation to trade-off detection-range for detection-rate. - // e.g. Some typical detection data using a Logitech C920 WebCam - // Decimation = 1 .. Detect 2" Tag from 10 feet away at 10 Frames per second - // Decimation = 2 .. Detect 2" Tag from 6 feet away at 22 Frames per second - // Decimation = 3 .. Detect 2" Tag from 4 feet away at 30 Frames Per Second - // Decimation = 3 .. Detect 5" Tag from 10 feet away at 30 Frames Per Second - // Note: Decimation can be changed on-the-fly to adapt during a match. - aprilTag.setDecimation(2); - - // Create the vision portal by using a builder. - if (USE_WEBCAM) { - visionPortal = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .addProcessor(aprilTag) - .build(); - } else { - visionPortal = new VisionPortal.Builder() - .setCamera(BuiltinCameraDirection.BACK) - .addProcessor(aprilTag) - .build(); - } - } - - /* - Manually set the camera gain and exposure. - This can only be called AFTER calling initAprilTag(), and only works for Webcams; - */ - private void setManualExposure(int exposureMS, int gain) { - // Wait for the camera to be open, then use the controls - - if (visionPortal == null) { - return; - } - - // Make sure camera is streaming before we try to set the exposure controls - if (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING) { - telemetry.addData("Camera", "Waiting"); - telemetry.update(); - while (!isStopRequested() && (visionPortal.getCameraState() != VisionPortal.CameraState.STREAMING)) { - sleep(20); - } - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - - // Set camera controls unless we are stopping. - if (!isStopRequested()) - { - ExposureControl exposureControl = visionPortal.getCameraControl(ExposureControl.class); - if (exposureControl.getMode() != ExposureControl.Mode.Manual) { - exposureControl.setMode(ExposureControl.Mode.Manual); - sleep(50); - } - exposureControl.setExposure((long)exposureMS, TimeUnit.MILLISECONDS); - sleep(20); - GainControl gainControl = visionPortal.getCameraControl(GainControl.class); - gainControl.setGain(gain); - sleep(20); - telemetry.addData("Camera", "Ready"); - telemetry.update(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToLine_Linear.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToLine_Linear.java deleted file mode 100644 index 780f2604..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotAutoDriveToLine_Linear.java +++ /dev/null @@ -1,142 +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.Autonomous; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.hardware.NormalizedColorSensor; -import com.qualcomm.robotcore.hardware.NormalizedRGBA; -import com.qualcomm.robotcore.hardware.SwitchableLight; - -/* - * This OpMode illustrates the concept of driving up to a line and then stopping. - * The code is structured as a LinearOpMode - * - * The Sensor used here can be a REV Color Sensor V2 or V3. Make sure the white LED is turned on. - * The sensor can be plugged into any I2C port, and must be named "sensor_color" in the active configuration. - * - * Depending on the height of your color sensor, you may want to set the sensor "gain". - * The higher the gain, the greater the reflected light reading will be. - * Use the SensorColor sample in this folder to determine the minimum gain value that provides an - * "Alpha" reading of 1.0 when you are on top of the white line. In this sample, we use a gain of 15 - * which works well with a Rev V2 color sensor - * - * Setting the correct WHITE_THRESHOLD value is key to stopping correctly. - * This should be set halfway between the bare-tile, and white-line "Alpha" values. - * The reflected light value can be read on the screen once the OpMode has been INIT, but before it is STARTED. - * Move the sensor on and off the white line and note the min and max readings. - * Edit this code to make WHITE_THRESHOLD halfway between the min and max. - * - * 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="Robot: Auto Drive To Line", group="Robot") -@Disabled -public class RobotAutoDriveToLine_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - - /** The variable to store a reference to our color sensor hardware object */ - NormalizedColorSensor colorSensor; - - static final double WHITE_THRESHOLD = 0.5; // spans between 0.0 - 1.0 from dark to light - static final double APPROACH_SPEED = 0.25; - - @Override - public void runOpMode() { - - // Initialize the drive system variables. - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // When run, this OpMode should start both motors driving forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // If there are encoders connected, switch to RUN_USING_ENCODER mode for greater accuracy - // leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - // rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Get a reference to our sensor object. It's recommended to use NormalizedColorSensor over - // ColorSensor, because NormalizedColorSensor consistently gives values between 0 and 1, while - // the values you get from ColorSensor are dependent on the specific sensor you're using. - colorSensor = hardwareMap.get(NormalizedColorSensor.class, "sensor_color"); - - // If necessary, turn ON the white LED (if there is no LED switch on the sensor) - if (colorSensor instanceof SwitchableLight) { - ((SwitchableLight)colorSensor).enableLight(true); - } - - // Some sensors allow you to set your light sensor gain for optimal sensitivity... - // See the SensorColor sample in this folder for how to determine the optimal gain. - // A gain of 15 causes a Rev Color Sensor V2 to produce an Alpha value of 1.0 at about 1.5" above the floor. - colorSensor.setGain(15); - - // Wait for driver to press START) - // Abort this loop is started or stopped. - while (opModeInInit()) { - - // Send telemetry message to signify robot waiting; - telemetry.addData("Status", "Ready to drive to white line."); // - - // Display the light level while we are waiting to start - getBrightness(); - } - - // Start the robot moving forward, and then begin looking for a white line. - leftDrive.setPower(APPROACH_SPEED); - rightDrive.setPower(APPROACH_SPEED); - - // run until the white line is seen OR the driver presses STOP; - while (opModeIsActive() && (getBrightness() < WHITE_THRESHOLD)) { - sleep(5); - } - - // Stop all motors - leftDrive.setPower(0); - rightDrive.setPower(0); - } - - // to obtain reflected light, read the normalized values from the color sensor. Return the Alpha channel. - double getBrightness() { - NormalizedRGBA colors = colorSensor.getNormalizedColors(); - telemetry.addData("Light Level (0 to 1)", "%4.2f", colors.alpha); - telemetry.update(); - - return colors.alpha; - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotHardware.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotHardware.java deleted file mode 100644 index b1c8de62..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotHardware.java +++ /dev/null @@ -1,167 +0,0 @@ -/* Copyright (c) 2022 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.hardware.DcMotor; -import com.qualcomm.robotcore.hardware.Servo; -import com.qualcomm.robotcore.util.Range; - -/* - * This file works in conjunction with the External Hardware Class sample called: ConceptExternalHardwareClass.java - * Please read the explanations in that Sample about how to use this class definition. - * - * This file defines a Java Class that performs all the setup and configuration for a sample robot's hardware (motors and sensors). - * It assumes three motors (left_drive, right_drive and arm) and two servos (left_hand and right_hand) - * - * This one file/class can be used by ALL of your OpModes without having to cut & paste the code each time. - * - * Where possible, the actual hardware objects are "abstracted" (or hidden) so the OpMode code just makes calls into the class, - * rather than accessing the internal hardware directly. This is why the objects are declared "private". - * - * Use Android Studio to Copy this Class, and Paste it into your team's code folder with *exactly the same name*. - * - * Or... In OnBot Java, add a new file named RobotHardware.java, select this sample, and select Not an OpMode. - * Also add a new OpMode, select the sample ConceptExternalHardwareClass.java, and select TeleOp. - * - */ - -public class RobotHardware { - - /* Declare OpMode members. */ - private LinearOpMode myOpMode = null; // gain access to methods in the calling OpMode. - - // Define Motor and Servo objects (Make them private so they can't be accessed externally) - private DcMotor leftDrive = null; - private DcMotor rightDrive = null; - private DcMotor armMotor = null; - private Servo leftHand = null; - private Servo rightHand = null; - - // Define Drive constants. Make them public so they CAN be used by the calling OpMode - public static final double MID_SERVO = 0.5 ; - public static final double HAND_SPEED = 0.02 ; // sets rate to move servo - public static final double ARM_UP_POWER = 0.45 ; - public static final double ARM_DOWN_POWER = -0.45 ; - - // Define a constructor that allows the OpMode to pass a reference to itself. - public RobotHardware (LinearOpMode opmode) { - myOpMode = opmode; - } - - /** - * Initialize all the robot's hardware. - * This method must be called ONCE when the OpMode is initialized. - *

- * All of the hardware devices are accessed via the hardware map, and initialized. - */ - public void init() { - // Define and Initialize Motors (note: need to use reference to actual OpMode). - leftDrive = myOpMode.hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = myOpMode.hardwareMap.get(DcMotor.class, "right_drive"); - armMotor = myOpMode.hardwareMap.get(DcMotor.class, "arm"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left stick forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // If there are encoders connected, switch to RUN_USING_ENCODER mode for greater accuracy - // leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - // rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Define and initialize ALL installed servos. - leftHand = myOpMode.hardwareMap.get(Servo.class, "left_hand"); - rightHand = myOpMode.hardwareMap.get(Servo.class, "right_hand"); - leftHand.setPosition(MID_SERVO); - rightHand.setPosition(MID_SERVO); - - myOpMode.telemetry.addData(">", "Hardware Initialized"); - myOpMode.telemetry.update(); - } - - /** - * Calculates the left/right motor powers required to achieve the requested - * robot motions: Drive (Axial motion) and Turn (Yaw motion). - * Then sends these power levels to the motors. - * - * @param Drive Fwd/Rev driving power (-1.0 to 1.0) +ve is forward - * @param Turn Right/Left turning power (-1.0 to 1.0) +ve is CW - */ - public void driveRobot(double Drive, double Turn) { - // Combine drive and turn for blended motion. - double left = Drive + Turn; - double right = Drive - Turn; - - // Scale the values so neither exceed +/- 1.0 - double max = Math.max(Math.abs(left), Math.abs(right)); - if (max > 1.0) - { - left /= max; - right /= max; - } - - // Use existing function to drive both wheels. - setDrivePower(left, right); - } - - /** - * Pass the requested wheel motor powers to the appropriate hardware drive motors. - * - * @param leftWheel Fwd/Rev driving power (-1.0 to 1.0) +ve is forward - * @param rightWheel Fwd/Rev driving power (-1.0 to 1.0) +ve is forward - */ - public void setDrivePower(double leftWheel, double rightWheel) { - // Output the values to the motor drives. - leftDrive.setPower(leftWheel); - rightDrive.setPower(rightWheel); - } - - /** - * Pass the requested arm power to the appropriate hardware drive motor - * - * @param power driving power (-1.0 to 1.0) - */ - public void setArmPower(double power) { - armMotor.setPower(power); - } - - /** - * Send the two hand-servos to opposing (mirrored) positions, based on the passed offset. - * - * @param offset - */ - public void setHandPositions(double offset) { - offset = Range.clip(offset, -0.5, 0.5); - leftHand.setPosition(MID_SERVO + offset); - rightHand.setPosition(MID_SERVO - offset); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopPOV_Linear.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopPOV_Linear.java deleted file mode 100644 index af3840d3..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopPOV_Linear.java +++ /dev/null @@ -1,159 +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.DcMotor; -import com.qualcomm.robotcore.hardware.Servo; -import com.qualcomm.robotcore.util.Range; - -/* - * This OpMode executes a POV Game style Teleop for a direct drive robot - * The code is structured as a LinearOpMode - * - * In this mode the left stick moves the robot FWD and back, the Right stick turns left and right. - * It raises and lowers the arm using the Gamepad Y and A buttons respectively. - * It also opens and closes the claws slowly using the left and right Bumper buttons. - * - * 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="Robot: Teleop POV", group="Robot") -@Disabled -public class RobotTeleopPOV_Linear extends LinearOpMode { - - /* Declare OpMode members. */ - public DcMotor leftDrive = null; - public DcMotor rightDrive = null; - public DcMotor leftArm = null; - public Servo leftClaw = null; - public Servo rightClaw = null; - - double clawOffset = 0; - - public static final double MID_SERVO = 0.5 ; - public static final double CLAW_SPEED = 0.02 ; // sets rate to move servo - public static final double ARM_UP_POWER = 0.45 ; - public static final double ARM_DOWN_POWER = -0.45 ; - - @Override - public void runOpMode() { - double left; - double right; - double drive; - double turn; - double max; - - // Define and Initialize Motors - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - leftArm = hardwareMap.get(DcMotor.class, "left_arm"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left stick forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // If there are encoders connected, switch to RUN_USING_ENCODER mode for greater accuracy - // leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - // rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Define and initialize ALL installed servos. - leftClaw = hardwareMap.get(Servo.class, "left_hand"); - rightClaw = hardwareMap.get(Servo.class, "right_hand"); - leftClaw.setPosition(MID_SERVO); - rightClaw.setPosition(MID_SERVO); - - // Send telemetry message to signify robot waiting; - telemetry.addData(">", "Robot Ready. Press START."); // - telemetry.update(); - - // Wait for the game to start (driver presses START) - waitForStart(); - - // run until the end of the match (driver presses STOP) - while (opModeIsActive()) { - - // Run wheels in POV mode (note: The joystick goes negative when pushed forward, so negate it) - // In this mode the Left stick moves the robot fwd and back, the Right stick turns left and right. - // This way it's also easy to just drive straight, or just turn. - drive = -gamepad1.left_stick_y; - turn = gamepad1.right_stick_x; - - // Combine drive and turn for blended motion. - left = drive + turn; - right = drive - turn; - - // Normalize the values so neither exceed +/- 1.0 - max = Math.max(Math.abs(left), Math.abs(right)); - if (max > 1.0) - { - left /= max; - right /= max; - } - - // Output the safe vales to the motor drives. - leftDrive.setPower(left); - rightDrive.setPower(right); - - // Use gamepad left & right Bumpers to open and close the claw - if (gamepad1.right_bumper) - clawOffset += CLAW_SPEED; - else if (gamepad1.left_bumper) - clawOffset -= CLAW_SPEED; - - // Move both servos to new position. Assume servos are mirror image of each other. - clawOffset = Range.clip(clawOffset, -0.5, 0.5); - leftClaw.setPosition(MID_SERVO + clawOffset); - rightClaw.setPosition(MID_SERVO - clawOffset); - - // Use gamepad buttons to move arm up (Y) and down (A) - if (gamepad1.y) - leftArm.setPower(ARM_UP_POWER); - else if (gamepad1.a) - leftArm.setPower(ARM_DOWN_POWER); - else - leftArm.setPower(0.0); - - // Send telemetry message to signify robot running; - telemetry.addData("claw", "Offset = %.2f", clawOffset); - telemetry.addData("left", "%.2f", left); - telemetry.addData("right", "%.2f", right); - telemetry.update(); - - // Pace this loop so jaw action is reasonable speed. - sleep(50); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopTank_Iterative.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopTank_Iterative.java deleted file mode 100644 index a622f27b..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/RobotTeleopTank_Iterative.java +++ /dev/null @@ -1,160 +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.OpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.DcMotor; -import com.qualcomm.robotcore.hardware.Servo; -import com.qualcomm.robotcore.util.Range; - -/* - * This OpMode executes a Tank Drive control TeleOp a direct drive robot - * The code is structured as an Iterative OpMode - * - * In this mode, the left and right joysticks control the left and right motors respectively. - * Pushing a joystick forward will make the attached motor drive forward. - * It raises and lowers the claw using the Gamepad Y and A buttons respectively. - * It also opens and closes the claws slowly using the left and right Bumper buttons. - * - * 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="Robot: Teleop Tank", group="Robot") -@Disabled -public class RobotTeleopTank_Iterative extends OpMode{ - - /* Declare OpMode members. */ - public DcMotor leftDrive = null; - public DcMotor rightDrive = null; - public DcMotor leftArm = null; - public Servo leftClaw = null; - public Servo rightClaw = null; - - double clawOffset = 0; - - public static final double MID_SERVO = 0.5 ; - public static final double CLAW_SPEED = 0.02 ; // sets rate to move servo - public static final double ARM_UP_POWER = 0.50 ; // Run arm motor up at 50% power - public static final double ARM_DOWN_POWER = -0.25 ; // Run arm motor down at -25% power - - /* - * Code to run ONCE when the driver hits INIT - */ - @Override - public void init() { - // Define and Initialize Motors - leftDrive = hardwareMap.get(DcMotor.class, "left_drive"); - rightDrive = hardwareMap.get(DcMotor.class, "right_drive"); - leftArm = hardwareMap.get(DcMotor.class, "left_arm"); - - // To drive forward, most robots need the motor on one side to be reversed, because the axles point in opposite directions. - // Pushing the left and right sticks forward MUST make robot go forward. So adjust these two lines based on your first test drive. - // Note: The settings here assume direct drive on left and right wheels. Gear Reduction or 90 Deg drives may require direction flips - leftDrive.setDirection(DcMotor.Direction.REVERSE); - rightDrive.setDirection(DcMotor.Direction.FORWARD); - - // If there are encoders connected, switch to RUN_USING_ENCODER mode for greater accuracy - // leftDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - // rightDrive.setMode(DcMotor.RunMode.RUN_USING_ENCODER); - - // Define and initialize ALL installed servos. - leftClaw = hardwareMap.get(Servo.class, "left_hand"); - rightClaw = hardwareMap.get(Servo.class, "right_hand"); - leftClaw.setPosition(MID_SERVO); - rightClaw.setPosition(MID_SERVO); - - // Send telemetry message to signify robot waiting; - telemetry.addData(">", "Robot Ready. Press START."); // - } - - /* - * Code to run REPEATEDLY after the driver hits INIT, but before they hit START - */ - @Override - public void init_loop() { - } - - /* - * Code to run ONCE when the driver hits START - */ - @Override - public void start() { - } - - /* - * Code to run REPEATEDLY after the driver hits START but before they hit STOP - */ - @Override - public void loop() { - double left; - double right; - - // Run wheels in tank mode (note: The joystick goes negative when pushed forward, so negate it) - left = -gamepad1.left_stick_y; - right = -gamepad1.right_stick_y; - - leftDrive.setPower(left); - rightDrive.setPower(right); - - // Use gamepad left & right Bumpers to open and close the claw - if (gamepad1.right_bumper) - clawOffset += CLAW_SPEED; - else if (gamepad1.left_bumper) - clawOffset -= CLAW_SPEED; - - // Move both servos to new position. Assume servos are mirror image of each other. - clawOffset = Range.clip(clawOffset, -0.5, 0.5); - leftClaw.setPosition(MID_SERVO + clawOffset); - rightClaw.setPosition(MID_SERVO - clawOffset); - - // Use gamepad buttons to move the arm up (Y) and down (A) - if (gamepad1.y) - leftArm.setPower(ARM_UP_POWER); - else if (gamepad1.a) - leftArm.setPower(ARM_DOWN_POWER); - else - leftArm.setPower(0.0); - - // Send telemetry message to signify robot running; - telemetry.addData("claw", "Offset = %.2f", clawOffset); - telemetry.addData("left", "%.2f", left); - telemetry.addData("right", "%.2f", right); - } - - /* - * Code to run ONCE after the driver hits STOP - */ - @Override - public void stop() { - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SampleRevBlinkinLedDriver.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SampleRevBlinkinLedDriver.java deleted file mode 100644 index bcf5b80e..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SampleRevBlinkinLedDriver.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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; - -/* - * This OpMode demonstrates use of the 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/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java deleted file mode 100644 index 405da1e9..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMU.java +++ /dev/null @@ -1,186 +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.bosch.BNO055IMU; -import com.qualcomm.hardware.bosch.JustLoggingAccelerationIntegrator; -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; -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.Position; -import org.firstinspires.ftc.robotcore.external.navigation.Velocity; - -import java.util.Locale; - -/* - * This OpMode gives a short demo on how to use the BNO055 Inertial Motion Unit (IMU) from AdaFruit. - * - * Note: this is a Legacy example that will not work with newer Control/Expansion Hubs that use a different IMU - * Please use the new SensorIMUOrthogonal or SensorIMUNonOrthogonal samples for a more universal IMU interface. - * - * 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 Adafruit IMU - */ -@TeleOp(name = "Sensor: BNO055 IMU", group = "Sensor") -@Disabled // Comment this out to add to the OpMode list -public class SensorBNO055IMU extends LinearOpMode - { - //---------------------------------------------------------------------------------------------- - // State - //---------------------------------------------------------------------------------------------- - - // The IMU sensor object - BNO055IMU imu; - - // State used for updating telemetry - Orientation angles; - Acceleration gravity; - - //---------------------------------------------------------------------------------------------- - // Main logic - //---------------------------------------------------------------------------------------------- - - @Override public void runOpMode() { - - // Set up the parameters with which we will use our IMU. Note that integration - // algorithm here just reports accelerations to the logcat log; it doesn't actually - // provide positional information. - BNO055IMU.Parameters parameters = new BNO055IMU.Parameters(); - parameters.angleUnit = BNO055IMU.AngleUnit.DEGREES; - parameters.accelUnit = BNO055IMU.AccelUnit.METERS_PERSEC_PERSEC; - parameters.calibrationDataFile = "BNO055IMUCalibration.json"; // see the calibration sample OpMode - parameters.loggingEnabled = true; - parameters.loggingTag = "IMU"; - parameters.accelerationIntegrationAlgorithm = new JustLoggingAccelerationIntegrator(); - - // Retrieve and initialize the IMU. We expect the IMU to be attached to an I2C port - // on a Core Device Interface Module, configured to be a sensor of type "AdaFruit IMU", - // and named "imu". - imu = hardwareMap.get(BNO055IMU.class, "imu"); - imu.initialize(parameters); - - // Set up our telemetry dashboard - composeTelemetry(); - - // Wait until we're told to go - waitForStart(); - - // Start the logging of measured acceleration - imu.startAccelerationIntegration(new Position(), new Velocity(), 1000); - - // Loop and update the dashboard - while (opModeIsActive()) { - telemetry.update(); - } - } - - //---------------------------------------------------------------------------------------------- - // Telemetry Configuration - //---------------------------------------------------------------------------------------------- - - void composeTelemetry() { - - // At the beginning of each telemetry update, grab a bunch of data - // from the IMU that we will then display in separate lines. - telemetry.addAction(new Runnable() { @Override public void run() - { - // Acquiring the angles is relatively expensive; we don't want - // to do that in each of the three items that need that info, as that's - // three times the necessary expense. - angles = imu.getAngularOrientation(AxesReference.INTRINSIC, AxesOrder.ZYX, AngleUnit.DEGREES); - gravity = imu.getGravity(); - } - }); - - telemetry.addLine() - .addData("status", new Func() { - @Override public String value() { - return imu.getSystemStatus().toShortString(); - } - }) - .addData("calib", new Func() { - @Override public String value() { - return imu.getCalibrationStatus().toString(); - } - }); - - telemetry.addLine() - .addData("heading", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.firstAngle); - } - }) - .addData("roll", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.secondAngle); - } - }) - .addData("pitch", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.thirdAngle); - } - }); - - telemetry.addLine() - .addData("grvty", new Func() { - @Override public String value() { - return gravity.toString(); - } - }) - .addData("mag", new Func() { - @Override public String value() { - return String.format(Locale.getDefault(), "%.3f", - Math.sqrt(gravity.xAccel*gravity.xAccel - + gravity.yAccel*gravity.yAccel - + gravity.zAccel*gravity.zAccel)); - } - }); - } - - //---------------------------------------------------------------------------------------------- - // Formatting - //---------------------------------------------------------------------------------------------- - - String formatAngle(AngleUnit angleUnit, double angle) { - return formatDegrees(AngleUnit.DEGREES.fromUnit(angleUnit, angle)); - } - - String formatDegrees(double degrees){ - return String.format(Locale.getDefault(), "%.1f", AngleUnit.DEGREES.normalize(degrees)); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMUCalibration.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMUCalibration.java deleted file mode 100644 index 93f1789d..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorBNO055IMUCalibration.java +++ /dev/null @@ -1,230 +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.bosch.BNO055IMU; -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.ReadWriteFile; -import org.firstinspires.ftc.robotcore.external.Func; -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.internal.system.AppUtil; - -import java.io.File; -import java.util.Locale; - -/* - * This OpMode calibrates a BNO055 IMU per - * "Section 3.11 Calibration" of the BNO055 specification. - * - * Note: this is a Legacy example that will not work with newer Control/Expansion Hubs that use a different IMU - * Please use the new SensorIMUOrthogonal or SensorIMUNonOrthogonal samples for a more universal IMU interface. - * - * Manual calibration of the IMU is definitely NOT necessary: except for the magnetometer (which is not used by the - * default "IMU" SensorMode), the BNO055 is internally self-calibrating and thus can be very successfully used without - * manual intervention. That said, performing a one-time calibration, saving the results persistently, then loading them - * again at each run can help reduce the time that automatic calibration requires. - * - * This summary of the calibration process from Intel is informative: - * http://iotdk.intel.com/docs/master/upm/classupm_1_1_b_n_o055.html - * - * "This device requires calibration in order to operate accurately. [...] Calibration data is - * lost on a power cycle. See one of the examples for a description of how to calibrate the device, - * but in essence: - * - * There is a calibration status register available [...] that returns the calibration status - * of the accelerometer (ACC), magnetometer (MAG), gyroscope (GYR), and overall system (SYS). - * Each of these values range from 0 (uncalibrated) to 3 (fully calibrated). Calibration [ideally] - * involves certain motions to get all 4 values at 3. The motions are as follows (though see the - * datasheet for more information): - * - * 1. GYR: Simply let the sensor sit flat for a few seconds. - * 2. ACC: Move the sensor in various positions. Start flat, then rotate slowly by 45 - * degrees, hold for a few seconds, then continue rotating another 45 degrees and - * hold, etc. 6 or more movements of this type may be required. You can move through - * any axis you desire, but make sure that the device is lying at least once - * perpendicular to the x, y, and z axis. - * 3. MAG: Move slowly in a figure 8 pattern in the air, until the calibration values reaches 3. - * 4. SYS: This will usually reach 3 when the other items have also reached 3. If not, continue - * slowly moving the device though various axes until it does." - * - * To calibrate the IMU, run this sample OpMode with a gamepad attached to the driver station. - * Once the IMU has reached sufficient calibration as reported on telemetry, press the 'A' - * button on the gamepad to write the calibration to a file. That file can then be indicated - * later when running an OpMode which uses the IMU. - * - * Note: if your intended uses of the IMU do not include use of all its sensors (for example, - * you might not use the magnetometer), then it makes little sense for you to wait for full - * calibration of the sensors you are not using before saving the calibration data. Indeed, - * it appears that in a SensorMode that doesn't use the magnetometer (for example), the - * magnetometer cannot actually be calibrated. - * - * References: - * The AdafruitBNO055IMU Javadoc - * The BNO055IMU.Parameters.calibrationDataFile Javadoc - * The BNO055 product page: https://www.bosch-sensortec.com/bst/products/all_products/bno055 - * The BNO055 datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bno055-ds000.pdf - */ -@TeleOp(name = "Sensor: BNO055 IMU Calibration", group = "Sensor") -@Disabled // Uncomment this to add to the OpMode list -public class SensorBNO055IMUCalibration extends LinearOpMode - { - //---------------------------------------------------------------------------------------------- - // State - //---------------------------------------------------------------------------------------------- - - // Our sensors, motors, and other devices go here, along with other long term state - BNO055IMU imu; - - // State used for updating telemetry - Orientation angles; - - //---------------------------------------------------------------------------------------------- - // Main logic - //---------------------------------------------------------------------------------------------- - - @Override public void runOpMode() { - - telemetry.log().setCapacity(12); - telemetry.log().add(""); - telemetry.log().add("Please refer to the calibration instructions"); - telemetry.log().add("contained in the Adafruit IMU calibration"); - telemetry.log().add("sample OpMode."); - telemetry.log().add(""); - telemetry.log().add("When sufficient calibration has been reached,"); - telemetry.log().add("press the 'A' button to write the current"); - telemetry.log().add("calibration data to a file."); - telemetry.log().add(""); - - // We are expecting the IMU to be attached to an I2C port on a Core Device Interface Module and named "imu". - BNO055IMU.Parameters parameters = new BNO055IMU.Parameters(); - parameters.loggingEnabled = true; - parameters.loggingTag = "IMU"; - imu = hardwareMap.get(BNO055IMU.class, "imu"); - imu.initialize(parameters); - - composeTelemetry(); - telemetry.log().add("Waiting for start..."); - - // Wait until we're told to go - while (!isStarted()) { - telemetry.update(); - idle(); - } - - telemetry.log().add("...started..."); - - while (opModeIsActive()) { - - if (gamepad1.a) { - - // Get the calibration data - BNO055IMU.CalibrationData calibrationData = imu.readCalibrationData(); - - // Save the calibration data to a file. You can choose whatever file - // name you wish here, but you'll want to indicate the same file name - // when you initialize the IMU in an OpMode in which it is used. If you - // have more than one IMU on your robot, you'll of course want to use - // different configuration file names for each. - String filename = "AdafruitIMUCalibration.json"; - File file = AppUtil.getInstance().getSettingsFile(filename); - ReadWriteFile.writeFile(file, calibrationData.serialize()); - telemetry.log().add("saved to '%s'", filename); - - // Wait for the button to be released - while (gamepad1.a) { - telemetry.update(); - idle(); - } - } - - telemetry.update(); - } - } - - void composeTelemetry() { - - // At the beginning of each telemetry update, grab a bunch of data - // from the IMU that we will then display in separate lines. - telemetry.addAction(new Runnable() { @Override public void run() - { - // Acquiring the angles is relatively expensive; we don't want - // to do that in each of the three items that need that info, as that's - // three times the necessary expense. - angles = imu.getAngularOrientation(AxesReference.INTRINSIC, AxesOrder.ZYX, AngleUnit.DEGREES); - } - }); - - telemetry.addLine() - .addData("status", new Func() { - @Override public String value() { - return imu.getSystemStatus().toShortString(); - } - }) - .addData("calib", new Func() { - @Override public String value() { - return imu.getCalibrationStatus().toString(); - } - }); - - telemetry.addLine() - .addData("heading", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.firstAngle); - } - }) - .addData("roll", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.secondAngle); - } - }) - .addData("pitch", new Func() { - @Override public String value() { - return formatAngle(angles.angleUnit, angles.thirdAngle); - } - }); - } - - //---------------------------------------------------------------------------------------------- - // Formatting - //---------------------------------------------------------------------------------------------- - - String formatAngle(AngleUnit angleUnit, double angle) { - return formatDegrees(AngleUnit.DEGREES.fromUnit(angleUnit, angle)); - } - - String formatDegrees(double degrees){ - return String.format(Locale.getDefault(), "%.1f", AngleUnit.DEGREES.normalize(degrees)); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java deleted file mode 100644 index 7546c9de..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorColor.java +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright (c) 2017-2020 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.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.DistanceSensor; -import com.qualcomm.robotcore.hardware.NormalizedColorSensor; -import com.qualcomm.robotcore.hardware.NormalizedRGBA; -import com.qualcomm.robotcore.hardware.SwitchableLight; -import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; - -/* - * This OpMode shows how to use a color sensor in a generic - * way, regardless of which particular make or model of color sensor is used. The OpMode - * assumes that the color sensor is configured with a name of "sensor_color". - * - * There will be some variation in the values measured depending on the specific sensor you are using. - * - * You can increase the gain (a multiplier to make the sensor report higher values) by holding down - * the A button on the gamepad, and decrease the gain by holding down the B button on the gamepad. - * - * If the color sensor has a light which is controllable from software, you can use the X button on - * the gamepad to toggle the light on and off. The REV sensors don't support this, but instead have - * a physical switch on them to turn the light on and off, beginning with REV Color Sensor V2. - * - * If the color sensor also supports short-range distance measurements (usually via an infrared - * proximity sensor), the reported distance will be written to telemetry. As of September 2020, - * the only color sensors that support this are the ones from REV Robotics. These infrared proximity - * sensor measurements are only useful at very small distances, and are sensitive to ambient light - * and surface reflectivity. You should use a different sensor if you need precise distance measurements. - * - * 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: Color", group = "Sensor") -@Disabled -public class SensorColor extends LinearOpMode { - - /** The colorSensor field will contain a reference to our color sensor hardware object */ - NormalizedColorSensor colorSensor; - - /** The relativeLayout field is used to aid in providing interesting visual feedback - * in this sample application; you probably *don't* need this when you use a color sensor on your - * robot. Note that you won't see anything change on the Driver Station, only on the Robot Controller. */ - View relativeLayout; - - /* - * The runOpMode() method is the root of this OpMode, as it is in all LinearOpModes. - * Our implementation here, though is a bit unusual: we've decided to put all the actual work - * in the runSample() method rather than directly in runOpMode() itself. The reason we do that is - * that in this sample we're changing the background color of the robot controller screen as the - * OpMode runs, and we want to be able to *guarantee* that we restore it to something reasonable - * and palatable when the OpMode ends. The simplest way to do that is to use a try...finally - * block around the main, core logic, and an easy way to make that all clear was to separate - * the former from the latter in separate methods. - */ - @Override public void runOpMode() { - - // Get a reference to the RelativeLayout so we can later 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()); - relativeLayout = ((Activity) hardwareMap.appContext).findViewById(relativeLayoutId); - - try { - runSample(); // actually execute the sample - } finally { - // On the way out, *guarantee* that the background is reasonable. It doesn't actually start off - // as pure white, but it's too much work to dig out what actually was used, and this is good - // enough to at least make the screen reasonable again. - // Set the panel back to the default color - relativeLayout.post(new Runnable() { - public void run() { - relativeLayout.setBackgroundColor(Color.WHITE); - } - }); - } - } - - protected void runSample() { - // You can give the sensor a gain value, will be multiplied by the sensor's raw value before the - // normalized color values are calculated. Color sensors (especially the REV Color Sensor V3) - // can give very low values (depending on the lighting conditions), which only use a small part - // of the 0-1 range that is available for the red, green, and blue values. In brighter conditions, - // you should use a smaller gain than in dark conditions. If your gain is too high, all of the - // colors will report at or near 1, and you won't be able to determine what color you are - // actually looking at. For this reason, it's better to err on the side of a lower gain - // (but always greater than or equal to 1). - float gain = 2; - - // Once per loop, we will update this hsvValues array. The first element (0) will contain the - // hue, the second element (1) will contain the saturation, and the third element (2) will - // contain the value. See http://web.archive.org/web/20190311170843/https://infohost.nmt.edu/tcc/help/pubs/colortheory/web/hsv.html - // for an explanation of HSV color. - final float[] hsvValues = new float[3]; - - // xButtonPreviouslyPressed and xButtonCurrentlyPressed keep track of the previous and current - // state of the X button on the gamepad - boolean xButtonPreviouslyPressed = false; - boolean xButtonCurrentlyPressed = false; - - // Get a reference to our sensor object. It's recommended to use NormalizedColorSensor over - // ColorSensor, because NormalizedColorSensor consistently gives values between 0 and 1, while - // the values you get from ColorSensor are dependent on the specific sensor you're using. - colorSensor = hardwareMap.get(NormalizedColorSensor.class, "sensor_color"); - - // If possible, turn the light on in the beginning (it might already be on anyway, - // we just make sure it is if we can). - if (colorSensor instanceof SwitchableLight) { - ((SwitchableLight)colorSensor).enableLight(true); - } - - // Wait for the start button to be pressed. - waitForStart(); - - // Loop until we are asked to stop - while (opModeIsActive()) { - // Explain basic gain information via telemetry - telemetry.addLine("Hold the A button on gamepad 1 to increase gain, or B to decrease it.\n"); - telemetry.addLine("Higher gain values mean that the sensor will report larger numbers for Red, Green, and Blue, and Value\n"); - - // Update the gain value if either of the A or B gamepad buttons is being held - if (gamepad1.a) { - // Only increase the gain by a small amount, since this loop will occur multiple times per second. - gain += 0.005; - } else if (gamepad1.b && gain > 1) { // A gain of less than 1 will make the values smaller, which is not helpful. - gain -= 0.005; - } - - // Show the gain value via telemetry - telemetry.addData("Gain", gain); - - // Tell the sensor our desired gain value (normally you would do this during initialization, - // not during the loop) - colorSensor.setGain(gain); - - // Check the status of the X button on the gamepad - xButtonCurrentlyPressed = gamepad1.x; - - // If the button state is different than what it was, then act - if (xButtonCurrentlyPressed != xButtonPreviouslyPressed) { - // If the button is (now) down, then toggle the light - if (xButtonCurrentlyPressed) { - if (colorSensor instanceof SwitchableLight) { - SwitchableLight light = (SwitchableLight)colorSensor; - light.enableLight(!light.isLightOn()); - } - } - } - xButtonPreviouslyPressed = xButtonCurrentlyPressed; - - // Get the normalized colors from the sensor - NormalizedRGBA colors = colorSensor.getNormalizedColors(); - - /* Use telemetry to display feedback on the driver station. We show the red, green, and blue - * normalized values from the sensor (in the range of 0 to 1), as well as the equivalent - * HSV (hue, saturation and value) values. See http://web.archive.org/web/20190311170843/https://infohost.nmt.edu/tcc/help/pubs/colortheory/web/hsv.html - * for an explanation of HSV color. */ - - // Update the hsvValues array by passing it to Color.colorToHSV() - Color.colorToHSV(colors.toColor(), hsvValues); - - telemetry.addLine() - .addData("Red", "%.3f", colors.red) - .addData("Green", "%.3f", colors.green) - .addData("Blue", "%.3f", colors.blue); - telemetry.addLine() - .addData("Hue", "%.3f", hsvValues[0]) - .addData("Saturation", "%.3f", hsvValues[1]) - .addData("Value", "%.3f", hsvValues[2]); - telemetry.addData("Alpha", "%.3f", colors.alpha); - - /* If this color sensor also has a distance sensor, display the measured distance. - * Note that the reported distance is only useful at very close range, and is impacted by - * ambient light and surface reflectivity. */ - if (colorSensor instanceof DistanceSensor) { - telemetry.addData("Distance (cm)", "%.3f", ((DistanceSensor) colorSensor).getDistance(DistanceUnit.CM)); - } - - telemetry.update(); - - // Change the Robot Controller's background color to match the color detected by the color sensor. - relativeLayout.post(new Runnable() { - public void run() { - relativeLayout.setBackgroundColor(Color.HSVToColor(hsvValues)); - } - }); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java deleted file mode 100644 index 44c3ca9c..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorDigitalTouch.java +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2024 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.DigitalChannel; - -/* - * This OpMode demonstrates how to use a digital channel. - * - * The OpMode assumes that the digital channel is configured with a name of "digitalTouch". - * - * 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: digital channel", group = "Sensor") -@Disabled -public class SensorDigitalTouch extends LinearOpMode { - DigitalChannel digitalTouch; // Digital channel Object - - @Override - public void runOpMode() { - - // get a reference to our touchSensor object. - digitalTouch = hardwareMap.get(DigitalChannel.class, "digitalTouch"); - - digitalTouch.setMode(DigitalChannel.Mode.INPUT); - telemetry.addData("DigitalTouchSensorExample", "Press start to continue..."); - telemetry.update(); - - // wait for the start button to be pressed. - waitForStart(); - - // while the OpMode is active, loop and read the digital channel. - // Note we use opModeIsActive() as our loop condition because it is an interruptible method. - while (opModeIsActive()) { - - // button is pressed if value returned is LOW or false. - // send the info back to driver station using telemetry function. - if (digitalTouch.getState() == false) { - telemetry.addData("Button", "PRESSED"); - } else { - telemetry.addData("Button", "NOT PRESSED"); - } - - telemetry.update(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHuskyLens.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHuskyLens.java deleted file mode 100644 index af7ca552..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorHuskyLens.java +++ /dev/null @@ -1,160 +0,0 @@ -/* -Copyright (c) 2023 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.dfrobot.HuskyLens; -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.internal.system.Deadline; - -import java.util.concurrent.TimeUnit; - -/* - * This OpMode illustrates how to use the DFRobot HuskyLens. - * - * The HuskyLens is a Vision Sensor with a built-in object detection model. It can - * detect a number of predefined objects and AprilTags in the 36h11 family, can - * recognize colors, and can be trained to detect custom objects. See this website for - * documentation: https://wiki.dfrobot.com/HUSKYLENS_V1.0_SKU_SEN0305_SEN0336 - * - * For detailed instructions on how a HuskyLens is used in FTC, please see this tutorial: - * https://ftc-docs.firstinspires.org/en/latest/devices/huskylens/huskylens.html - * - * This sample illustrates how to detect AprilTags, but can be used to detect other types - * of objects by changing the algorithm. It assumes that the HuskyLens is configured with - * a name of "huskylens". - * - * 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: HuskyLens", group = "Sensor") -@Disabled -public class SensorHuskyLens extends LinearOpMode { - - private final int READ_PERIOD = 1; - - private HuskyLens huskyLens; - - @Override - public void runOpMode() - { - huskyLens = hardwareMap.get(HuskyLens.class, "huskylens"); - - /* - * This sample rate limits the reads solely to allow a user time to observe - * what is happening on the Driver Station telemetry. Typical applications - * would not likely rate limit. - */ - Deadline rateLimit = new Deadline(READ_PERIOD, TimeUnit.SECONDS); - - /* - * Immediately expire so that the first time through we'll do the read. - */ - rateLimit.expire(); - - /* - * Basic check to see if the device is alive and communicating. This is not - * technically necessary here as the HuskyLens class does this in its - * doInitialization() method which is called when the device is pulled out of - * the hardware map. However, sometimes it's unclear why a device reports as - * failing on initialization. In the case of this device, it's because the - * call to knock() failed. - */ - if (!huskyLens.knock()) { - telemetry.addData(">>", "Problem communicating with " + huskyLens.getDeviceName()); - } else { - telemetry.addData(">>", "Press start to continue"); - } - - /* - * The device uses the concept of an algorithm to determine what types of - * objects it will look for and/or what mode it is in. The algorithm may be - * selected using the scroll wheel on the device, or via software as shown in - * the call to selectAlgorithm(). - * - * The SDK itself does not assume that the user wants a particular algorithm on - * startup, and hence does not set an algorithm. - * - * Users, should, in general, explicitly choose the algorithm they want to use - * within the OpMode by calling selectAlgorithm() and passing it one of the values - * found in the enumeration HuskyLens.Algorithm. - * - * Other algorithm choices for FTC might be: OBJECT_RECOGNITION, COLOR_RECOGNITION or OBJECT_CLASSIFICATION. - */ - huskyLens.selectAlgorithm(HuskyLens.Algorithm.TAG_RECOGNITION); - - telemetry.update(); - waitForStart(); - - /* - * Looking for AprilTags per the call to selectAlgorithm() above. A handy grid - * for testing may be found at https://wiki.dfrobot.com/HUSKYLENS_V1.0_SKU_SEN0305_SEN0336#target_20. - * - * Note again that the device only recognizes the 36h11 family of tags out of the box. - */ - while(opModeIsActive()) { - if (!rateLimit.hasExpired()) { - continue; - } - rateLimit.reset(); - - /* - * All algorithms, except for LINE_TRACKING, return a list of Blocks where a - * Block represents the outline of a recognized object along with its ID number. - * ID numbers allow you to identify what the device saw. See the HuskyLens documentation - * referenced in the header comment above for more information on IDs and how to - * assign them to objects. - * - * Returns an empty array if no objects are seen. - */ - HuskyLens.Block[] blocks = huskyLens.blocks(); - telemetry.addData("Block count", blocks.length); - for (int i = 0; i < blocks.length; i++) { - telemetry.addData("Block", blocks[i].toString()); - /* - * Here inside the FOR loop, you could save or evaluate specific info for the currently recognized Bounding Box: - * - blocks[i].width and blocks[i].height (size of box, in pixels) - * - blocks[i].left and blocks[i].top (edges of box) - * - blocks[i].x and blocks[i].y (center location) - * - blocks[i].id (Color ID) - * - * These values have Java type int (integer). - */ - } - - telemetry.update(); - } - } -} \ No newline at end of file diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUNonOrthogonal.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUNonOrthogonal.java deleted file mode 100644 index 70bc8d4a..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUNonOrthogonal.java +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright (c) 2022 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.RevHubOrientationOnRobot; -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.IMU; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.Orientation; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; - -import static com.qualcomm.hardware.rev.RevHubOrientationOnRobot.xyzOrientation; - -/* - * This OpMode shows how to use the new universal IMU interface. This - * interface may be used with the BNO055 IMU or the BHI260 IMU. It assumes that an IMU is configured - * on the robot with the name "imu". - * - * The sample will display the current Yaw, Pitch and Roll of the robot.
- * With the correct orientation parameters selected, pitch/roll/yaw should act as follows: - * Pitch value should INCREASE as the robot is tipped UP at the front. (Rotation about X) - * Roll value should INCREASE as the robot is tipped UP at the left side. (Rotation about Y) - * Yaw value should INCREASE as the robot is rotated Counter Clockwise. (Rotation about Z) - * - * The yaw can be reset (to zero) by pressing the Y button on the gamepad (Triangle on a PS4 controller) - * - * This specific sample DOES NOT assume that the Hub is mounted on one of the three orthogonal - * planes (X/Y, X/Z or Y/Z) OR that the Hub has only been rotated in a range of 90 degree increments. - * - * Note: if your Hub is mounted Orthogonally (on a orthogonal surface, angled at some multiple of - * 90 Degrees) then you should use the simpler SensorIMUOrthogonal sample in this folder. - * - * But... If your Hub is mounted Non-Orthogonally, you must specify one or more rotational angles - * that transform a "Default" Hub orientation into your desired orientation. That is what is - * illustrated here. - * - * 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. - * - * Finally, edit this OpMode to use at least one angle around an axis to orient your Hub. - */ -@TeleOp(name = "Sensor: IMU Non-Orthogonal", group = "Sensor") -@Disabled // Comment this out to add to the OpMode list -public class SensorIMUNonOrthogonal extends LinearOpMode -{ - // The IMU sensor object - IMU imu; - - //---------------------------------------------------------------------------------------------- - // Main logic - //---------------------------------------------------------------------------------------------- - - @Override public void runOpMode() throws InterruptedException { - - // Retrieve and initialize the IMU. - // This sample expects the IMU to be in a REV Hub and named "imu". - imu = hardwareMap.get(IMU.class, "imu"); - - /* Define how the hub is mounted to the robot to get the correct Yaw, Pitch and Roll values. - * - * You can apply up to three axis rotations to orient your Hub according to how it's mounted on the robot. - * - * The starting point for these rotations is the "Default" Hub orientation, which is: - * 1) Hub laying flat on a horizontal surface, with the Printed Logo facing UP - * 2) Rotated such that the USB ports are facing forward on the robot. - * - * If you are using a REV External IMU, the "Default" orientation is the same as for a REV Hub, but instead of - * the USB ports facing forward, the I2C port faces forward. - * - * The order that the rotations are performed matters, so this sample shows doing them in the order X, Y, then Z. - * For specifying non-orthogonal hub mounting orientations, we must temporarily use axes - * defined relative to the Hub itself, instead of the usual Robot Coordinate System axes - * used for the results the IMU gives us. In the starting orientation, the Hub axes are - * aligned with the Robot Coordinate System: - * - * X Axis: Starting at Center of Hub, pointing out towards I2C connectors - * Y Axis: Starting at Center of Hub, pointing out towards USB connectors - * Z Axis: Starting at Center of Hub, pointing Up through LOGO - * - * Positive rotation is defined by right-hand rule with thumb pointing in +ve direction on axis. - * - * Some examples. - * - * ---------------------------------------------------------------------------------------------------------------------------------- - * Example A) Assume that the hub is mounted on a sloped plate at the back of the robot, with the USB ports coming out the top of the hub. - * The plate is tilted UP 60 degrees from horizontal. - * - * To get the "Default" hub into this configuration you would just need a single rotation. - * 1) Rotate the Hub +60 degrees around the X axis to tilt up the front edge. - * 2) No rotation around the Y or Z axes. - * - * So the X,Y,Z rotations would be 60,0,0 - * - * ---------------------------------------------------------------------------------------------------------------------------------- - * Example B) Assume that the hub is laying flat on the chassis, but it has been twisted 30 degrees towards the right front wheel to make - * the USB cable accessible. - * - * To get the "Default" hub into this configuration you would just need a single rotation, but around a different axis. - * 1) No rotation around the X or Y axes. - * 2) Rotate the Hub -30 degrees (Clockwise) around the Z axis, since a positive angle would be Counter Clockwise. - * - * So the X,Y,Z rotations would be 0,0,-30 - * - * ---------------------------------------------------------------------------------------------------------------------------------- - * Example C) Assume that the hub is mounted on a vertical plate on the right side of the robot, with the Logo facing out, and the - * Hub rotated so that the USB ports are facing down 30 degrees towards the back wheels of the robot. - * - * To get the "Default" hub into this configuration will require several rotations. - * 1) Rotate the hub +90 degrees around the X axis to get it standing upright with the logo pointing backwards on the robot - * 2) Next, rotate the hub +90 around the Y axis to get it facing to the right. - * 3) Finally rotate the hub +120 degrees around the Z axis to take the USB ports from vertical to sloping down 30 degrees and - * facing towards the back of the robot. - * - * So the X,Y,Z rotations would be 90,90,120 - */ - - // The next three lines define the desired axis rotations. - // To Do: EDIT these values to match YOUR mounting configuration. - double xRotation = 0; // enter the desired X rotation angle here. - double yRotation = 0; // enter the desired Y rotation angle here. - double zRotation = 0; // enter the desired Z rotation angle here. - - Orientation hubRotation = xyzOrientation(xRotation, yRotation, zRotation); - - // Now initialize the IMU with this mounting orientation - RevHubOrientationOnRobot orientationOnRobot = new RevHubOrientationOnRobot(hubRotation); - imu.initialize(new IMU.Parameters(orientationOnRobot)); - - // Loop and update the dashboard - while (!isStopRequested()) { - telemetry.addData("Hub orientation", "X=%.1f, Y=%.1f, Z=%.1f \n", xRotation, yRotation, zRotation); - - // Check to see if heading reset is requested - if (gamepad1.y) { - telemetry.addData("Yaw", "Resetting\n"); - imu.resetYaw(); - } else { - telemetry.addData("Yaw", "Press Y (triangle) on Gamepad to reset\n"); - } - - // Retrieve Rotational Angles and Velocities - YawPitchRollAngles orientation = imu.getRobotYawPitchRollAngles(); - AngularVelocity angularVelocity = imu.getRobotAngularVelocity(AngleUnit.DEGREES); - - telemetry.addData("Yaw (Z)", "%.2f Deg. (Heading)", orientation.getYaw(AngleUnit.DEGREES)); - telemetry.addData("Pitch (X)", "%.2f Deg.", orientation.getPitch(AngleUnit.DEGREES)); - telemetry.addData("Roll (Y)", "%.2f Deg.\n", orientation.getRoll(AngleUnit.DEGREES)); - telemetry.addData("Yaw (Z) velocity", "%.2f Deg/Sec", angularVelocity.zRotationRate); - telemetry.addData("Pitch (X) velocity", "%.2f Deg/Sec", angularVelocity.xRotationRate); - telemetry.addData("Roll (Y) velocity", "%.2f Deg/Sec", angularVelocity.yRotationRate); - telemetry.update(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUOrthogonal.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUOrthogonal.java deleted file mode 100644 index af4c2028..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorIMUOrthogonal.java +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright (c) 2022 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.RevHubOrientationOnRobot; -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.IMU; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.YawPitchRollAngles; - -/* - * This OpMode shows how to use the new universal IMU interface. This - * interface may be used with the BNO055 IMU or the BHI260 IMU. It assumes that an IMU is configured - * on the robot with the name "imu". - * - * The sample will display the current Yaw, Pitch and Roll of the robot.
- * With the correct orientation parameters selected, pitch/roll/yaw should act as follows: - * Pitch value should INCREASE as the robot is tipped UP at the front. (Rotation about X)
- * Roll value should INCREASE as the robot is tipped UP at the left side. (Rotation about Y)
- * Yaw value should INCREASE as the robot is rotated Counter Clockwise. (Rotation about Z)
- * - * The yaw can be reset (to zero) by pressing the Y button on the gamepad (Triangle on a PS4 controller) - * - * This specific sample assumes that the Hub is mounted on one of the three orthogonal planes - * (X/Y, X/Z or Y/Z) and that the Hub has only been rotated in a range of 90 degree increments. - * - * Note: if your Hub is mounted on a surface angled at some non-90 Degree multiple (like 30) look at - * the alternative SensorIMUNonOrthogonal sample in this folder. - * - * This "Orthogonal" requirement means that: - * - * 1) The Logo printed on the top of the Hub can ONLY be pointing in one of six directions: - * FORWARD, BACKWARD, UP, DOWN, LEFT and RIGHT. - * - * 2) The USB ports can only be pointing in one of the same six directions:
- * FORWARD, BACKWARD, UP, DOWN, LEFT and RIGHT. - * - * So, To fully define how your Hub is mounted to the robot, you must simply specify:
- * logoFacingDirection
- * usbFacingDirection - * - * 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. - * - * Finally, choose the two correct parameters to define how your Hub is mounted and edit this OpMode - * to use those parameters. - */ -@TeleOp(name = "Sensor: IMU Orthogonal", group = "Sensor") -@Disabled // Comment this out to add to the OpMode list -public class SensorIMUOrthogonal extends LinearOpMode -{ - // The IMU sensor object - IMU imu; - - //---------------------------------------------------------------------------------------------- - // Main logic - //---------------------------------------------------------------------------------------------- - - @Override public void runOpMode() throws InterruptedException { - - // Retrieve and initialize the IMU. - // This sample expects the IMU to be in a REV Hub and named "imu". - imu = hardwareMap.get(IMU.class, "imu"); - - /* Define how the hub is mounted on the robot to get the correct Yaw, Pitch and Roll values. - * - * Two input parameters are required to fully specify the Orientation. - * The first parameter specifies the direction the printed logo on the Hub is pointing. - * The second parameter specifies the direction the USB connector on the Hub is pointing. - * All directions are relative to the robot, and left/right is as-viewed from behind the robot. - * - * If you are using a REV 9-Axis IMU, you can use the Rev9AxisImuOrientationOnRobot class instead of the - * RevHubOrientationOnRobot class, which has an I2cPortFacingDirection instead of a UsbFacingDirection. - */ - - /* The next two lines define Hub orientation. - * The Default Orientation (shown) is when a hub is mounted horizontally with the printed logo pointing UP and the USB port pointing FORWARD. - * - * To Do: EDIT these two lines to match YOUR mounting configuration. - */ - RevHubOrientationOnRobot.LogoFacingDirection logoDirection = RevHubOrientationOnRobot.LogoFacingDirection.UP; - RevHubOrientationOnRobot.UsbFacingDirection usbDirection = RevHubOrientationOnRobot.UsbFacingDirection.FORWARD; - - RevHubOrientationOnRobot orientationOnRobot = new RevHubOrientationOnRobot(logoDirection, usbDirection); - - // Now initialize the IMU with this mounting orientation - // Note: if you choose two conflicting directions, this initialization will cause a code exception. - imu.initialize(new IMU.Parameters(orientationOnRobot)); - - // Loop and update the dashboard - while (!isStopRequested()) { - - telemetry.addData("Hub orientation", "Logo=%s USB=%s\n ", logoDirection, usbDirection); - - // Check to see if heading reset is requested - if (gamepad1.y) { - telemetry.addData("Yaw", "Resetting\n"); - imu.resetYaw(); - } else { - telemetry.addData("Yaw", "Press Y (triangle) on Gamepad to reset\n"); - } - - // Retrieve Rotational Angles and Velocities - YawPitchRollAngles orientation = imu.getRobotYawPitchRollAngles(); - AngularVelocity angularVelocity = imu.getRobotAngularVelocity(AngleUnit.DEGREES); - - telemetry.addData("Yaw (Z)", "%.2f Deg. (Heading)", orientation.getYaw(AngleUnit.DEGREES)); - telemetry.addData("Pitch (X)", "%.2f Deg.", orientation.getPitch(AngleUnit.DEGREES)); - telemetry.addData("Roll (Y)", "%.2f Deg.\n", orientation.getRoll(AngleUnit.DEGREES)); - telemetry.addData("Yaw (Z) velocity", "%.2f Deg/Sec", angularVelocity.zRotationRate); - telemetry.addData("Pitch (X) velocity", "%.2f Deg/Sec", angularVelocity.xRotationRate); - telemetry.addData("Roll (Y) velocity", "%.2f Deg/Sec", angularVelocity.yRotationRate); - telemetry.update(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java deleted file mode 100644 index ccc945ff..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorKLNavxMicro.java +++ /dev/null @@ -1,128 +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.kauailabs.NavxMicroNavigationSensor; -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; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.AxesOrder; -import org.firstinspires.ftc.robotcore.external.navigation.AxesReference; -import org.firstinspires.ftc.robotcore.external.navigation.Orientation; - -/* - * This OpMode shows how to use Kauai Labs navX Micro Robotics Navigation - * Sensor. It assumes that the sensor is configured with a name of "navx". - * - * 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: KL navX Micro", group = "Sensor") -@Disabled -public class SensorKLNavxMicro 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 NavxMicroNavigationSensor}, by contrast, provides functionality that - * is unique to the navX Micro sensor. - */ - IntegratingGyroscope gyro; - NavxMicroNavigationSensor navxMicro; - - // A timer helps provide feedback while calibration is taking place - ElapsedTime timer = new ElapsedTime(); - - @Override public void runOpMode() throws InterruptedException { - // Get a reference to a Modern Robotics GyroSensor object. We use several interfaces - // on this object to illustrate which interfaces support which functionality. - navxMicro = hardwareMap.get(NavxMicroNavigationSensor.class, "navx"); - gyro = (IntegratingGyroscope)navxMicro; - // If you're only interested int the IntegratingGyroscope interface, the following will suffice. - // gyro = hardwareMap.get(IntegratingGyroscope.class, "navx"); - - // The gyro automatically starts calibrating. This takes a few seconds. - telemetry.log().add("Gyro Calibrating. Do Not Move!"); - - // Wait until the gyro calibration is complete - timer.reset(); - while (navxMicro.isCalibrating()) { - telemetry.addData("calibrating", "%s", Math.round(timer.seconds())%2==0 ? "|.." : "..|"); - telemetry.update(); - Thread.sleep(50); - } - telemetry.log().clear(); telemetry.log().add("Gyro Calibrated. Press Start."); - telemetry.clear(); telemetry.update(); - - // Wait for the start button to be pressed - waitForStart(); - telemetry.log().clear(); - - while (opModeIsActive()) { - - // Read dimensionalized data from the gyro. This gyro can report angular velocities - // about all three axes. Additionally, it internally integrates the Z axis to - // be able to report an absolute angular Z orientation. - AngularVelocity rates = gyro.getAngularVelocity(AngleUnit.DEGREES); - Orientation angles = gyro.getAngularOrientation(AxesReference.INTRINSIC, AxesOrder.ZYX, AngleUnit.DEGREES); - - telemetry.addLine() - .addData("dx", formatRate(rates.xRotationRate)) - .addData("dy", formatRate(rates.yRotationRate)) - .addData("dz", "%s deg/s", formatRate(rates.zRotationRate)); - - telemetry.addLine() - .addData("heading", formatAngle(angles.angleUnit, angles.firstAngle)) - .addData("roll", formatAngle(angles.angleUnit, angles.secondAngle)) - .addData("pitch", "%s deg", formatAngle(angles.angleUnit, angles.thirdAngle)); - telemetry.update(); - - idle(); // Always call idle() at the bottom of your while(opModeIsActive()) loop - } - } - - String formatRate(float rate) { - return String.format("%.3f", rate); - } - - String formatAngle(AngleUnit angleUnit, double angle) { - return formatDegrees(AngleUnit.DEGREES.fromUnit(angleUnit, angle)); - } - - String formatDegrees(double degrees){ - return String.format("%.1f", AngleUnit.DEGREES.normalize(degrees)); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLimelight3A.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLimelight3A.java deleted file mode 100644 index 6c1f702a..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorLimelight3A.java +++ /dev/null @@ -1,159 +0,0 @@ -/* -Copyright (c) 2024 Limelight Vision - -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.limelightvision.LLResult; -import com.qualcomm.hardware.limelightvision.LLResultTypes; -import com.qualcomm.hardware.limelightvision.LLStatus; -import com.qualcomm.hardware.limelightvision.Limelight3A; -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.Pose3D; - -import java.util.List; - -/* - * This OpMode illustrates how to use the Limelight3A Vision Sensor. - * - * @see Limelight - * - * Notes on configuration: - * - * The device presents itself, when plugged into a USB port on a Control Hub as an ethernet - * interface. A DHCP server running on the Limelight automatically assigns the Control Hub an - * ip address for the new ethernet interface. - * - * Since the Limelight is plugged into a USB port, it will be listed on the top level configuration - * activity along with the Control Hub Portal and other USB devices such as webcams. Typically - * serial numbers are displayed below the device's names. In the case of the Limelight device, the - * Control Hub's assigned ip address for that ethernet interface is used as the "serial number". - * - * Tapping the Limelight's name, transitions to a new screen where the user can rename the Limelight - * and specify the Limelight's ip address. Users should take care not to confuse the ip address of - * the Limelight itself, which can be configured through the Limelight settings page via a web browser, - * and the ip address the Limelight device assigned the Control Hub and which is displayed in small text - * below the name of the Limelight on the top level configuration screen. - */ -@TeleOp(name = "Sensor: Limelight3A", group = "Sensor") -@Disabled -public class SensorLimelight3A extends LinearOpMode { - - private Limelight3A limelight; - - @Override - public void runOpMode() throws InterruptedException - { - limelight = hardwareMap.get(Limelight3A.class, "limelight"); - - telemetry.setMsTransmissionInterval(11); - - limelight.pipelineSwitch(0); - - /* - * Starts polling for data. If you neglect to call start(), getLatestResult() will return null. - */ - limelight.start(); - - telemetry.addData(">", "Robot Ready. Press Play."); - telemetry.update(); - waitForStart(); - - while (opModeIsActive()) { - LLStatus status = limelight.getStatus(); - telemetry.addData("Name", "%s", - status.getName()); - telemetry.addData("LL", "Temp: %.1fC, CPU: %.1f%%, FPS: %d", - status.getTemp(), status.getCpu(),(int)status.getFps()); - telemetry.addData("Pipeline", "Index: %d, Type: %s", - status.getPipelineIndex(), status.getPipelineType()); - - LLResult result = limelight.getLatestResult(); - if (result != null) { - // Access general information - Pose3D botpose = result.getBotpose(); - double captureLatency = result.getCaptureLatency(); - double targetingLatency = result.getTargetingLatency(); - double parseLatency = result.getParseLatency(); - telemetry.addData("LL Latency", captureLatency + targetingLatency); - telemetry.addData("Parse Latency", parseLatency); - telemetry.addData("PythonOutput", java.util.Arrays.toString(result.getPythonOutput())); - - if (result.isValid()) { - telemetry.addData("tx", result.getTx()); - telemetry.addData("txnc", result.getTxNC()); - telemetry.addData("ty", result.getTy()); - telemetry.addData("tync", result.getTyNC()); - - telemetry.addData("Botpose", botpose.toString()); - - // Access barcode results - List barcodeResults = result.getBarcodeResults(); - for (LLResultTypes.BarcodeResult br : barcodeResults) { - telemetry.addData("Barcode", "Data: %s", br.getData()); - } - - // Access classifier results - List classifierResults = result.getClassifierResults(); - for (LLResultTypes.ClassifierResult cr : classifierResults) { - telemetry.addData("Classifier", "Class: %s, Confidence: %.2f", cr.getClassName(), cr.getConfidence()); - } - - // Access detector results - List detectorResults = result.getDetectorResults(); - for (LLResultTypes.DetectorResult dr : detectorResults) { - telemetry.addData("Detector", "Class: %s, Area: %.2f", dr.getClassName(), dr.getTargetArea()); - } - - // Access fiducial results - List fiducialResults = result.getFiducialResults(); - for (LLResultTypes.FiducialResult fr : fiducialResults) { - telemetry.addData("Fiducial", "ID: %d, Family: %s, X: %.2f, Y: %.2f", fr.getFiducialId(), fr.getFamily(),fr.getTargetXDegrees(), fr.getTargetYDegrees()); - } - - // Access color results - List colorResults = result.getColorResults(); - for (LLResultTypes.ColorResult cr : colorResults) { - telemetry.addData("Color", "X: %.2f, Y: %.2f", cr.getTargetXDegrees(), cr.getTargetYDegrees()); - } - } - } else { - telemetry.addData("Limelight", "No data available"); - } - - telemetry.update(); - } - limelight.stop(); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRColor.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRColor.java deleted file mode 100644 index 32b37e09..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRColor.java +++ /dev/null @@ -1,138 +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.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.ColorSensor; - -/* - * - * This OpMode that shows how to use - * a Modern Robotics Color Sensor. - * - * The OpMode 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 - */ -@TeleOp(name = "Sensor: MR Color", group = "Sensor") -@Disabled -public class SensorMRColor 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.get(ColorSensor.class, "sensor_color"); - - // Set the LED in the beginning - colorSensor.enableLed(bLedOn); - - // wait for the start button to be pressed. - waitForStart(); - - // while the OpMode is active, 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 either gamepad. - bCurrState = gamepad1.x; - - // check for button state transitions. - if (bCurrState && (bCurrState != bPrevState)) { - - // button is transitioning to a pressed state. So Toggle LED - bLedOn = !bLedOn; - colorSensor.enableLed(bLedOn); - } - - // update previous state variable. - bPrevState = bCurrState; - - // convert the RGB values to HSV values. - Color.RGBToHSV(colorSensor.red() * 8, colorSensor.green() * 8, colorSensor.blue() * 8, 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/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRGyro.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRGyro.java deleted file mode 100644 index 91c0062e..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRGyro.java +++ /dev/null @@ -1,160 +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.modernrobotics.ModernRoboticsI2cGyro; -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.IntegratingGyroscope; -import com.qualcomm.robotcore.util.ElapsedTime; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.AngularVelocity; -import org.firstinspires.ftc.robotcore.external.navigation.AxesOrder; -import org.firstinspires.ftc.robotcore.external.navigation.AxesReference; - -/* - * This OpMode shows how to use the Modern Robotics Gyro. - * - * The OpMode assumes that the gyro sensor is attached to a Device Interface Module - * I2C channel and 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 -*/ -@TeleOp(name = "Sensor: MR Gyro", group = "Sensor") -@Disabled -public class SensorMRGyro 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 ModernRoboticsI2cGyro}, by contrast, provides functionality that - * is unique to the Modern Robotics gyro sensor. - */ - IntegratingGyroscope gyro; - ModernRoboticsI2cGyro modernRoboticsI2cGyro; - - // A timer helps provide feedback while calibration is taking place - ElapsedTime timer = new ElapsedTime(); - - @Override - public void runOpMode() { - - boolean lastResetState = false; - boolean curResetState = false; - - // Get a reference to a Modern Robotics gyro object. We use several interfaces - // on this object to illustrate which interfaces support which functionality. - modernRoboticsI2cGyro = hardwareMap.get(ModernRoboticsI2cGyro.class, "gyro"); - gyro = (IntegratingGyroscope)modernRoboticsI2cGyro; - // If you're only interested int the IntegratingGyroscope interface, the following will suffice. - // gyro = hardwareMap.get(IntegratingGyroscope.class, "gyro"); - // A similar approach will work for the Gyroscope interface, if that's all you need. - - // Start calibrating the gyro. This takes a few seconds and is worth performing - // during the initialization phase at the start of each OpMode. - telemetry.log().add("Gyro Calibrating. Do Not Move!"); - modernRoboticsI2cGyro.calibrate(); - - // Wait until the gyro calibration is complete - timer.reset(); - while (!isStopRequested() && modernRoboticsI2cGyro.isCalibrating()) { - telemetry.addData("calibrating", "%s", Math.round(timer.seconds())%2==0 ? "|.." : "..|"); - telemetry.update(); - sleep(50); - } - - telemetry.log().clear(); telemetry.log().add("Gyro Calibrated. Press Start."); - telemetry.clear(); telemetry.update(); - - // Wait for the start button to be pressed - waitForStart(); - telemetry.log().clear(); - telemetry.log().add("Press A & B to reset heading"); - - // Loop until we're asked to stop - while (opModeIsActive()) { - - // If the A and B buttons are pressed just now, reset Z heading. - curResetState = (gamepad1.a && gamepad1.b); - if (curResetState && !lastResetState) { - modernRoboticsI2cGyro.resetZAxisIntegrator(); - } - lastResetState = curResetState; - - // The raw() methods report the angular rate of change about each of the - // three axes directly as reported by the underlying sensor IC. - int rawX = modernRoboticsI2cGyro.rawX(); - int rawY = modernRoboticsI2cGyro.rawY(); - int rawZ = modernRoboticsI2cGyro.rawZ(); - int heading = modernRoboticsI2cGyro.getHeading(); - int integratedZ = modernRoboticsI2cGyro.getIntegratedZValue(); - - // Read dimensionalized data from the gyro. This gyro can report angular velocities - // about all three axes. Additionally, it internally integrates the Z axis to - // be able to report an absolute angular Z orientation. - AngularVelocity rates = gyro.getAngularVelocity(AngleUnit.DEGREES); - float zAngle = gyro.getAngularOrientation(AxesReference.INTRINSIC, AxesOrder.ZYX, AngleUnit.DEGREES).firstAngle; - - // Read administrative information from the gyro - int zAxisOffset = modernRoboticsI2cGyro.getZAxisOffset(); - int zAxisScalingCoefficient = modernRoboticsI2cGyro.getZAxisScalingCoefficient(); - - telemetry.addLine() - .addData("dx", formatRate(rates.xRotationRate)) - .addData("dy", formatRate(rates.yRotationRate)) - .addData("dz", "%s deg/s", formatRate(rates.zRotationRate)); - telemetry.addData("angle", "%s deg", formatFloat(zAngle)); - telemetry.addData("heading", "%3d deg", heading); - telemetry.addData("integrated Z", "%3d", integratedZ); - telemetry.addLine() - .addData("rawX", formatRaw(rawX)) - .addData("rawY", formatRaw(rawY)) - .addData("rawZ", formatRaw(rawZ)); - telemetry.addLine().addData("z offset", zAxisOffset).addData("z coeff", zAxisScalingCoefficient); - telemetry.update(); - } - } - - String formatRaw(int rawValue) { - return String.format("%d", rawValue); - } - - String formatRate(float rate) { - return String.format("%.3f", rate); - } - - String formatFloat(float rate) { - return String.format("%.3f", rate); - } - -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMROpticalDistance.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMROpticalDistance.java deleted file mode 100644 index 6d2dfa39..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMROpticalDistance.java +++ /dev/null @@ -1,70 +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.OpticalDistanceSensor; - -/* - * This OpMode shows how to use a Modern Robotics Optical Distance Sensor - * It assumes that the ODS sensor is configured with a name of "sensor_ods". - * - * 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: MR ODS", group = "Sensor") -@Disabled -public class SensorMROpticalDistance extends LinearOpMode { - - OpticalDistanceSensor odsSensor; // Hardware Device Object - - @Override - public void runOpMode() { - - // get a reference to our Light Sensor object. - odsSensor = hardwareMap.get(OpticalDistanceSensor.class, "sensor_ods"); - - // wait for the start button to be pressed. - waitForStart(); - - // while the OpMode 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. - telemetry.addData("Raw", odsSensor.getRawLightDetected()); - telemetry.addData("Normal", odsSensor.getLightDetected()); - - telemetry.update(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java deleted file mode 100644 index 2039ef97..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorMRRangeSensor.java +++ /dev/null @@ -1,70 +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.modernrobotics.ModernRoboticsI2cRangeSensor; -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; - -/* - * This OpMode illustrates how to use the Modern Robotics Range Sensor. - * - * The OpMode 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 MR Range 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 { - - ModernRoboticsI2cRangeSensor rangeSensor; - - @Override public void runOpMode() { - - // get a reference to our compass - rangeSensor = hardwareMap.get(ModernRoboticsI2cRangeSensor.class, "sensor_range"); - - // wait for the start button to be pressed - waitForStart(); - - while (opModeIsActive()) { - telemetry.addData("raw ultrasonic", rangeSensor.rawUltrasonic()); - telemetry.addData("raw optical", rangeSensor.rawOptical()); - telemetry.addData("cm optical", "%.2f cm", rangeSensor.cmOptical()); - telemetry.addData("cm", "%.2f cm", rangeSensor.getDistance(DistanceUnit.CM)); - telemetry.update(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuad.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuad.java deleted file mode 100644 index 81548216..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuad.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2024 DigitalChickenLabs - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.hardware.digitalchickenlabs.OctoQuad; -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.Telemetry; - -/* - * This OpMode illustrates how to use the DigitalChickenLabs OctoQuad Quadrature Encoder & Pulse Width Interface Module - * - * The OctoQuad has 8 input channels that can used to read either Relative Quadrature Encoders or Pulse-Width Absolute Encoder inputs. - * Relative Quadrature encoders are found on most FTC motors, and some stand-alone position sensors like the REV Thru-Bore encoder. - * Pulse-Width encoders are less common. The REV Thru-Bore encoder can provide its absolute position via a variable pulse width, - * as can several sonar rangefinders such as the MaxBotix MB1000 series. - * - * This basic sample shows how an OctoQuad can be used to read the position three Odometry pods fitted - * with REV Thru-Bore encoders. For a more advanced example showing additional OctoQuad capabilities, see the SensorOctoQuadAdv sample. - * - * This OpMode assumes that the OctoQuad is attached to an I2C interface named "octoquad" in the robot configuration. - * - * The code assumes the first three OctoQuad inputs are connected as follows - * - Chan 0: for measuring forward motion on the left side of the robot. - * - Chan 1: for measuring forward motion on the right side of the robot. - * - Chan 2: for measuring Lateral (strafing) motion. - * - * The encoder values may be reset to zero by pressing the X (left most) button on Gamepad 1. - * - * This sample does not show how to interpret these readings, just how to obtain and display them. - * - * 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 the sensor's product page: https://www.tindie.com/products/35114/ - */ -@TeleOp(name = "OctoQuad Basic", group="OctoQuad") -@Disabled -public class SensorOctoQuad extends LinearOpMode { - - // Identify which encoder OctoQuad inputs are connected to each odometry pod. - private final int ODO_LEFT = 0; // Facing forward direction on left side of robot (Axial motion) - private final int ODO_RIGHT = 1; // Facing forward direction on right side or robot (Axial motion) - private final int ODO_PERP = 2; // Facing perpendicular direction at the center of the robot (Lateral motion) - - // Declare the OctoQuad object and members to store encoder positions and velocities - private OctoQuad octoquad; - - private int posLeft; - private int posRight; - private int posPerp; - - /** - * This function is executed when this OpMode is selected from the Driver Station. - */ - @Override - public void runOpMode() { - - // Connect to OctoQuad by referring to its name in the Robot Configuration. - octoquad = hardwareMap.get(OctoQuad.class, "octoquad"); - - // Read the Firmware Revision number from the OctoQuad and display it as telemetry. - telemetry.addData("OctoQuad Firmware Version ", octoquad.getFirmwareVersion()); - - // Reverse the count-direction of any encoder that is not what you require. - // e.g. if you push the robot forward and the left encoder counts down, then reverse it so it counts up. - octoquad.setSingleEncoderDirection(ODO_LEFT, OctoQuad.EncoderDirection.REVERSE); - octoquad.setSingleEncoderDirection(ODO_RIGHT, OctoQuad.EncoderDirection.FORWARD); - octoquad.setSingleEncoderDirection(ODO_PERP, OctoQuad.EncoderDirection.FORWARD); - - // Any changes that are made should be saved in FLASH just in case there is a sensor power glitch. - octoquad.saveParametersToFlash(); - - telemetry.addLine("\nPress START to read encoder values"); - telemetry.update(); - - waitForStart(); - - // Configure the telemetry for optimal display of data. - telemetry.setDisplayFormat(Telemetry.DisplayFormat.MONOSPACE); - telemetry.setMsTransmissionInterval(50); - - // Set all the encoder inputs to zero. - octoquad.resetAllPositions(); - - // Loop while displaying the odometry pod positions. - while (opModeIsActive()) { - telemetry.addData(">", "Press X to Reset Encoders\n"); - - // Check for X button to reset encoders. - if (gamepad1.x) { - // Reset the position of all encoders to zero. - octoquad.resetAllPositions(); - } - - // Read all the encoder data. Load into local members. - readOdometryPods(); - - // Display the values. - telemetry.addData("Left ", "%8d counts", posLeft); - telemetry.addData("Right", "%8d counts", posRight); - telemetry.addData("Perp ", "%8d counts", posPerp); - telemetry.update(); - } - } - - private void readOdometryPods() { - // For best performance, we should only perform ONE transaction with the OctoQuad each cycle. - // Since this example only needs to read positions from a few channels, we could use either - // readPositionRange(idxFirst, idxLast) to get a select number of sequential channels - // or - // readAllPositions() to get all 8 encoder readings - // - // Since both calls take almost the same amount of time, and the actual channels may not end up - // being sequential, we will read all of the encoder positions, and then pick out the ones we need. - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuadAdv.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuadAdv.java deleted file mode 100644 index 2e807ce0..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorOctoQuadAdv.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) 2024 DigitalChickenLabs - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.hardware.digitalchickenlabs.OctoQuad; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.util.ElapsedTime; -import com.qualcomm.robotcore.util.MovingStatistics; -import com.qualcomm.robotcore.eventloop.opmode.Disabled; - - -import org.firstinspires.ftc.robotcore.external.Telemetry; -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; - -import java.util.ArrayList; -import java.util.List; - -/* - * This OpMode illustrates how to use advanced features of the DigitalChickenLabs OctoQuad Quadrature Encoder & Pulse Width Interface Module - * - * The OctoQuad has 8 input channels that can used to read either Quadrature Encoder signals (like with most FTC motors) - * or Pulse-Width style Absolute Encoder inputs (eg: REV Through Bore encoder pulse width output). - * - * This OpMode illustrates several of the more advanced features of an OctoQuad, including Pulse Width measurement and velocity measurement. - * For a more basic OpMode just showing how to read encoder inputs, see the SensorOctoQuad sample. - * - * This OpMode assumes that the OctoQuad is attached to an I2C interface named "octoquad" in the robot configuration. - * - * One system that requires a lot of encoder inputs is a Swerve Drive system. - * Such a drive requires two encoders per drive module: one for position & velocity of the Drive motor/wheel, and one for position/angle of the Steering motor. - * The Drive motor usually requires a quadrature encoder, and the Steering motor requires an Absolute encoder. - * This quantity and combination of encoder inputs is a challenge, but a single OctoQuad could be used to read them all. - * - * This sample will configure an OctoQuad for a swerve drive, as follows - * - Configure 4 Relative Quadrature Encoder inputs and 4 Absolute Pulse-Width Encoder inputs - * - Configure a velocity sample interval of 25 mSec - * - Configure a pulse width input range of 1-1024 uSec for a REV Through Bore Encoder's Absolute Pulse output. - * - * An OctoSwerveDrive class will be created to initialize the OctoQuad, and manage the 4 swerve modules. - * An OctoSwerveModule class will be created to configure and read a single swerve module. - * - * Wiring: - * The OctoQuad will be configured to accept Quadrature encoders on the first four channels and Absolute (pulse width) encoders on the last four channels. - * - * The standard 4-pin to 4-pin cable can be used to connect each Driver Motor encoder to the OctoQuad. (channels 0-3) - * - * A modified version of the REV 6-4 pin cable (shipped with the encoder) connects the steering encoder to the OctoQuad. (channels 4-7) - * To connect the Absolute position signal from a REV Thru-Bore encoder to the OctoQuad, the Provided 6-pin to 4-pin cable will need to be modified. - * At the 6-pin connector end, move the yellow wire from its initial pin-3 position to the ABS pin-5 position. This can be done easily - * by using a small flathead screwdriver to lift the small white tab holding the metal wire crimp in place and gently pulling the wire out. - * See the OctoSwerveDrive() constructor below for the correct wheel/channel assignment. - * - * 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 - * - * Note: If you prefer, you can move the two support classes from this file, and place them in their own files. - * But leaving them in place is simpler for this example. - * - * See the sensor's product page: https://www.tindie.com/products/35114/ - */ -@TeleOp(name="OctoQuad Advanced", group="OctoQuad") -@Disabled -public class SensorOctoQuadAdv extends LinearOpMode { - - @Override - public void runOpMode() throws InterruptedException { - // Connect to the OctoQuad by looking up its name in the hardwareMap. - OctoQuad octoquad = hardwareMap.get(OctoQuad.class, "octoquad"); - - // Create the interface for the Swerve Drive Encoders - OctoSwerveDrive octoSwerveDrive = new OctoSwerveDrive(octoquad); - - // Display the OctoQuad firmware revision - telemetry.addLine("OctoQuad Firmware v" + octoquad.getFirmwareVersion()); - telemetry.addLine("\nPress START to read encoder values"); - telemetry.update(); - - waitForStart(); - - // Configure the telemetry for optimal display of data. - telemetry.setDisplayFormat(Telemetry.DisplayFormat.MONOSPACE); - telemetry.setMsTransmissionInterval(50); - - // Run stats to determine cycle times. - MovingStatistics avgTime = new MovingStatistics(100); - ElapsedTime elapsedTime = new ElapsedTime(); - - while (opModeIsActive()) { - telemetry.addData(">", "Press X to Reset Encoders\n"); - - if(gamepad1.x) { - octoquad.resetAllPositions(); - } - - // read all the swerve drive encoders and update positions and velocities. - octoSwerveDrive.updateModules(); - octoSwerveDrive.show(telemetry); - - // Update cycle time stats - avgTime.add(elapsedTime.nanoseconds()); - elapsedTime.reset(); - - telemetry.addData("Loop time", "%.1f mS", avgTime.getMean()/1000000); - telemetry.update(); - } - } -} - -// ============================ Internal (Inner) Classes ============================= - -/*** - * OctoSwerveDrive class manages 4 Swerve Modules - * - Performs general OctoQuad initialization - * - Creates 4 module classes, one for each swerve module - * - Updates swerve drive status by reading all data from OctoQuad and Updating each module - * - Displays all swerve drive data as telemetry - */ -class OctoSwerveDrive { - - private final OctoQuad octoquad; - private final List allModules = new ArrayList<>(); - - // members to hold encoder data for each module. - public final OctoSwerveModule LeftFront; - public final OctoSwerveModule RightFront; - public final OctoSwerveModule LeftBack; - public final OctoSwerveModule RightBack; - - // Prepare an object to hold an entire OctoQuad encoder readable register bank (pos and vel) - private final OctoQuad.EncoderDataBlock encoderDataBlock = new OctoQuad.EncoderDataBlock(); - - public OctoSwerveDrive(OctoQuad octoquad) { - this.octoquad = octoquad; - - // Clear out all prior settings and encoder data before setting up desired configuration - octoquad.resetEverything(); - - // Assume first 4 channels are relative encoders and the next 4 are absolute encoders - octoquad.setChannelBankConfig(OctoQuad.ChannelBankConfig.BANK1_QUADRATURE_BANK2_PULSE_WIDTH); - - // Create the four OctoSwerveModules, and add them to a 'list' for easier reference. - - // Note: The wheel/channel order is set here. Ensure your encoder cables match. - // - // Note: The angleOffset must be set for each module so a forward facing wheel shows a steer angle of 0 degrees. - // The process for determining the correct angleOffsets is as follows: - // 1) Set all the angleValues (below) to zero then build and deploy the code. - // 2) Physically rotate all the swerve drives so the wheels are facing forward in the desired 0 degree position - // 3) Run the OpMode, view the telemetry and record the "Degrees" value for each module. - // 4) Update the code by entering the recorded Degrees value for each module as the angleOffset (last) parameter in the lines below. - // - // Rebuild and deploy the new code. Verify that the telemetry now indicates 0 degrees when the wheels are facing forward. - // Also verify that the correct module values change appropriately when you manually spin (drive) and rotate (steer) a wheel. - - allModules.add(LeftFront = new OctoSwerveModule(octoquad, "LF ",0,0));// Drive = 0, Steer = 4 - allModules.add(RightFront = new OctoSwerveModule(octoquad, "RF ",1,0));// Drive = 1, Steer = 5 - allModules.add(LeftBack = new OctoSwerveModule(octoquad, "LB ",2,0));// Drive = 2, Steer = 6 - allModules.add(RightBack = new OctoSwerveModule(octoquad, "RB ",3,0));// Drive = 3, Steer = 7 - - // now make sure the settings persist through any power glitches. - octoquad.saveParametersToFlash(); - } - - /** - * Updates all 4 swerve modules - */ - public void updateModules() { - // Read full OctoQuad data block and then pass DataBlock to each swerve module to update themselves. - octoquad.readAllEncoderData(encoderDataBlock); - for (OctoSwerveModule module : allModules) { - module.updateModule(encoderDataBlock); - } - } - - /** - * Generate telemetry data for all modules. - * @param telemetry OpMode Telemetry object - */ - public void show(Telemetry telemetry) { - // create general header block and then have each module add its own telemetry - telemetry.addData("pos", " Count CPS Degree DPS"); - for (OctoSwerveModule module : allModules) { - module.show(telemetry); - } - } -} - -/*** - * The OctoSwerveModule class manages a single swerve module - */ -class OctoSwerveModule { - - public double driveCounts; - public double driveCountsPerSec; - public double steerDegrees; - public double steerDegreesPerSec; - - private final String name; - private final int channel; - private final double angleOffset; - private final double steerDirMult; - - private static final int VELOCITY_SAMPLE_INTERVAL_MS = 25; // To provide 40 updates per second. - private static final double DEGREES_PER_US = (360.0 / 1024.0); // based on REV Through Bore Encoder - private static final double VELOCITY_SAMPLES_PER_S = (1000.0 / VELOCITY_SAMPLE_INTERVAL_MS); - - // The correct drive and turn directions must be set for the Swerve Module based on the specific hardware geometry. - // Forward motion must generate an increasing drive count. - // Counter Clockwise steer rotation must generate an increasing Steer Angle (degrees) - private static final boolean INVERT_DRIVE_ENCODER = false; // Set true if forward motion decreases drive "Count" - private static final boolean INVERT_STEER_ENCODER = false; // Set true if counter clockwise steer action decreases steer "Degree" - - /*** - * @param octoquad provide access to configure OctoQuad - * @param name name used for telemetry display - * @param quadChannel Quadrature encoder channel. Pulse Width channel is this + 4 - * @param angleOffset Angle to subtract from absolute encoder to calibrate zero position. (see comments above) - */ - public OctoSwerveModule (OctoQuad octoquad, String name, int quadChannel, double angleOffset) { - this.name = name; - this.channel = quadChannel; - this.angleOffset = angleOffset; - this.steerDirMult = INVERT_STEER_ENCODER ? -1 : 1 ; // create a multiplier to flip the steer angle. - - // Set the drive encoder direction. Note the absolute encoder does not have built-in direction inversion. - octoquad.setSingleEncoderDirection(channel, INVERT_DRIVE_ENCODER ? OctoQuad.EncoderDirection.REVERSE : OctoQuad.EncoderDirection.FORWARD); - - // Set the velocity sample interval on both encoders - octoquad.setSingleVelocitySampleInterval(channel, VELOCITY_SAMPLE_INTERVAL_MS); - octoquad.setSingleVelocitySampleInterval(channel + 4, VELOCITY_SAMPLE_INTERVAL_MS); - - // Setup Absolute encoder pulse range to match REV Through Bore encoder. - octoquad.setSingleChannelPulseWidthParams (channel + 4, new OctoQuad.ChannelPulseWidthParams(1,1024)); - } - - /*** - * Calculate the Swerve module's position and velocity values - * @param encoderDataBlock most recent full data block read from OctoQuad. - */ - public void updateModule(OctoQuad.EncoderDataBlock encoderDataBlock) { - driveCounts = encoderDataBlock.positions[channel]; // get Counts. - driveCountsPerSec = encoderDataBlock.velocities[channel] * VELOCITY_SAMPLES_PER_S; // convert counts/interval to counts/sec - - // convert uS to degrees. Add in any possible direction flip. - steerDegrees = AngleUnit.normalizeDegrees((encoderDataBlock.positions[channel+ 4] * DEGREES_PER_US * steerDirMult) - angleOffset); - // convert uS/interval to deg per sec. Add in any possible direction flip. - steerDegreesPerSec = encoderDataBlock.velocities[channel + 4] * DEGREES_PER_US * steerDirMult * VELOCITY_SAMPLES_PER_S; - } - - /** - * Display the Swerve module's state as telemetry - * @param telemetry OpMode Telemetry object - */ - public void show(Telemetry telemetry) { - telemetry.addData(name, "%8.0f %7.0f %7.0f %6.0f", driveCounts, driveCountsPerSec, steerDegrees, steerDegreesPerSec); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREV2mDistance.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREV2mDistance.java deleted file mode 100644 index 13883c34..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorREV2mDistance.java +++ /dev/null @@ -1,87 +0,0 @@ -/* -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.Disabled; -import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; -import com.qualcomm.robotcore.eventloop.opmode.TeleOp; -import com.qualcomm.robotcore.hardware.DistanceSensor; -import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; - -/* - * This OpMode illustrates how to use the REV Robotics 2M Distance Sensor. - * - * The OpMode assumes that the sensor is configured with a name of "sensor_distance". - * - * 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 the sensor's product page: https://www.revrobotics.com/rev-31-1505/ - */ -@TeleOp(name = "Sensor: REV2mDistance", group = "Sensor") -@Disabled -public class SensorREV2mDistance extends LinearOpMode { - - private DistanceSensor sensorDistance; - - @Override - public void runOpMode() { - // you can use this as a regular DistanceSensor. - sensorDistance = hardwareMap.get(DistanceSensor.class, "sensor_distance"); - - // you can also cast this to a Rev2mDistanceSensor if you want to use added - // methods associated with the Rev2mDistanceSensor class. - Rev2mDistanceSensor sensorTimeOfFlight = (Rev2mDistanceSensor) sensorDistance; - - telemetry.addData(">>", "Press start to continue"); - telemetry.update(); - - waitForStart(); - while(opModeIsActive()) { - // generic DistanceSensor methods. - telemetry.addData("deviceName", sensorDistance.getDeviceName() ); - telemetry.addData("range", String.format("%.01f mm", sensorDistance.getDistance(DistanceUnit.MM))); - telemetry.addData("range", String.format("%.01f cm", sensorDistance.getDistance(DistanceUnit.CM))); - telemetry.addData("range", String.format("%.01f m", sensorDistance.getDistance(DistanceUnit.METER))); - telemetry.addData("range", String.format("%.01f in", sensorDistance.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(); - } - } - -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorSparkFunOTOS.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorSparkFunOTOS.java deleted file mode 100644 index 3a25230f..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorSparkFunOTOS.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - SPDX-License-Identifier: MIT - - Copyright (c) 2024 SparkFun Electronics -*/ -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.hardware.sparkfun.SparkFunOTOS; - -import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit; -import org.firstinspires.ftc.robotcore.external.navigation.DistanceUnit; - -/* - * This OpMode illustrates how to use the SparkFun Qwiic Optical Tracking Odometry Sensor (OTOS) - * - * The OpMode assumes that the sensor is configured with a name of "sensor_otos". - * - * 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 the sensor's product page: https://www.sparkfun.com/products/24904 - */ -@TeleOp(name = "Sensor: SparkFun OTOS", group = "Sensor") -@Disabled -public class SensorSparkFunOTOS extends LinearOpMode { - // Create an instance of the sensor - SparkFunOTOS myOtos; - - @Override - public void runOpMode() throws InterruptedException { - // Get a reference to the sensor - myOtos = hardwareMap.get(SparkFunOTOS.class, "sensor_otos"); - - // All the configuration for the OTOS is done in this helper method, check it out! - configureOtos(); - - // Wait for the start button to be pressed - waitForStart(); - - // Loop until the OpMode ends - while (opModeIsActive()) { - // Get the latest position, which includes the x and y coordinates, plus the - // heading angle - SparkFunOTOS.Pose2D pos = myOtos.getPosition(); - - // Reset the tracking if the user requests it - if (gamepad1.y) { - myOtos.resetTracking(); - } - - // Re-calibrate the IMU if the user requests it - if (gamepad1.x) { - myOtos.calibrateImu(); - } - - // Inform user of available controls - telemetry.addLine("Press Y (triangle) on Gamepad to reset tracking"); - telemetry.addLine("Press X (square) on Gamepad to calibrate the IMU"); - telemetry.addLine(); - - // Log the position to the telemetry - telemetry.addData("X coordinate", pos.x); - telemetry.addData("Y coordinate", pos.y); - telemetry.addData("Heading angle", pos.h); - - // Update the telemetry on the driver station - telemetry.update(); - } - } - - private void configureOtos() { - telemetry.addLine("Configuring OTOS..."); - telemetry.update(); - - // Set the desired units for linear and angular measurements. Can be either - // meters or inches for linear, and radians or degrees for angular. If not - // set, the default is inches and degrees. Note that this setting is not - // persisted in the sensor, so you need to set at the start of all your - // OpModes if using the non-default value. - // myOtos.setLinearUnit(DistanceUnit.METER); - myOtos.setLinearUnit(DistanceUnit.INCH); - // myOtos.setAngularUnit(AnguleUnit.RADIANS); - myOtos.setAngularUnit(AngleUnit.DEGREES); - - // Assuming you've mounted your sensor to a robot and it's not centered, - // you can specify the offset for the sensor relative to the center of the - // robot. The units default to inches and degrees, but if you want to use - // different units, specify them before setting the offset! Note that as of - // firmware version 1.0, these values will be lost after a power cycle, so - // you will need to set them each time you power up the sensor. For example, if - // the sensor is mounted 5 inches to the left (negative X) and 10 inches - // forward (positive Y) of the center of the robot, and mounted 90 degrees - // clockwise (negative rotation) from the robot's orientation, the offset - // would be {-5, 10, -90}. These can be any value, even the angle can be - // tweaked slightly to compensate for imperfect mounting (eg. 1.3 degrees). - SparkFunOTOS.Pose2D offset = new SparkFunOTOS.Pose2D(0, 0, 0); - myOtos.setOffset(offset); - - // Here we can set the linear and angular scalars, which can compensate for - // scaling issues with the sensor measurements. Note that as of firmware - // version 1.0, these values will be lost after a power cycle, so you will - // need to set them each time you power up the sensor. They can be any value - // from 0.872 to 1.127 in increments of 0.001 (0.1%). It is recommended to - // first set both scalars to 1.0, then calibrate the angular scalar, then - // the linear scalar. To calibrate the angular scalar, spin the robot by - // multiple rotations (eg. 10) to get a precise error, then set the scalar - // to the inverse of the error. Remember that the angle wraps from -180 to - // 180 degrees, so for example, if after 10 rotations counterclockwise - // (positive rotation), the sensor reports -15 degrees, the required scalar - // would be 3600/3585 = 1.004. To calibrate the linear scalar, move the - // robot a known distance and measure the error; do this multiple times at - // multiple speeds to get an average, then set the linear scalar to the - // inverse of the error. For example, if you move the robot 100 inches and - // the sensor reports 103 inches, set the linear scalar to 100/103 = 0.971 - myOtos.setLinearScalar(1.0); - myOtos.setAngularScalar(1.0); - - // The IMU on the OTOS includes a gyroscope and accelerometer, which could - // have an offset. Note that as of firmware version 1.0, the calibration - // will be lost after a power cycle; the OTOS performs a quick calibration - // when it powers up, but it is recommended to perform a more thorough - // calibration at the start of all your OpModes. Note that the sensor must - // be completely stationary and flat during calibration! When calling - // calibrateImu(), you can specify the number of samples to take and whether - // to wait until the calibration is complete. If no parameters are provided, - // it will take 255 samples and wait until done; each sample takes about - // 2.4ms, so about 612ms total - myOtos.calibrateImu(); - - // Reset the tracking algorithm - this resets the position to the origin, - // but can also be used to recover from some rare tracking errors - myOtos.resetTracking(); - - // After resetting the tracking, the OTOS will report that the robot is at - // the origin. If your robot does not start at the origin, or you have - // another source of location information (eg. vision odometry), you can set - // the OTOS location to match and it will continue to track from there. - SparkFunOTOS.Pose2D currentPosition = new SparkFunOTOS.Pose2D(0, 0, 0); - myOtos.setPosition(currentPosition); - - // Get the hardware and firmware version - SparkFunOTOS.Version hwVersion = new SparkFunOTOS.Version(); - SparkFunOTOS.Version fwVersion = new SparkFunOTOS.Version(); - myOtos.getVersionInfo(hwVersion, fwVersion); - - telemetry.addLine("OTOS configured! Press start to get position data!"); - telemetry.addLine(); - telemetry.addLine(String.format("OTOS Hardware Version: v%d.%d", hwVersion.major, hwVersion.minor)); - telemetry.addLine(String.format("OTOS Firmware Version: v%d.%d", fwVersion.major, fwVersion.minor)); - telemetry.update(); - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorTouch.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorTouch.java deleted file mode 100644 index 3d794472..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/SensorTouch.java +++ /dev/null @@ -1,78 +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 OpMode demonstrates how to use a REV Robotics Touch Sensor, REV Robotics Magnetic Limit Switch, or other device - * that implements the TouchSensor interface. Any touch sensor that connects its output to ground when pressed - * (known as "active low") can be configured as a "REV Touch Sensor". This includes REV's Magnetic Limit Switch. - * - * The OpMode assumes that the touch sensor is configured with a name of "sensor_touch". - * - * A REV Robotics Touch Sensor must be configured on digital port number 1, 3, 5, or 7. - * A Magnetic Limit Switch can be configured on any digital port. - * - * 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: REV touch sensor", group = "Sensor") -@Disabled -public class SensorTouch extends LinearOpMode { - TouchSensor touchSensor; // Touch sensor Object - - @Override - public void runOpMode() { - - // get a reference to our touchSensor object. - touchSensor = hardwareMap.get(TouchSensor.class, "sensor_touch"); - - // wait for the start button to be pressed. - waitForStart(); - - // while the OpMode is active, loop and read whether the sensor is being pressed. - // 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 Sensor", "Is Pressed"); - } else { - telemetry.addData("Touch Sensor", "Is Not Pressed"); - } - - telemetry.update(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityCameraFrameCapture.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityCameraFrameCapture.java deleted file mode 100644 index 69420cca..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityCameraFrameCapture.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2023 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.util.Size; -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.hardware.camera.BuiltinCameraDirection; -import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; -import org.firstinspires.ftc.vision.VisionPortal; - -import java.util.Locale; - -/* - * This OpMode helps calibrate a webcam or RC phone camera, useful for AprilTag pose estimation - * with the FTC VisionPortal. It captures a camera frame (image) and stores it on the Robot Controller - * (Control Hub or RC phone), with each press of the gamepad button X (or Square). - * Full calibration instructions are here: - * - * https://ftc-docs.firstinspires.org/camera-calibration - * - * In Android Studio, copy this class into your "teamcode" folder with a new name. - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list. - * - * In OnBot Java, use "Add File" to add this OpMode from the list of Samples. - */ - -@TeleOp(name = "Utility: Camera Frame Capture", group = "Utility") -@Disabled -public class UtilityCameraFrameCapture extends LinearOpMode -{ - /* - * EDIT THESE PARAMETERS AS NEEDED - */ - final boolean USING_WEBCAM = false; - final BuiltinCameraDirection INTERNAL_CAM_DIR = BuiltinCameraDirection.BACK; - final int RESOLUTION_WIDTH = 640; - final int RESOLUTION_HEIGHT = 480; - - // Internal state - boolean lastX; - int frameCount; - long capReqTime; - - @Override - public void runOpMode() - { - VisionPortal portal; - - if (USING_WEBCAM) - { - portal = new VisionPortal.Builder() - .setCamera(hardwareMap.get(WebcamName.class, "Webcam 1")) - .setCameraResolution(new Size(RESOLUTION_WIDTH, RESOLUTION_HEIGHT)) - .build(); - } - else - { - portal = new VisionPortal.Builder() - .setCamera(INTERNAL_CAM_DIR) - .setCameraResolution(new Size(RESOLUTION_WIDTH, RESOLUTION_HEIGHT)) - .build(); - } - - while (!isStopRequested()) - { - boolean x = gamepad1.x; - - if (x && !lastX) - { - portal.saveNextFrameRaw(String.format(Locale.US, "CameraFrameCapture-%06d", frameCount++)); - capReqTime = System.currentTimeMillis(); - } - - lastX = x; - - telemetry.addLine("######## Camera Capture Utility ########"); - telemetry.addLine(String.format(Locale.US, " > Resolution: %dx%d", RESOLUTION_WIDTH, RESOLUTION_HEIGHT)); - telemetry.addLine(" > Press X (or Square) to capture a frame"); - telemetry.addData(" > Camera Status", portal.getCameraState()); - - if (capReqTime != 0) - { - telemetry.addLine("\nCaptured Frame!"); - } - - if (capReqTime != 0 && System.currentTimeMillis() - capReqTime > 1000) - { - capReqTime = 0; - } - - telemetry.update(); - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityOctoQuadConfigMenu.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityOctoQuadConfigMenu.java deleted file mode 100644 index a962919f..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/UtilityOctoQuadConfigMenu.java +++ /dev/null @@ -1,812 +0,0 @@ -/* - * Copyright (c) 2024 DigitalChickenLabs - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.firstinspires.ftc.robotcontroller.external.samples; - -import com.qualcomm.hardware.digitalchickenlabs.OctoQuad; -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.Gamepad; - -import org.firstinspires.ftc.robotcore.external.Telemetry; - -import java.util.ArrayList; -import java.util.Stack; - -/* - * This OpMode illustrates how to use the DigitalChickenLabs OctoQuad Quadrature Encoder & Pulse Width Interface Module. - * - * The OctoQuad has 8 input channels that can used to read either Relative Quadrature Encoders or Pulse-Width Absolute Encoder inputs. - * Relative Quadrature encoders are found on most FTC motors, and some stand-alone position sensors like the REV Thru-Bore encoder. - * Pulse-Width encoders are less common. The REV Thru-Bore encoder can provide its absolute position via a variable pulse width, - * as can several sonar rangefinders such as the MaxBotix MB1000 series. - * - * This OpMode assumes that the OctoQuad is attached to an I2C interface named "octoquad" in the robot configuration. - * - * Remove or comment out the @Disabled line to add this OpMode to the Driver Station OpMode list - * - * Select, Init and run the "OctoQuad Configuration Tool" OpMode - * Read the blue User-Interface tips at the top of the telemetry screen. - * Use the UI buttons to navigate the menu and make any desired changes to the OctoQuad configuration. - * Use the Program Settings To FLASH option to make any changes permanent. - * - * See the sensor's product page: https://www.tindie.com/products/digitalchickenlabs/octoquad-8ch-quadrature-pulse-width-decoder/ - */ -@TeleOp(name = "OctoQuad Configuration Tool", group="OctoQuad") -@Disabled -public class UtilityOctoQuadConfigMenu extends LinearOpMode -{ - TelemetryMenu.MenuElement rootMenu = new TelemetryMenu.MenuElement("OctoQuad Config Menu", true); - TelemetryMenu.MenuElement menuHwInfo = new TelemetryMenu.MenuElement("Hardware Information", false); - TelemetryMenu.EnumOption optionI2cResetMode; - TelemetryMenu.EnumOption optionChannelBankConfig; - - TelemetryMenu.MenuElement menuEncoderDirections = new TelemetryMenu.MenuElement("Set Encoder Directions", false); - TelemetryMenu.BooleanOption[] optionsEncoderDirections = new TelemetryMenu.BooleanOption[OctoQuad.NUM_ENCODERS]; - - TelemetryMenu.MenuElement menuVelocityIntervals = new TelemetryMenu.MenuElement("Velocity Measurement Intervals", false); - TelemetryMenu.IntegerOption[] optionsVelocityIntervals = new TelemetryMenu.IntegerOption[OctoQuad.NUM_ENCODERS]; - - TelemetryMenu.MenuElement menuAbsParams = new TelemetryMenu.MenuElement("Abs. Encoder Pulse Width Params", false); - TelemetryMenu.IntegerOption[] optionsAbsParamsMax = new TelemetryMenu.IntegerOption[OctoQuad.NUM_ENCODERS]; - TelemetryMenu.IntegerOption[] optionsAbsParamsMin = new TelemetryMenu.IntegerOption[OctoQuad.NUM_ENCODERS]; - - TelemetryMenu.OptionElement optionProgramToFlash; - TelemetryMenu.OptionElement optionSendToRAM; - - TelemetryMenu.StaticClickableOption optionExit; - - OctoQuad octoquad; - - boolean error = false; - - @Override - public void runOpMode() - { - octoquad = hardwareMap.getAll(OctoQuad.class).get(0); - - if(octoquad.getChipId() != OctoQuad.OCTOQUAD_CHIP_ID) - { - telemetry.addLine("Error: cannot communicate with OctoQuad. Check your wiring and configuration and try again"); - telemetry.update(); - - error = true; - } - else - { - if(octoquad.getFirmwareVersion().maj != OctoQuad.SUPPORTED_FW_VERSION_MAJ) - { - telemetry.addLine("Error: The OctoQuad is running a different major firmware version than this driver was built for. Cannot run configuration tool"); - telemetry.update(); - - error = true; - } - } - - if(error) - { - waitForStart(); - return; - } - - telemetry.addLine("Retrieving current configuration from OctoQuad"); - telemetry.update(); - - optionExit = new TelemetryMenu.StaticClickableOption("Exit configuration menu") - { - @Override - void onClick() // called on OpMode thread - { - requestOpModeStop(); - } - }; - - optionI2cResetMode = new TelemetryMenu.EnumOption("I2C Reset Mode", OctoQuad.I2cRecoveryMode.values(), octoquad.getI2cRecoveryMode()); - optionChannelBankConfig = new TelemetryMenu.EnumOption("Channel Bank Modes", OctoQuad.ChannelBankConfig.values(), octoquad.getChannelBankConfig()); - - menuHwInfo.addChild(new TelemetryMenu.StaticItem("Board Firmware: v" + octoquad.getFirmwareVersion())); - //menuHwInfo.addChild(new TelemetryMenu.StaticItem("Board unique ID: FIXME")); - - for(int i = 0; i < OctoQuad.NUM_ENCODERS; i++) - { - optionsEncoderDirections[i] = new TelemetryMenu.BooleanOption( - String.format("Encoder %d direction", i), - octoquad.getSingleEncoderDirection(i) == OctoQuad.EncoderDirection.REVERSE, - "-", - "+"); - } - menuEncoderDirections.addChildren(optionsEncoderDirections); - - for(int i = 0; i < OctoQuad.NUM_ENCODERS; i++) - { - optionsVelocityIntervals[i] = new TelemetryMenu.IntegerOption( - String.format("Chan %d velocity intvl", i), - OctoQuad.MIN_VELOCITY_MEASUREMENT_INTERVAL_MS, - OctoQuad.MAX_VELOCITY_MEASUREMENT_INTERVAL_MS, - octoquad.getSingleVelocitySampleInterval(i)); - } - menuVelocityIntervals.addChildren(optionsVelocityIntervals); - - for(int i = 0; i < OctoQuad.NUM_ENCODERS; i++) - { - OctoQuad.ChannelPulseWidthParams params = octoquad.getSingleChannelPulseWidthParams(i); - - optionsAbsParamsMax[i] = new TelemetryMenu.IntegerOption( - String.format("Chan %d max pulse length", i), - OctoQuad.MIN_PULSE_WIDTH_US, - OctoQuad.MAX_PULSE_WIDTH_US, - params.max_length_us); - - optionsAbsParamsMin[i] = new TelemetryMenu.IntegerOption( - String.format("Chan %d min pulse length", i), - OctoQuad.MIN_PULSE_WIDTH_US, - OctoQuad.MAX_PULSE_WIDTH_US, - params.min_length_us); - } - menuAbsParams.addChildren(optionsAbsParamsMin); - menuAbsParams.addChildren(optionsAbsParamsMax); - - optionProgramToFlash = new TelemetryMenu.OptionElement() - { - String name = "Program Settings to FLASH"; - long lastClickTime = 0; - - @Override - protected String getDisplayText() - { - if(lastClickTime == 0) - { - return name; - } - else - { - if(System.currentTimeMillis() - lastClickTime < 1000) - { - return name + " **OK**"; - } - else - { - lastClickTime = 0; - return name; - } - } - } - - @Override - void onClick() - { - sendSettingsToRam(); - octoquad.saveParametersToFlash(); - lastClickTime = System.currentTimeMillis(); - } - }; - - optionSendToRAM = new TelemetryMenu.OptionElement() - { - String name = "Send Settings to RAM"; - long lastClickTime = 0; - - @Override - protected String getDisplayText() - { - if(lastClickTime == 0) - { - return name; - } - else - { - if(System.currentTimeMillis() - lastClickTime < 1000) - { - return name + " **OK**"; - } - else - { - lastClickTime = 0; - return name; - } - } - } - - @Override - void onClick() - { - sendSettingsToRam(); - lastClickTime = System.currentTimeMillis(); - } - }; - - rootMenu.addChild(menuHwInfo); - rootMenu.addChild(optionI2cResetMode); - rootMenu.addChild(optionChannelBankConfig); - rootMenu.addChild(menuEncoderDirections); - rootMenu.addChild(menuVelocityIntervals); - rootMenu.addChild(menuAbsParams); - rootMenu.addChild(optionProgramToFlash); - rootMenu.addChild(optionSendToRAM); - rootMenu.addChild(optionExit); - - TelemetryMenu menu = new TelemetryMenu(telemetry, rootMenu); - - while (!isStopRequested()) - { - menu.loop(gamepad1); - telemetry.update(); - sleep(20); - } - } - - void sendSettingsToRam() - { - for(int i = 0; i < OctoQuad.NUM_ENCODERS; i++) - { - octoquad.setSingleEncoderDirection(i, optionsEncoderDirections[i].getValue() ? OctoQuad.EncoderDirection.REVERSE : OctoQuad.EncoderDirection.FORWARD); - octoquad.setSingleVelocitySampleInterval(i, optionsVelocityIntervals[i].getValue()); - - OctoQuad.ChannelPulseWidthParams params = new OctoQuad.ChannelPulseWidthParams(); - params.max_length_us = optionsAbsParamsMax[i].getValue(); - params.min_length_us = optionsAbsParamsMin[i].getValue(); - - octoquad.setSingleChannelPulseWidthParams(i, params); - } - - octoquad.setI2cRecoveryMode((OctoQuad.I2cRecoveryMode) optionI2cResetMode.getValue()); - octoquad.setChannelBankConfig((OctoQuad.ChannelBankConfig) optionChannelBankConfig.getValue()); - } - - /* - * Copyright (c) 2023 OpenFTC Team - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - - public static class TelemetryMenu - { - private final MenuElement root; - private MenuElement currentLevel; - - private boolean dpadUpPrev; - private boolean dpadDnPrev; - private boolean dpadRightPrev; - private boolean dpadLeftPrev; - private boolean xPrev; - private boolean lbPrev; - - private int selectedIdx = 0; - private Stack selectedIdxStack = new Stack<>(); - - private final Telemetry telemetry; - - /** - * TelemetryMenu constructor - * @param telemetry pass in 'telemetry' from your OpMode - * @param root the root menu element - */ - public TelemetryMenu(Telemetry telemetry, MenuElement root) - { - this.root = root; - this.currentLevel = root; - this.telemetry = telemetry; - - telemetry.setDisplayFormat(Telemetry.DisplayFormat.HTML); - telemetry.setMsTransmissionInterval(50); - } - - /** - * Call this from inside your loop to put the current menu state into - * telemetry, and process gamepad inputs for navigating the menu - * @param gamepad the gamepad you want to use to navigate the menu - */ - public void loop(Gamepad gamepad) - { - // Capture current state of the gamepad buttons we care about; - // We can only look once or we risk a race condition - boolean dpadUp = gamepad.dpad_up; - boolean dpadDn = gamepad.dpad_down; - boolean dpadRight = gamepad.dpad_right; - boolean dpadLeft = gamepad.dpad_left; - boolean x = gamepad.x; - boolean lb = gamepad.left_bumper; - - // Figure out who our children our at this level - // and figure out which item is currently highlighted - // with the selection pointer - ArrayList children = currentLevel.children(); - Element currentSelection = children.get(selectedIdx); - - // Left and right are inputs to the selected item (if it's an Option) - if (currentSelection instanceof OptionElement) - { - if (dpadRight && !dpadRightPrev) // rising edge - { - ((OptionElement) currentSelection).onRightInput(); - } - else if (dpadLeft && !dpadLeftPrev) // rising edge - { - ((OptionElement) currentSelection).onLeftInput(); - } - } - - // Up and down navigate the current selection pointer - if (dpadUp && !dpadUpPrev) // rising edge - { - selectedIdx--; // Move selection pointer up - } - else if (dpadDn && !dpadDnPrev) // rising edge - { - selectedIdx++; // Move selection pointer down - } - - // Make selected index sane (don't let it go out of bounds) :eyes: - if (selectedIdx >= children.size()) - { - selectedIdx = children.size()-1; - } - else if (selectedIdx < 0) - { - selectedIdx = 0; - } - - // Select: either enter submenu or input to option - else if (x && !xPrev) // rising edge - { - // Select up element - if (currentSelection instanceof SpecialUpElement) - { - // We can only go up if we're not at the root level - if (currentLevel != root) - { - // Restore selection pointer to where it was before - selectedIdx = selectedIdxStack.pop(); - - // Change to the parent level - currentLevel = currentLevel.parent(); - } - } - // Input to option - else if (currentSelection instanceof OptionElement) - { - ((OptionElement) currentSelection).onClick(); - } - // Enter submenu - else if (currentSelection instanceof MenuElement) - { - // Save our current selection pointer so we can restore it - // later if the user navigates back up a level - selectedIdxStack.push(selectedIdx); - - // We have no idea what's in the submenu :monkey: so best to - // just set the selection pointer to the first element - selectedIdx = 0; - - // Now the current level becomes the submenu that the selection - // pointer was on - currentLevel = (MenuElement) currentSelection; - } - } - - // Go up a level - else if (lb && !lbPrev) - { - // We can only go up if we're not at the root level - if (currentLevel != root) - { - // Restore selection pointer to where it was before - selectedIdx = selectedIdxStack.pop(); - - // Change to the parent level - currentLevel = currentLevel.parent(); - } - } - - // Save the current button states so that we can look for - // the rising edge the next time around the loop :) - dpadUpPrev = dpadUp; - dpadDnPrev = dpadDn; - dpadRightPrev = dpadRight; - dpadLeftPrev = dpadLeft; - xPrev = x; - lbPrev = lb; - - // Start building the text display. - // First, we add the static directions for gamepad operation - StringBuilder builder = new StringBuilder(); - builder.append(""); - builder.append("Navigate items.....dpad up/down\n") - .append("Select.............X or Square\n") - .append("Edit option........dpad left/right\n") - .append("Up one level.......left bumper\n"); - builder.append(""); - builder.append("\n"); - - // Now actually add the menu options. We start by adding the name of the current menu level. - builder.append(""); - builder.append("Current Menu: ").append(currentLevel.name).append("\n"); - - // Now we loop through all the child elements of this level and add them - for (int i = 0; i < children.size(); i++) - { - // If the selection pointer is at this index, put a green dot in the box :) - if (selectedIdx == i) - { - builder.append("[] "); - } - // Otherwise, just put an empty box - else - { - builder.append("[ ] "); - } - - // Figure out who the selection pointer is pointing at :eyes: - Element e = children.get(i); - - // If it's pointing at a submenu, indicate that it's a submenu to the user - // by prefixing "> " to the name. - if (e instanceof MenuElement) - { - builder.append("> "); - } - - // Finally, add the element's name - builder.append(e.getDisplayText()); - - // We musn't forget the newline - builder.append("\n"); - } - - // Don't forget to close the font tag either - builder.append(""); - - // Build the string!!!! :nerd: - String menu = builder.toString(); - - // Add it to telemetry - telemetry.addLine(menu); - } - - public static class MenuElement extends Element - { - private String name; - private ArrayList children = new ArrayList<>(); - - /** - * Create a new MenuElement; may either be the root menu, or a submenu (set isRoot accordingly) - * @param name the name for this menu - * @param isRoot whether this is a root menu, or a submenu - */ - public MenuElement(String name, boolean isRoot) - { - this.name = name; - - // If it's not the root menu, we add the up one level option as the first element - if (!isRoot) - { - children.add(new SpecialUpElement()); - } - } - - /** - * Add a child element to this menu (may either be an Option or another menu) - * @param child the child element to add - */ - public void addChild(Element child) - { - child.setParent(this); - children.add(child); - } - - /** - * Add multiple child elements to this menu (may either be option, or another menu) - * @param children the children to add - */ - public void addChildren(Element[] children) - { - for (Element e : children) - { - e.setParent(this); - this.children.add(e); - } - } - - @Override - protected String getDisplayText() - { - return name; - } - - private ArrayList children() - { - return children; - } - } - - public static abstract class OptionElement extends Element - { - /** - * Override this to get notified when the element is clicked - */ - void onClick() {} - - /** - * Override this to get notified when the element gets a "left edit" input - */ - protected void onLeftInput() {} - - /** - * Override this to get notified when the element gets a "right edit" input - */ - protected void onRightInput() {} - } - - public static class EnumOption extends OptionElement - { - protected int idx = 0; - protected Enum[] e; - protected String name; - - public EnumOption(String name, Enum[] e) - { - this.e = e; - this.name = name; - } - - public EnumOption(String name, Enum[] e, Enum def) - { - this(name, e); - idx = def.ordinal(); - } - - @Override - public void onLeftInput() - { - idx++; - - if(idx > e.length-1) - { - idx = 0; - } - } - - @Override - public void onRightInput() - { - idx--; - - if(idx < 0) - { - idx = e.length-1; - } - } - - @Override - public void onClick() - { - //onRightInput(); - } - - @Override - protected String getDisplayText() - { - return String.format("%s: %s", name, e[idx].name()); - } - - public Enum getValue() - { - return e[idx]; - } - } - - public static class IntegerOption extends OptionElement - { - protected int i; - protected int min; - protected int max; - protected String name; - - public IntegerOption(String name, int min, int max, int def) - { - this.name = name; - this.min = min; - this.max = max; - this.i = def; - } - - @Override - public void onLeftInput() - { - i--; - - if(i < min) - { - i = max; - } - } - - @Override - public void onRightInput() - { - i++; - - if(i > max) - { - i = min; - } - } - - @Override - public void onClick() - { - //onRightInput(); - } - - @Override - protected String getDisplayText() - { - return String.format("%s: %d", name, i); - } - - public int getValue() - { - return i; - } - } - - static class BooleanOption extends OptionElement - { - private String name; - private boolean val = true; - - private String customTrue; - private String customFalse; - - BooleanOption(String name, boolean def) - { - this.name = name; - this.val = def; - } - - BooleanOption(String name, boolean def, String customTrue, String customFalse) - { - this(name, def); - this.customTrue = customTrue; - this.customFalse = customFalse; - } - - @Override - public void onLeftInput() - { - val = !val; - } - - @Override - public void onRightInput() - { - val = !val; - } - - @Override - public void onClick() - { - val = !val; - } - - @Override - protected String getDisplayText() - { - String valStr; - - if(customTrue != null && customFalse != null) - { - valStr = val ? customTrue : customFalse; - } - else - { - valStr = val ? "true" : "false"; - } - - return String.format("%s: %s", name, valStr); - } - - public boolean getValue() - { - return val; - } - } - - /** - * - */ - public static class StaticItem extends OptionElement - { - private String name; - - public StaticItem(String name) - { - this.name = name; - } - - @Override - protected String getDisplayText() - { - return name; - } - } - - public static abstract class StaticClickableOption extends OptionElement - { - private String name; - - public StaticClickableOption(String name) - { - this.name = name; - } - - abstract void onClick(); - - @Override - protected String getDisplayText() - { - return name; - } - } - - private static abstract class Element - { - private MenuElement parent; - - protected void setParent(MenuElement parent) - { - this.parent = parent; - } - - protected MenuElement parent() - { - return parent; - } - - protected abstract String getDisplayText(); - } - - private static class SpecialUpElement extends Element - { - @Override - protected String getDisplayText() - { - return ".. ↰ Up One Level"; - } - } - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md deleted file mode 100644 index 326978de..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/readme.md +++ /dev/null @@ -1,45 +0,0 @@ - -## Caution -No Team-specific code should be placed or modified in this ``.../samples`` folder. - -Samples should be Copied from here, and then Pasted into the team's -[/TeamCode/src/main/java/org/firstinspires/ftc/teamcode](../../../../../../../../../../TeamCode/src/main/java/org/firstinspires/ftc/teamcode) - folder, using the Android Studio cut and paste commands. This automatically changes all file and -class names to be consistent. From there, the sample can be modified to suit the team's needs. - -For more detailed instructions see the /teamcode readme. - -### Naming of Samples - -To gain a better understanding of how the samples are organized, and how to interpret the -naming system, it will help to understand the conventions that were used during their creation. - -These conventions are described (in detail) in the sample_conventions.md file in this folder. - -To summarize: A range of different samples classes will reside in the java/external/samples. -The class names will follow a naming convention which indicates the purpose of each class. -The prefix of the name will be one of the following: - -Basic: This is a minimally functional OpMode used to illustrate the skeleton/structure - of a particular style of OpMode. These are bare bones examples. - -Sensor: This is a Sample OpMode that shows how to use a specific sensor. - It is not intended to drive a functioning robot, it is simply showing the minimal code - required to read and display the sensor values. - -Robot: This is a Sample OpMode that assumes a simple two-motor (differential) drive base. - It may be used to provide a common baseline driving OpMode, or - to demonstrate how a particular sensor or concept can be used to navigate. - -Concept: This is a sample OpMode that illustrates performing a specific function or concept. - These may be complex, but their operation should be explained clearly in the comments, - or the comments should reference an external doc, guide or tutorial. - Each OpMode should try to only demonstrate a single concept so they are easy to - locate based on their name. These OpModes may not produce a drivable robot. - -After the prefix, other conventions will apply: - -* Sensor class names are constructed as: Sensor - Company - Type -* Robot class names are constructed as: Robot - Mode - Action - OpModetype -* Concept class names are constructed as: Concept - Topic - OpModetype - diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md deleted file mode 100644 index e85e6254..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/external/samples/sample_conventions.md +++ /dev/null @@ -1,113 +0,0 @@ -## Sample Class/Opmode conventions -#### V 1.1.0 8/9/2017 - -This document defines the FTC Sample OpMode and Class conventions. - -### OpMode Name - -To gain a better understanding of how the samples are organized, and how to interpret the -naming system, it will help to understand the conventions that were used during their creation. - -To summarize: A range of different samples classes will reside in the java/external/samples. -The class names will follow a naming convention which indicates the purpose of each class. -The prefix of the name will be one of the following: - -Basic: This is a minimally functional OpMode used to illustrate the skeleton/structure - of a particular style of OpMode. These are bare bones examples. - -Sensor: This is a Sample OpMode that shows how to use a specific sensor. - It is not intended to drive a functioning robot, it is simply showing the minimal code - required to read and display the sensor values. - -Robot: This is a Sample OpMode that assumes a simple two-motor (differential) drive base. - It may be used to provide a common baseline driving OpMode, or - to demonstrate how a particular sensor or concept can be used to navigate. - -Concept: This is a sample OpMode that illustrates performing a specific function or concept. - These may be complex, but their operation should be explained clearly in the comments, - or the comments should reference an external doc, guide or tutorial. - Each OpMode should try to only demonstrate a single concept so they are easy to - locate based on their name. These OpModes may not produce a drivable robot. - -Utility: This sample type is provided as a useful tool, or aide, to perform some specific development task. - It is not expected to be something you would include in your own robot code. - To use the tool, comment out the @Disabled annotation and build the App. - Read the comments found in the sample for an explanation of its intended use. - -After the prefix, other conventions will apply: - -* Sensor class names should constructed as: Sensor - Company - Type -* Robot class names should be constructed as: Robot - Mode - Action - OpModetype -* Concept class names should be constructed as: Concept - Topic - OpModetype - -### Sample OpMode Content/Style - -Code is formatted as per the Google Style Guide: - -https://google.github.io/styleguide/javaguide.html - -With “Sensor” and “Hardware” samples, the code should demonstrate the essential function, -and not be embellished with too much additional “clever” code. If a sensor has special -addressing needs, or has a variety of modes or outputs, these should be demonstrated as -simply as possible. - -Special programming methods, or robot control techniques should be reserved for “Concept” Samples, -and where possible, Samples should strive to only demonstrate a single concept, -eg: State machine coding, or a User Menu system, and not combine them into a single “all inclusive” -sample. This will prevent an “all inclusive” Sample being deleted just because one part of it -becomes obsolete. - -### Device Configuration Names - -The following device names are used in the external samples - -** Motors: -left_drive -right_drive -left_arm - -** Servos: -left_hand -right_hand -arm -claw - -** Sensors: -sensor_color -sensor_ir -sensor_light -sensor_ods -sensor_range -sensor_touch -sensor_color_distance -sensor_digital -digin -digout - -** Localization: -compass -gyro -imu -navx - -### Device Object Names - -Device Object names should use the same words as the device’s configuration name, but they -should be re-structured to be a suitable Java variable name. This should keep the same word order, -but adopt the style of beginning with a lower case letter, and then each subsequent word -starting with an upper case letter. - -Eg: from the examples above: tool, leftMotor, rightClawServo, rearLightSensor. - -Note: Sometimes it’s helpful to put the device type first, followed by the variant. -eg: motorLeft and motorRight, but this should only be done if the same word order -is used on the device configuration name. - -### OpMode code Comments - -Sample comments should read like normal code comments, that is, as an explanation of what the -sample code is doing. They should NOT be directives to the user, -like: “insert your joystick code here” as these comments typically aren’t -detailed enough to be useful. They also often get left in the code and become garbage. - -Instead, an example of the joystick code should be shown with a comment describing what it is doing. diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcOpModeRegister.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcOpModeRegister.java deleted file mode 100644 index ceab67db..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcOpModeRegister.java +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2014, 2015 Qualcomm Technologies Inc - -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 Qualcomm Technologies Inc 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 com.qualcomm.robotcore.eventloop.opmode.OpModeManager; -import com.qualcomm.robotcore.eventloop.opmode.OpModeRegister; - -/** - * {@link FtcOpModeRegister} is responsible for registering OpModes for use in an FTC game. - * @see #register(OpModeManager) - */ -public class FtcOpModeRegister implements OpModeRegister { - - /** - * {@link #register(OpModeManager)} is called by the SDK game in order to register - * OpMode classes or instances that will participate in an FTC game. - * - * There are two mechanisms by which an OpMode may be registered. - * - * 1) The preferred method is by means of class annotations in the OpMode itself. - * See, for example the class annotations in {@link org.firstinspires.ftc.robotcontroller.external.samples.ConceptNullOp}. - * - * 2) The other, retired, method is to modify this {@link #register(OpModeManager)} - * method to include explicit calls to OpModeManager.register(). - * This method of modifying this file directly is discouraged, as it - * makes updates to the SDK harder to integrate into your code. - * - * @param manager the object which contains methods for carrying out OpMode registrations - * - * @see com.qualcomm.robotcore.eventloop.opmode.TeleOp - * @see com.qualcomm.robotcore.eventloop.opmode.Autonomous - */ - public void register(OpModeManager manager) { - - /** - * Any manual OpMode class registrations should go here. - */ - } -} diff --git a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java deleted file mode 100644 index 3f1f77ce..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/FtcRobotControllerActivity.java +++ /dev/null @@ -1,845 +0,0 @@ -/* Copyright (c) 2014, 2015 Qualcomm Technologies Inc - -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 Qualcomm Technologies Inc 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.app.ActionBar; -import android.app.Activity; -import android.app.ActivityManager; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; -import android.net.wifi.WifiManager; -import android.os.Bundle; -import android.os.IBinder; -import android.preference.PreferenceManager; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.view.WindowManager; -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.ProgrammingWebHandlers; -import com.google.blocks.ftcrobotcontroller.runtime.BlocksOpMode; -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; -import com.qualcomm.ftccommon.FtcRobotControllerService.FtcRobotControllerBinder; -import com.qualcomm.ftccommon.FtcRobotControllerSettingsActivity; -import com.qualcomm.ftccommon.LaunchActivityConstantsList; -import com.qualcomm.ftccommon.LaunchActivityConstantsList.RequestCode; -import com.qualcomm.ftccommon.Restarter; -import com.qualcomm.ftccommon.UpdateUI; -import com.qualcomm.ftccommon.configuration.EditParameters; -import com.qualcomm.ftccommon.configuration.FtcLoadFileActivity; -import com.qualcomm.ftccommon.configuration.RobotConfigFile; -import com.qualcomm.ftccommon.configuration.RobotConfigFileManager; -import com.qualcomm.ftcrobotcontroller.BuildConfig; -import com.qualcomm.ftcrobotcontroller.R; -import com.qualcomm.hardware.HardwareFactory; -import com.qualcomm.robotcore.eventloop.EventLoopManager; -import com.qualcomm.robotcore.eventloop.opmode.FtcRobotControllerServiceState; -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.robot.Robot; -import com.qualcomm.robotcore.robot.RobotState; -import com.qualcomm.robotcore.util.ClockWarningSource; -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 org.firstinspires.ftc.ftccommon.external.SoundPlayingRobotMonitor; -import org.firstinspires.ftc.ftccommon.internal.AnnotatedHooksClassFilter; -import org.firstinspires.ftc.ftccommon.internal.FtcRobotControllerWatchdogService; -import org.firstinspires.ftc.ftccommon.internal.ProgramAndManageActivity; -import org.firstinspires.ftc.onbotjava.ExternalLibraries; -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.opmode.OnBotJavaHelper; -import org.firstinspires.ftc.robotcore.internal.system.AppAliveNotifier; -import org.firstinspires.ftc.robotcore.internal.system.AppUtil; -import org.firstinspires.ftc.robotcore.internal.system.Assert; -import org.firstinspires.ftc.robotcore.internal.system.PreferencesHelper; -import org.firstinspires.ftc.robotcore.internal.system.ServiceController; -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.robotserver.internal.programmingmode.ProgrammingModeManager; -import org.firstinspires.inspection.RcInspectionActivity; -import org.threeten.bp.YearMonth; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.FileNotFoundException; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.ConcurrentLinkedQueue; - -@SuppressWarnings("WeakerAccess") -public class FtcRobotControllerActivity extends Activity - { - public static final String TAG = "RCActivity"; - public String getTag() { return TAG; } - - private static final int REQUEST_CONFIG_WIFI_CHANNEL = 1; - private static final int NUM_GAMEPADS = 2; - - protected WifiManager.WifiLock wifiLock; - protected RobotConfigFileManager cfgFileMgr; - - private OnBotJavaHelper onBotJavaHelper; - - protected ProgrammingModeManager programmingModeManager; - - protected UpdateUI.Callback callback; - protected Context context; - protected Utility utility; - protected StartResult prefRemoterStartResult = new StartResult(); - protected StartResult deviceNameStartResult = new StartResult(); - protected PreferencesHelper preferencesHelper; - protected final SharedPreferencesListener sharedPreferencesListener = new SharedPreferencesListener(); - - protected ImageButton buttonMenu; - protected TextView textDeviceName; - protected TextView textNetworkConnectionStatus; - protected TextView textRobotStatus; - protected TextView[] textGamepad = new TextView[NUM_GAMEPADS]; - protected TextView textOpMode; - protected TextView textErrorMessage; - protected ImmersiveMode immersion; - - protected UpdateUI updateUI; - protected Dimmer dimmer; - protected LinearLayout entireScreenLayout; - - protected FtcRobotControllerService controllerService; - protected NetworkType networkType; - - 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() { - requestRobotRestart(); - } - - } - - protected boolean serviceShouldUnbind = false; - protected ServiceConnection connection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - FtcRobotControllerBinder binder = (FtcRobotControllerBinder) service; - onServiceBind(binder.getService()); - } - - @Override - public void onServiceDisconnected(ComponentName name) { - RobotLog.vv(FtcRobotControllerService.TAG, "%s.controllerService=null", TAG); - controllerService = null; - } - }; - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - - if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) { - UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - RobotLog.vv(TAG, "ACTION_USB_DEVICE_ATTACHED: %s", usbDevice.getDeviceName()); - - if (usbDevice != null) { // paranoia - // We might get attachment notifications before the event loop is set up, so - // we hold on to them and pass them along only when we're good and ready. - if (receivedUsbAttachmentNotifications != null) { // *total* paranoia - receivedUsbAttachmentNotifications.add(usbDevice); - passReceivedUsbAttachmentsToEventLoop(); - } - } - } - } - - protected void passReceivedUsbAttachmentsToEventLoop() { - if (this.eventLoop != null) { - for (;;) { - UsbDevice usbDevice = receivedUsbAttachmentNotifications.poll(); - if (usbDevice == null) - break; - this.eventLoop.onUsbDeviceAttached(usbDevice); - } - } - else { - // Paranoia: we don't want the pending list to grow without bound when we don't - // (yet) have an event loop - while (receivedUsbAttachmentNotifications.size() > 100) { - receivedUsbAttachmentNotifications.poll(); - } - } - } - - /** - * 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 - - // 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()) { - // Double-sure check that we can talk to the DB over the serial TTY - AndroidBoard.getInstance().getAndroidBoardIsPresentPin().setState(true); - } - - context = this; - utility = new Utility(this); - - DeviceNameManagerFactory.getInstance().start(deviceNameStartResult); - - PreferenceRemoterRC.getInstance().start(prefRemoterStartResult); - - receivedUsbAttachmentNotifications = new ConcurrentLinkedQueue(); - eventLoop = null; - - setContentView(R.layout.activity_ftc_controller); - - preferencesHelper = new PreferencesHelper(TAG, context); - preferencesHelper.writeBooleanPrefIfDifferent(context.getString(R.string.pref_rc_connected), true); - preferencesHelper.getSharedPreferences().registerOnSharedPreferenceChangeListener(sharedPreferencesListener); - - // Check if this RC app is from a later FTC season than what was installed previously - int ftcSeasonYearOfPreviouslyInstalledRc = preferencesHelper.readInt(getString(R.string.pref_ftc_season_year_of_current_rc), 0); - int ftcSeasonYearOfCurrentlyInstalledRc = AppUtil.getInstance().getFtcSeasonYear(AppUtil.getInstance().getLocalSdkBuildMonth()).getValue(); - if (ftcSeasonYearOfCurrentlyInstalledRc > ftcSeasonYearOfPreviouslyInstalledRc) { - preferencesHelper.writeIntPrefIfDifferent(getString(R.string.pref_ftc_season_year_of_current_rc), ftcSeasonYearOfCurrentlyInstalledRc); - // Since it's a new FTC season, we should reset certain settings back to their default values. - preferencesHelper.writeBooleanPrefIfDifferent(getString(R.string.pref_warn_about_2_4_ghz_band), true); - preferencesHelper.writeBooleanPrefIfDifferent(getString(R.string.pref_warn_about_obsolete_software), true); - preferencesHelper.writeBooleanPrefIfDifferent(getString(R.string.pref_warn_about_mismatched_app_versions), true); - preferencesHelper.writeBooleanPrefIfDifferent(getString(R.string.pref_warn_about_incorrect_clocks), true); - } - - entireScreenLayout = (LinearLayout) findViewById(R.id.entire_screen); - buttonMenu = (ImageButton) findViewById(R.id.menu_buttons); - buttonMenu.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - 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); - AnnotatedHooksClassFilter.getInstance().callOnCreateMenuMethods( - FtcRobotControllerActivity.this, popupMenu.getMenu()); - popupMenu.show(); - } - }); - - updateMonitorLayout(getResources().getConfiguration()); - - BlocksOpMode.setActivityAndWebView(this, (WebView) findViewById(R.id.webViewBlocksRuntime)); - - ExternalLibraries.getInstance().onCreate(); - onBotJavaHelper = new OnBotJavaHelperImpl(); - - /* - * 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(onBotJavaHelper); - ClassManagerFactory.registerFilters(); - ClassManagerFactory.processAllClasses(); - } - - cfgFileMgr = new RobotConfigFileManager(this); - - // Clean up 'dirty' status after a possible crash - RobotConfigFile configFile = cfgFileMgr.getActiveConfig(); - if (configFile.isDirty()) { - configFile.markClean(); - cfgFileMgr.setActiveConfig(false, configFile); - } - - textDeviceName = (TextView) findViewById(R.id.textDeviceName); - textNetworkConnectionStatus = (TextView) findViewById(R.id.textNetworkConnectionStatus); - textRobotStatus = (TextView) findViewById(R.id.textRobotStatus); - textOpMode = (TextView) findViewById(R.id.textOpMode); - textErrorMessage = (TextView) findViewById(R.id.textErrorMessage); - textGamepad[0] = (TextView) findViewById(R.id.textGamepad1); - textGamepad[1] = (TextView) findViewById(R.id.textGamepad2); - immersion = new ImmersiveMode(getWindow().getDecorView()); - dimmer = new Dimmer(this); - dimmer.longBright(); - - programmingModeManager = new ProgrammingModeManager(); - programmingModeManager.register(new ProgrammingWebHandlers()); - programmingModeManager.register(new OnBotJavaProgrammingMode()); - - updateUI = createUpdateUI(); - callback = createUICallback(updateUI); - - PreferenceManager.setDefaultValues(this, R.xml.app_settings, false); - - WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); - wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, ""); - - hittingMenuButtonBrightensScreen(); - - wifiLock.acquire(); - callback.networkConnectionUpdate(NetworkConnection.NetworkEvent.DISCONNECTED); - readNetworkType(); - ServiceController.startService(FtcRobotControllerWatchdogService.class); - bindToService(); - RobotLog.logAppInfo(); - RobotLog.logDeviceInfo(); - AndroidBoard.getInstance().logAndroidBoardInfo(); - - if (preferencesHelper.readBoolean(getString(R.string.pref_wifi_automute), false)) { - initWifiMute(true); - } - - FtcAboutActivity.setBuildTimeFromBuildConfig(BuildConfig.APP_BUILD_TIME); - - // check to see if there is a preferred Wi-Fi to use. - checkPreferredChannel(); - - AnnotatedHooksClassFilter.getInstance().callOnCreateMethods(this); - } - - protected UpdateUI createUpdateUI() { - Restarter restarter = new RobotRestarter(); - UpdateUI result = new UpdateUI(this, dimmer); - result.setRestarter(restarter); - result.setTextViews(textNetworkConnectionStatus, textRobotStatus, textGamepad, textOpMode, textErrorMessage, textDeviceName); - return result; - } - - protected UpdateUI.Callback createUICallback(UpdateUI updateUI) { - UpdateUI.Callback result = updateUI.new Callback(); - result.setStateMonitor(new SoundPlayingRobotMonitor()); - return result; - } - - @Override - protected void onStart() { - super.onStart(); - RobotLog.vv(TAG, "onStart()"); - - entireScreenLayout.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - dimmer.handleDimTimer(); - return false; - } - }); - } - - @Override - protected void onResume() { - super.onResume(); - RobotLog.vv(TAG, "onResume()"); - - // In case the user just got back from fixing their clock, refresh ClockWarningSource - ClockWarningSource.getInstance().onPossibleRcClockUpdate(); - } - - @Override - protected void onPause() { - super.onPause(); - RobotLog.vv(TAG, "onPause()"); - } - - @Override - protected void onStop() { - // Note: this gets called even when the configuration editor is launched. That is, it gets - // called surprisingly often. So, we don't actually do much here. - super.onStop(); - RobotLog.vv(TAG, "onStop()"); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - RobotLog.vv(TAG, "onDestroy()"); - - shutdownRobot(); // Ensure the robot is put away to bed - if (callback != null) callback.close(); - - 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); - if (wifiLock != null) wifiLock.release(); - if (preferencesHelper != null) preferencesHelper.getSharedPreferences().unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener); - - RobotLog.cancelWriteLogcatToDisk(); - - AnnotatedHooksClassFilter.getInstance().callOnDestroyMethods(this); - } - - protected void bindToService() { - readNetworkType(); - Intent intent = new Intent(this, FtcRobotControllerService.class); - intent.putExtra(NetworkConnectionFactory.NETWORK_CONNECTION_TYPE, networkType); - serviceShouldUnbind = bindService(intent, connection, Context.BIND_AUTO_CREATE); - } - - protected void unbindFromService() { - if (serviceShouldUnbind) { - unbindService(connection); - serviceShouldUnbind = false; - } - } - - protected void readNetworkType() { - // Control hubs are always running the access point model. Everything else, for the time - // being always runs the Wi-Fi 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_pairing_kind), networkType.toString()); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - - if (hasFocus) { - immersion.hideSystemUI(); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.ftc_robot_controller, menu); - AnnotatedHooksClassFilter.getInstance().callOnCreateMenuMethods(this, menu); - return true; - } - - private boolean isRobotRunning() { - if (controllerService == null) { - return false; - } - - Robot robot = controllerService.getRobot(); - - if ((robot == null) || (robot.eventLoopManager == null)) { - return false; - } - - RobotState robotState = robot.eventLoopManager.state; - - if (robotState != RobotState.RUNNING) { - return false; - } else { - return true; - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - - if (id == R.id.action_program_and_manage) { - if (isRobotRunning()) { - Intent programmingModeIntent = new Intent(AppUtil.getDefContext(), ProgramAndManageActivity.class); - RobotControllerWebInfo webInfo = programmingModeManager.getWebServer().getConnectionInformation(); - programmingModeIntent.putExtra(LaunchActivityConstantsList.RC_WEB_INFO, webInfo.toJson()); - startActivity(programmingModeIntent); - } else { - AppUtil.getInstance().showToast(UILocation.ONLY_LOCAL, context.getString(R.string.toastWifiUpBeforeProgrammingMode)); - } - } else if (id == R.id.action_inspection_mode) { - Intent inspectionModeIntent = new Intent(AppUtil.getDefContext(), RcInspectionActivity.class); - startActivity(inspectionModeIntent); - return true; - } else if (id == R.id.action_restart_robot) { - dimmer.handleDimTimer(); - AppUtil.getInstance().showToast(UILocation.BOTH, context.getString(R.string.toastRestartingRobot)); - requestRobotRestart(); - return true; - } - else if (id == R.id.action_configure_robot) { - EditParameters parameters = new EditParameters(); - Intent intentConfigure = new Intent(AppUtil.getDefContext(), FtcLoadFileActivity.class); - parameters.putIntent(intentConfigure); - startActivityForResult(intentConfigure, RequestCode.CONFIGURE_ROBOT_CONTROLLER.ordinal()); - } - else if (id == R.id.action_settings) { - // historical: this once erroneously used FTC_CONFIGURE_REQUEST_CODE_ROBOT_CONTROLLER - Intent settingsIntent = new Intent(AppUtil.getDefContext(), FtcRobotControllerSettingsActivity.class); - startActivityForResult(settingsIntent, RequestCode.SETTINGS_ROBOT_CONTROLLER.ordinal()); - return true; - } - else if (id == R.id.action_about) { - Intent intent = new Intent(AppUtil.getDefContext(), FtcAboutActivity.class); - startActivity(intent); - return true; - } - else if (id == R.id.action_exit_app) { - - //Clear backstack and everything to prevent edge case where VM might be - //restarted (after it was exited) if more than one activity was on the - //backstack for some reason. - finishAffinity(); - - //For lollipop and up, we can clear ourselves from the recents list too - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); - List tasks = manager.getAppTasks(); - - for (ActivityManager.AppTask task : tasks) { - task.finishAndRemoveTask(); - } - } - - // Allow the user to use the Control Hub operating system's UI, instead of relaunching the app - AppAliveNotifier.getInstance().disableAppWatchdogUntilNextAppStart(); - - //Finally, nuke the VM from orbit - AppUtil.getInstance().exitApplication(); - - return true; - } - - return super.onOptionsItemSelected(item); - } - - @Override - 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) - * 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.getString(R.string.toastWifiConfigurationComplete)); - } - } - // was some historical confusion about launch codes here, so we err safely - if (request == RequestCode.CONFIGURE_ROBOT_CONTROLLER.ordinal() || request == RequestCode.SETTINGS_ROBOT_CONTROLLER.ordinal()) { - // We always do a refresh, whether it was a cancel or an OK, for robustness - shutdownRobot(); - cfgFileMgr.getActiveConfigAndUpdateUI(); - updateUIAndRequestRobotSetup(); - } - } - - public void onServiceBind(final FtcRobotControllerService service) { - RobotLog.vv(FtcRobotControllerService.TAG, "%s.controllerService=bound", TAG); - controllerService = service; - updateUI.setControllerService(controllerService); - - controllerService.setOnBotJavaHelper(onBotJavaHelper); - - updateUIAndRequestRobotSetup(); - programmingModeManager.setState(new FtcRobotControllerServiceState() { - @NonNull - @Override - public WebServer getWebServer() { - return service.getWebServer(); - } - - @Nullable - @Override - public OnBotJavaHelper getOnBotJavaHelper() { - return service.getOnBotJavaHelper(); - } - - @Override - public EventLoopManager getEventLoopManager() { - return service.getRobot().eventLoopManager; - } - }); - - AnnotatedHooksClassFilter.getInstance().callWebHandlerRegistrarMethods(this, - service.getWebServer().getWebHandlerManager()); - } - - private void updateUIAndRequestRobotSetup() { - if (controllerService != null) { - callback.networkConnectionUpdate(controllerService.getNetworkConnectionStatus()); - callback.updateRobotStatus(controllerService.getRobotStatus()); - // 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(@Nullable Runnable runOnComplete) { - if (controllerService == null) return; - - RobotConfigFile file = cfgFileMgr.getActiveConfigAndUpdateUI(); - HardwareFactory hardwareFactory = new HardwareFactory(context); - try { - hardwareFactory.setXmlPullParser(file.getXml()); - } catch (FileNotFoundException | XmlPullParserException e) { - RobotLog.ww(TAG, e, "Unable to set configuration file %s. Falling back on noConfig.", file.getName()); - file = RobotConfigFile.noConfig(cfgFileMgr); - try { - hardwareFactory.setXmlPullParser(file.getXml()); - cfgFileMgr.setActiveConfigAndUpdateUI(false, file); - } catch (FileNotFoundException | XmlPullParserException e1) { - RobotLog.ee(TAG, e1, "Failed to fall back on noConfig"); - } - } - - OpModeRegister userOpModeRegister = createOpModeRegister(); - eventLoop = new FtcEventLoop(hardwareFactory, userOpModeRegister, callback, this); - FtcEventLoopIdle idleLoop = new FtcEventLoopIdle(hardwareFactory, userOpModeRegister, callback, this); - - controllerService.setCallback(callback); - controllerService.setupRobot(eventLoop, idleLoop, runOnComplete); - - passReceivedUsbAttachmentsToEventLoop(); - AndroidBoard.showErrorIfUnknownControlHub(); - - AnnotatedHooksClassFilter.getInstance().callOnCreateEventLoopMethods(this, eventLoop); - } - - protected OpModeRegister createOpModeRegister() { - return new FtcOpModeRegister(); - } - - private void shutdownRobot() { - if (controllerService != null) controllerService.shutdownRobot(); - } - - private void requestRobotRestart() { - AppUtil.getInstance().showToast(UILocation.BOTH, AppUtil.getDefContext().getString(R.string.toastRestartingRobot)); - // - RobotLog.clearGlobalErrorMsg(); - RobotLog.clearGlobalWarningMsg(); - shutdownRobot(); - 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() { - ActionBar actionBar = getActionBar(); - if (actionBar != null) { - actionBar.addOnMenuVisibilityListener(new ActionBar.OnMenuVisibilityListener() { - @Override - public void onMenuVisibilityChanged(boolean isVisible) { - if (isVisible) { - dimmer.handleDimTimer(); - } - } - }); - } - } - - protected class SharedPreferencesListener implements SharedPreferences.OnSharedPreferenceChangeListener { - @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/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/PermissionValidatorWrapper.java b/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/PermissionValidatorWrapper.java deleted file mode 100644 index a0094bc9..00000000 --- a/library/FtcRobotController/src/main/java/org/firstinspires/ftc/robotcontroller/internal/PermissionValidatorWrapper.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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); - add(Manifest.permission.ACCESS_FINE_LOCATION); - add(Manifest.permission.READ_PHONE_STATE); - }}; - - 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.permAccessLocationExplain); - } else if (permission.equals(Manifest.permission.ACCESS_FINE_LOCATION)) { - return Misc.formatForUser(R.string.permAccessLocationExplain); - } else if (permission.equals(Manifest.permission.READ_PHONE_STATE)) { - return Misc.formatForUser(R.string.permReadPhoneState); - } - 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/library/FtcRobotController/src/main/res/drawable-xhdpi/icon_menu.png b/library/FtcRobotController/src/main/res/drawable-xhdpi/icon_menu.png deleted file mode 100644 index 6b9e997c..00000000 Binary files a/library/FtcRobotController/src/main/res/drawable-xhdpi/icon_menu.png and /dev/null differ diff --git a/library/FtcRobotController/src/main/res/drawable-xhdpi/icon_robotcontroller.png b/library/FtcRobotController/src/main/res/drawable-xhdpi/icon_robotcontroller.png deleted file mode 100644 index 022552f4..00000000 Binary files a/library/FtcRobotController/src/main/res/drawable-xhdpi/icon_robotcontroller.png and /dev/null differ diff --git a/library/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml b/library/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml deleted file mode 100644 index 6524f948..00000000 --- a/library/FtcRobotController/src/main/res/layout/activity_ftc_controller.xml +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/library/FtcRobotController/src/main/res/menu/ftc_robot_controller.xml b/library/FtcRobotController/src/main/res/menu/ftc_robot_controller.xml deleted file mode 100644 index 657c1aac..00000000 --- a/library/FtcRobotController/src/main/res/menu/ftc_robot_controller.xml +++ /dev/null @@ -1,78 +0,0 @@ - - -

- - - - - - - - - - - - - - - diff --git a/library/FtcRobotController/src/main/res/raw/gold.wav b/library/FtcRobotController/src/main/res/raw/gold.wav deleted file mode 100644 index 3a7baf88..00000000 Binary files a/library/FtcRobotController/src/main/res/raw/gold.wav and /dev/null differ diff --git a/library/FtcRobotController/src/main/res/raw/silver.wav b/library/FtcRobotController/src/main/res/raw/silver.wav deleted file mode 100644 index 25918a72..00000000 Binary files a/library/FtcRobotController/src/main/res/raw/silver.wav and /dev/null differ diff --git a/library/FtcRobotController/src/main/res/values/dimens.xml b/library/FtcRobotController/src/main/res/values/dimens.xml deleted file mode 100644 index 63f1babc..00000000 --- a/library/FtcRobotController/src/main/res/values/dimens.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - 16dp - 5dp - - \ No newline at end of file diff --git a/library/FtcRobotController/src/main/res/values/strings.xml b/library/FtcRobotController/src/main/res/values/strings.xml deleted file mode 100644 index 6ea191ed..00000000 --- a/library/FtcRobotController/src/main/res/values/strings.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - FTC Robot Controller - - - Self Inspect - Program & Manage - Blocks - Settings - Restart Robot - Configure Robot - About - Exit - - - Configuration Complete - Restarting Robot - The Robot Controller must be fully up and running before entering Program and Manage Mode. - - - - @style/AppThemeRedRC - @style/AppThemeGreenRC - @style/AppThemeBlueRC - @style/AppThemePurpleRC - @style/AppThemeOrangeRC - @style/AppThemeTealRC - - - pref_ftc_season_year_of_current_rc_new - - @string/packageNameRobotController - - diff --git a/library/FtcRobotController/src/main/res/values/styles.xml b/library/FtcRobotController/src/main/res/values/styles.xml deleted file mode 100644 index 07689c03..00000000 --- a/library/FtcRobotController/src/main/res/values/styles.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/library/FtcRobotController/src/main/res/xml/app_settings.xml b/library/FtcRobotController/src/main/res/xml/app_settings.xml deleted file mode 100644 index 58d3aa9c..00000000 --- a/library/FtcRobotController/src/main/res/xml/app_settings.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/library/FtcRobotController/src/main/res/xml/device_filter.xml b/library/FtcRobotController/src/main/res/xml/device_filter.xml deleted file mode 100644 index 7b75350c..00000000 --- a/library/FtcRobotController/src/main/res/xml/device_filter.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - diff --git a/library/FullPanels/build.gradle.kts b/library/FullPanels/build.gradle.kts index 5a66b0a0..5096e2c5 100644 --- a/library/FullPanels/build.gradle.kts +++ b/library/FullPanels/build.gradle.kts @@ -2,56 +2,45 @@ val pluginNamespace = "com.bylazar.fullpanels" val pluginVersion = "1.0.12" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "FullPanels" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - api(project(":Panels")) api(project(":OpModeControl")) @@ -77,9 +66,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("All in one toolbox dashboard for FTC with core plugins.") @@ -96,12 +87,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/FullPanels/web/bun.lock b/library/FullPanels/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/FullPanels/web/bun.lock +++ b/library/FullPanels/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Gamepad/build.gradle.kts b/library/Gamepad/build.gradle.kts index bfafbd39..95b22da4 100644 --- a/library/Gamepad/build.gradle.kts +++ b/library/Gamepad/build.gradle.kts @@ -2,56 +2,44 @@ val pluginNamespace = "com.bylazar.gamepad" val pluginVersion = "1.0.4" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Gamepad" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +49,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Gamepad Plugin") @@ -80,12 +70,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Gamepad/web/bun.lock b/library/Gamepad/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/Gamepad/web/bun.lock +++ b/library/Gamepad/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Graph/build.gradle.kts b/library/Graph/build.gradle.kts index 4cad699a..86e65549 100644 --- a/library/Graph/build.gradle.kts +++ b/library/Graph/build.gradle.kts @@ -2,43 +2,41 @@ val pluginNamespace = "com.bylazar.graph" val pluginVersion = "1.0.4" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Graph" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } @@ -61,9 +59,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Graph Plugin") @@ -80,12 +80,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Graph/web/bun.lock b/library/Graph/web/bun.lock index bfc69e3b..0832e7d8 100644 --- a/library/Graph/web/bun.lock +++ b/library/Graph/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Lights/build.gradle.kts b/library/Lights/build.gradle.kts index 46942d59..d0bc98fc 100644 --- a/library/Lights/build.gradle.kts +++ b/library/Lights/build.gradle.kts @@ -2,56 +2,45 @@ val pluginNamespace = "com.bylazar.lights" val pluginVersion = "1.0.3" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Lights" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +50,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Telemetry Plugin") @@ -80,12 +71,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Lights/web/bun.lock b/library/Lights/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/Lights/web/bun.lock +++ b/library/Lights/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/LimelightProxy/build.gradle.kts b/library/LimelightProxy/build.gradle.kts index 6f51a5ce..c6a87df9 100644 --- a/library/LimelightProxy/build.gradle.kts +++ b/library/LimelightProxy/build.gradle.kts @@ -1,63 +1,49 @@ -import org.gradle.kotlin.dsl.implementation - val pluginNamespace = "com.bylazar.limelightproxy" val pluginVersion = "1.0.4" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "LimelightProxy" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"$version\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"${dairyPublishing.version}\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) implementation("com.squareup.okhttp3:okhttp:4.10.0") - } afterEvaluate { @@ -66,9 +52,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Limelight Proxy Plugin") @@ -85,12 +73,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/LimelightProxy/web/bun.lock b/library/LimelightProxy/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/LimelightProxy/web/bun.lock +++ b/library/LimelightProxy/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/OpModeControl/build.gradle.kts b/library/OpModeControl/build.gradle.kts index 9987f5fa..4febced0 100644 --- a/library/OpModeControl/build.gradle.kts +++ b/library/OpModeControl/build.gradle.kts @@ -2,56 +2,48 @@ val pluginNamespace = "com.bylazar.opmodecontrol" val pluginVersion = "1.0.3" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace +dairyPublishing { + gitDir = file("..") +} - defaultConfig { - compileSdk = 34 - minSdk = 24 - } +version = "${dairyPublishing.version}+$pluginVersion" - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +meta { + packagePath = pluginNamespace + name = "OpModeControl" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"${dairyPublishing.version}\"" } +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } - - kotlinOptions { - jvmTarget = "11" - } - - publishing { - singleVariant("release") {} + dairy { + implementation(Sloth) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +53,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaHtmlJar) + artifact(dairyDoc.dokkaJavadocJar) pom { description.set("Panels OpModeControl Plugin") @@ -80,12 +74,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/OpModeControl/src/main/java/com/bylazar/opmodecontrol/OpModeControlPlugin.kt b/library/OpModeControl/src/main/java/com/bylazar/opmodecontrol/OpModeControlPlugin.kt index 98b7fbf5..dea76d61 100644 --- a/library/OpModeControl/src/main/java/com/bylazar/opmodecontrol/OpModeControlPlugin.kt +++ b/library/OpModeControl/src/main/java/com/bylazar/opmodecontrol/OpModeControlPlugin.kt @@ -1,7 +1,6 @@ package com.bylazar.opmodecontrol import android.content.Context -import android.os.SystemClock import com.bylazar.panels.Panels import com.bylazar.panels.plugins.BasePluginConfig import com.bylazar.panels.plugins.Plugin @@ -9,22 +8,35 @@ import com.bylazar.panels.server.Socket import com.qualcomm.ftccommon.FtcEventLoop import com.qualcomm.robotcore.eventloop.opmode.OpMode import com.qualcomm.robotcore.eventloop.opmode.OpModeManagerImpl +import dev.frozenmilk.sinister.Scanner +import dev.frozenmilk.sinister.sdk.apphooks.SDKOpModeRegistrar +import dev.frozenmilk.sinister.sdk.opmodes.OpModeScanner +import dev.frozenmilk.sinister.sdk.opmodes.SinisterRegisteredOpModes +import dev.frozenmilk.sinister.targeting.NarrowSearch +import dev.frozenmilk.util.graph.rule.dependsOn +import dev.frozenmilk.util.graph.rule.dependsOnClass import org.firstinspires.ftc.robotcore.internal.opmode.OpModeMeta -import org.firstinspires.ftc.robotcore.internal.opmode.RegisteredOpModes import java.lang.ref.WeakReference import java.util.concurrent.Executors import java.util.concurrent.ScheduledFuture import java.util.concurrent.TimeUnit -open class OpModeControlPluginConfig : BasePluginConfig() { -} +open class OpModeControlPluginConfig : BasePluginConfig() {} + +object Plugin : Plugin(OpModeControlPluginConfig()), Scanner { + val opModeList: List + get() = SinisterRegisteredOpModes.opModes.mapNotNull { opModeMeta -> + if (opModeMeta.flavor == OpModeMeta.Flavor.SYSTEM) null + else OpModeDetails( + name = opModeMeta.name, + group = opModeMeta.group, + flavour = opModeMeta.flavor, + source = opModeMeta.source ?: OpModeMeta.Source.ANDROID_STUDIO, + defaultGroup = OpModeMeta.DefaultGroup, + autoTransition = opModeMeta.autoTransition ?: "" + ) + }.sortedWith(compareBy({ it.group }, { it.name })) -object Plugin : Plugin(OpModeControlPluginConfig()) { - var opModeList: MutableList = mutableListOf() - set(value) { - field = value - send("opModesList", OpModesList(value)) - } var status = OpModeStatus.STOPPED var activeOpMode: OpMode? = null var activeOpModeStartTimestamp: Long? = null @@ -58,6 +70,7 @@ object Plugin : Plugin(OpModeControlPluginConfig()) { private val scheduler = Executors.newSingleThreadScheduledExecutor { r -> Thread(r, "OpModeControl-Ticker") } + @Volatile private var tickTask: ScheduledFuture<*>? = null @@ -107,8 +120,7 @@ object Plugin : Plugin(OpModeControlPluginConfig()) { } override fun onRegister( - panelsInstance: Panels, - context: Context + panelsInstance: Panels, context: Context ) { } @@ -122,9 +134,6 @@ object Plugin : Plugin(OpModeControlPluginConfig()) { opModeManagerRef = WeakReference(o) activeOpMode = null activeOpModeName = "" - opModeList.clear() - val t = Thread(FetcherRoutine()) - t.start() activeOpModeStartTimestamp = null } @@ -170,39 +179,32 @@ object Plugin : Plugin(OpModeControlPluginConfig()) { sendActiveOpMode() } - class FetcherRoutine : Runnable { - override fun run() { - RegisteredOpModes.getInstance().waitOpModesRegistered() - - var list = ArrayList() - for (opModeMeta in RegisteredOpModes.getInstance().opModes) { - if (opModeMeta.flavor != OpModeMeta.Flavor.SYSTEM) { - list.add( - OpModeDetails( - name = opModeMeta.name, - group = opModeMeta.group, - flavour = opModeMeta.flavor, - source = opModeMeta.source ?: OpModeMeta.Source.ANDROID_STUDIO, - defaultGroup = OpModeMeta.DefaultGroup, - autoTransition = opModeMeta.autoTransition ?: "" - ) - ) - } - } - - opModeList = list.sortedWith(compareBy({ it.group }, { it.name })).toMutableList() - log("OpModes: ${opModeList.joinToString(", ", transform = { it.name })}") - - send("opModesList", OpModesList(opModeList)) - sendActiveOpMode() - } + override fun onEnablePanels() { } + override fun onDisablePanels() { + } - override fun onEnablePanels() { + override val loadAdjacencyRule = + dependsOnClass(OpModeScanner::class.java).and(dependsOn(SDKOpModeRegistrar)) + override val unloadAdjacencyRule = + dependsOnClass(OpModeScanner::class.java).and(dependsOn(SDKOpModeRegistrar)) + override val targets = NarrowSearch() + + override fun scan(loader: ClassLoader, cls: Class<*>) {} + override fun afterScan(loader: ClassLoader) { + val opModeList = opModeList + log("OpModes: ${opModeList.joinToString(", ", transform = { it.name })}") + send("opModesList", OpModesList(opModeList)) + sendActiveOpMode() } - override fun onDisablePanels() { + override fun unload(loader: ClassLoader, cls: Class<*>) {} + override fun afterUnload(loader: ClassLoader) { + val opModeList = opModeList + log("OpModes: ${opModeList.joinToString(", ", transform = { it.name })}") + send("opModesList", OpModesList(opModeList)) + sendActiveOpMode() } } \ No newline at end of file diff --git a/library/OpModeControl/web/bun.lock b/library/OpModeControl/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/OpModeControl/web/bun.lock +++ b/library/OpModeControl/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Panels/build.gradle.kts b/library/Panels/build.gradle.kts index e369dbe4..38bf6301 100644 --- a/library/Panels/build.gradle.kts +++ b/library/Panels/build.gradle.kts @@ -1,77 +1,59 @@ +val pluginNamespace = "com.bylazar.panels" +val pluginVersion = "1.0.5" + plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } -val pluginNamespace = "com.bylazar.panels" -val pluginVersion = "1.0.5" +android.namespace = pluginNamespace svelteAssets { - webAppPath = "web" - buildDirPath = "build" assetsPath = "web" + buildDirPath = "build" } -android { - namespace = "com.bylazar.panels" - - defaultConfig { - compileSdk = 34 - minSdk = 24 - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Panels" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) + implementation(appcompat) } } dependencies { - implementation("androidx.core:core-ktx:1.13.1") - implementation("androidx.appcompat:appcompat:1.2.0") - implementation("com.google.android.material:material:1.12.0") + implementation("androidx.core:core-ktx:1.2.0") testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.2.1") - androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") - - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + //androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") implementation("org.nanohttpd:nanohttpd-websocket:2.3.1") { exclude(module = "nanohttpd") } - implementation("org.jetbrains.kotlin:kotlin-reflect:1.9.23") + implementation("org.jetbrains.kotlin:kotlin-reflect:2.3.0") implementation("org.tukaani:xz:1.9") } @@ -82,9 +64,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("All in one toolbox dashboard for FTC.") @@ -101,12 +85,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Panels/src/androidTest/java/com/bylazar/panels/TestCompression.kt b/library/Panels/src/androidTest/java/com/bylazar/panels/TestCompression.kt index 4a20eb27..9fd2a6f3 100644 --- a/library/Panels/src/androidTest/java/com/bylazar/panels/TestCompression.kt +++ b/library/Panels/src/androidTest/java/com/bylazar/panels/TestCompression.kt @@ -62,9 +62,8 @@ class TestCompression { return output.toByteArray() } - private fun decompressGzip(input: ByteArray, originalSize: Int): ByteArray { - val inputStream = ByteArrayInputStream(input) - return GZIPInputStream(inputStream).readAllBytes() + private fun decompressGzip(input: ByteArray, originalSize: Int) = ByteArrayInputStream(input).use { + GZIPInputStream(it).readBytes() } fun compressLzma(input: ByteArray): ByteArray { @@ -74,9 +73,8 @@ class TestCompression { return baos.toByteArray() } - fun decompressLzma(input: ByteArray): ByteArray { - val bais = ByteArrayInputStream(input) - return LZMAInputStream(bais).readAllBytes() + fun decompressLzma(input: ByteArray) = ByteArrayInputStream(input).use { + LZMAInputStream(it).readBytes() } fun compressDeflate(input: ByteArray): ByteArray { diff --git a/library/Panels/src/main/java/com/bylazar/panels/Logger.kt b/library/Panels/src/main/java/com/bylazar/panels/Logger.kt index 64fe4673..58555df7 100644 --- a/library/Panels/src/main/java/com/bylazar/panels/Logger.kt +++ b/library/Panels/src/main/java/com/bylazar/panels/Logger.kt @@ -1,5 +1,7 @@ package com.bylazar.panels +import com.qualcomm.robotcore.util.RobotLog + object Logger { const val REFLECTION_PREFIX = "Reflection" const val SOCKET_PREFIX = "Socket" @@ -7,8 +9,8 @@ object Logger { const val PLUGINS_PREFIX = "Plugins" const val CORE_PREFIX = "Core" - private fun getCallerClassName(): String { - if(!Panels.config.enableClassCallerLogs) return "Disabled" + private fun getCallerClassName(): String? { + if(!Panels.config.enableClassCallerLogs) return null return Throwable() .stackTrace .firstOrNull { !it.className.contains("com.bylazar.panels.Logger") } @@ -17,14 +19,20 @@ object Logger { ?: "Unknown" } + private fun logCallerClass(message: String) = + getCallerClassName()?.let { "($it): $message" } ?: message + fun log(prefix: String, message: String) { if(!Panels.config.enableLogs) return - println("PANELS: ${prefix.uppercase()}: (${getCallerClassName()}): $message") + RobotLog.ii("Panels::$prefix", logCallerClass(message)) } fun error(prefix: String, message: String) { - if(!Panels.config.enableLogs) return - println("PANELS: ${prefix.uppercase()}: (${getCallerClassName()}): ERROR: $message") + RobotLog.ee("Panels::$prefix", logCallerClass(message)) + } + + fun error(prefix: String, message: String, e: Throwable) { + RobotLog.ee("Panels@$prefix", e, logCallerClass(message)) } fun reflectionLog(message: String) = log(REFLECTION_PREFIX, message) @@ -32,13 +40,16 @@ object Logger { fun socketLog(message: String) = log(SOCKET_PREFIX, message) fun socketError(message: String) = error(SOCKET_PREFIX, message) + fun socketError(message: String, e: Throwable) = error(SOCKET_PREFIX, message, e) fun serverLog(message: String) = log(SERVER_PREFIX, message) fun serverError(message: String) = error(SERVER_PREFIX, message) + fun serverError(message: String, e: Throwable) = error(SERVER_PREFIX, message, e) fun pluginsLog(message: String) = log(PLUGINS_PREFIX, message) fun pluginsError(message: String) = error(PLUGINS_PREFIX, message) fun coreLog(message: String) = log(CORE_PREFIX, message) fun coreError(message: String) = error(CORE_PREFIX, message) + fun coreError(message: String, e: Throwable) = error(CORE_PREFIX, message, e) } \ No newline at end of file diff --git a/library/Panels/src/main/java/com/bylazar/panels/Panels.kt b/library/Panels/src/main/java/com/bylazar/panels/Panels.kt index 9f86fae5..7957d714 100644 --- a/library/Panels/src/main/java/com/bylazar/panels/Panels.kt +++ b/library/Panels/src/main/java/com/bylazar/panels/Panels.kt @@ -1,19 +1,16 @@ package com.bylazar.panels import android.content.Context -import androidx.core.app.PendingIntentCompat.send -import com.bylazar.panels.core.TextHandler import com.bylazar.panels.core.OpModeHandler import com.bylazar.panels.core.PreferencesHandler +import com.bylazar.panels.core.TextHandler import com.bylazar.panels.plugins.PluginsManager -import com.bylazar.panels.plugins.PluginsManager.contextRef import com.bylazar.panels.reflection.ClassFinder import com.bylazar.panels.server.Socket import com.bylazar.panels.server.StaticServer import com.qualcomm.ftccommon.FtcEventLoop import com.qualcomm.robotcore.eventloop.opmode.OpMode import com.qualcomm.robotcore.eventloop.opmode.OpModeManager -import com.qualcomm.robotcore.eventloop.opmode.OpModeManagerImpl import com.qualcomm.robotcore.eventloop.opmode.OpModeManagerNotifier.Notifications import com.qualcomm.robotcore.eventloop.opmode.OpModeRegistrar import com.qualcomm.robotcore.util.WebHandlerManager @@ -22,10 +19,7 @@ import org.firstinspires.ftc.ftccommon.external.OnCreateEventLoop import org.firstinspires.ftc.ftccommon.external.OnDestroy import org.firstinspires.ftc.ftccommon.external.WebHandlerRegistrar import org.firstinspires.ftc.ftccommon.internal.FtcRobotControllerWatchdogService -import org.firstinspires.ftc.robotcore.internal.opmode.OpModeMeta -import org.firstinspires.ftc.robotcore.internal.opmode.RegisteredOpModes import org.firstinspires.ftc.robotcore.internal.system.AppUtil -import java.lang.ref.WeakReference object Panels : Notifications { @@ -83,7 +77,7 @@ object Panels : Notifications { server = StaticServer(context, 8001, "web") socket = Socket(8002) } catch (e: Exception) { - Logger.coreLog("Failed to start webserver: " + e.message) + Logger.coreError("Failed to start webserver", e) } if (PreferencesHandler.isEnabled) { diff --git a/library/Panels/src/main/java/com/bylazar/panels/plugins/Plugin.kt b/library/Panels/src/main/java/com/bylazar/panels/plugins/Plugin.kt index 5d81e405..b0a19d75 100644 --- a/library/Panels/src/main/java/com/bylazar/panels/plugins/Plugin.kt +++ b/library/Panels/src/main/java/com/bylazar/panels/plugins/Plugin.kt @@ -36,11 +36,15 @@ abstract class Plugin(baseConfig: T) { } fun log(message: String) { - Logger.log("${Logger.PLUGINS_PREFIX}/${id}", message) + Logger.log("${Logger.PLUGINS_PREFIX}/${id.ifBlank { "UNKNOWN" }}", message) } fun error(message: String) { - Logger.error("${Logger.PLUGINS_PREFIX}/${id}", message) + Logger.error("${Logger.PLUGINS_PREFIX}/${id.ifBlank { "UNKNOWN" }}", message) + } + + fun error(message: String, e: Throwable) { + Logger.error("${Logger.PLUGINS_PREFIX}/${id.ifBlank { "UNKNOWN" }}", message, e) } fun send(type: String, data: Any) { diff --git a/library/Panels/src/main/java/com/bylazar/panels/server/StaticServer.kt b/library/Panels/src/main/java/com/bylazar/panels/server/StaticServer.kt index 657544fb..e4737470 100644 --- a/library/Panels/src/main/java/com/bylazar/panels/server/StaticServer.kt +++ b/library/Panels/src/main/java/com/bylazar/panels/server/StaticServer.kt @@ -25,6 +25,7 @@ class StaticServer( init { var files = listWebFiles(baseFolder) + Logger.serverLog("Found ${files.size} web files") files.forEach { Logger.serverLog("Found file: $it") } @@ -280,15 +281,15 @@ class StaticServer( Logger.serverLog("Success") return newChunkedResponse(Response.Status.OK, mime, inputStream).allowCors() } catch (e: Exception) { - Logger.serverLog("Primary asset not found: $path — ${e.message}") + Logger.serverError("Primary asset not found: $path", e) return try { val fallbackStream = assets.open("$baseFolder/index.html") Logger.serverLog("Fallback to index.html") newChunkedResponse(Response.Status.OK, "text/html", fallbackStream) } catch (fallbackException: Exception) { - val message = "Fallback also failed: ${fallbackException.message}" - Logger.serverLog(message) + val message = "Fallback also failed, check logcat for more info" + Logger.serverError(message, fallbackException) getResponse(message, status = Response.Status.INTERNAL_ERROR) } } @@ -299,7 +300,7 @@ class StaticServer( start() Logger.serverLog("Server started on port $listeningPort") } catch (e: IOException) { - Logger.serverLog("Failed to start server: ${e.message}") + Logger.serverError("Failed to start server", e) } } diff --git a/library/Panels/web/bun.lock b/library/Panels/web/bun.lock index 21500d67..806acf29 100644 --- a/library/Panels/web/bun.lock +++ b/library/Panels/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-app", diff --git a/library/Pinger/build.gradle.kts b/library/Pinger/build.gradle.kts index 1b074238..b0e3d49a 100644 --- a/library/Pinger/build.gradle.kts +++ b/library/Pinger/build.gradle.kts @@ -2,56 +2,45 @@ val pluginNamespace = "com.bylazar.pinger" val pluginVersion = "1.0.3" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Pinger" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +50,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Pinger Plugin") @@ -80,12 +71,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Pinger/src/main/java/com/bylazar/pinger/PingerPlugin.kt b/library/Pinger/src/main/java/com/bylazar/pinger/PingerPlugin.kt index 274ead0b..159753df 100644 --- a/library/Pinger/src/main/java/com/bylazar/pinger/PingerPlugin.kt +++ b/library/Pinger/src/main/java/com/bylazar/pinger/PingerPlugin.kt @@ -9,7 +9,6 @@ import com.bylazar.panels.server.Socket import com.qualcomm.ftccommon.FtcEventLoop import com.qualcomm.robotcore.eventloop.opmode.OpMode import com.qualcomm.robotcore.eventloop.opmode.OpModeManagerImpl -import com.sun.tools.doclint.Entity.delta open class ExamplePluginConfig : BasePluginConfig() { } diff --git a/library/Pinger/web/bun.lock b/library/Pinger/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/Pinger/web/bun.lock +++ b/library/Pinger/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/TeamCode/build.gradle b/library/TeamCode/build.gradle deleted file mode 100644 index 3e52c54d..00000000 --- a/library/TeamCode/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -// -// build.gradle in TeamCode -// -// Most of the definitions for building your module reside in a common, shared -// file 'build.common.gradle'. Being factored in this way makes it easier to -// integrate updates to the FTC into your code. If you really need to customize -// the build definitions, you can place those customizations in this file, but -// please think carefully as to whether such customizations are really necessary -// before doing so. - - -// Custom definitions may go here - -// Include common definitions from above. -apply from: '../build.common.gradle' -apply from: '../build.dependencies.gradle' -apply plugin: 'org.jetbrains.kotlin.android' - -android { - namespace = 'org.firstinspires.ftc.teamcode' - - compileSdk 34 - - packagingOptions { - jniLibs.useLegacyPackaging true - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - kotlinOptions { - jvmTarget = '11' - } -} - -repositories { -} - -dependencies { - implementation project(':FtcRobotController') - implementation project(':FullPanels') - implementation project(':ExamplePlugin') -} diff --git a/library/TeamCode/build.gradle.kts b/library/TeamCode/build.gradle.kts new file mode 100644 index 00000000..497754d3 --- /dev/null +++ b/library/TeamCode/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + id("dev.frozenmilk.teamcode") version "11.1.0-1.1.1" +} + +ftc { + kotlin() + sdk.TeamCode() +} + +dependencies { + implementation(project(":FullPanels")) +} \ No newline at end of file diff --git a/library/TeamCode/lib/OpModeAnnotationProcessor.jar b/library/TeamCode/lib/OpModeAnnotationProcessor.jar deleted file mode 100644 index 4825cc36..00000000 Binary files a/library/TeamCode/lib/OpModeAnnotationProcessor.jar and /dev/null differ diff --git a/library/TeamCode/libs/ftc.debug.keystore b/library/TeamCode/libs/ftc.debug.keystore new file mode 100644 index 00000000..a7204e66 Binary files /dev/null and b/library/TeamCode/libs/ftc.debug.keystore differ diff --git a/library/Telemetry/build.gradle.kts b/library/Telemetry/build.gradle.kts index 5470ad7b..48cae6a9 100644 --- a/library/Telemetry/build.gradle.kts +++ b/library/Telemetry/build.gradle.kts @@ -2,56 +2,45 @@ val pluginNamespace = "com.bylazar.telemetry" val pluginVersion = "1.0.5" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Telemetry" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +50,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Telemetry Plugin") @@ -80,12 +71,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Telemetry/web/bun.lock b/library/Telemetry/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/Telemetry/web/bun.lock +++ b/library/Telemetry/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Themes/build.gradle.kts b/library/Themes/build.gradle.kts index 686e4f2c..3f6e5273 100644 --- a/library/Themes/build.gradle.kts +++ b/library/Themes/build.gradle.kts @@ -2,56 +2,45 @@ val pluginNamespace = "com.bylazar.themes" val pluginVersion = "1.0.3" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Themes" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") {} +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -61,9 +50,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Themes Plugin") @@ -80,12 +71,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Themes/web/bun.lock b/library/Themes/web/bun.lock index 06220f3b..4386e178 100644 --- a/library/Themes/web/bun.lock +++ b/library/Themes/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/Utils/build.gradle.kts b/library/Utils/build.gradle.kts index b5768930..524206dd 100644 --- a/library/Utils/build.gradle.kts +++ b/library/Utils/build.gradle.kts @@ -2,58 +2,45 @@ val pluginNamespace = "com.bylazar.utils" val pluginVersion = "1.0.4" plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("maven-publish") + id("dev.frozenmilk.android-library") version "11.1.0-1.1.1" id("com.bylazar.svelte-assets") + id("dev.frozenmilk.publish") version "0.0.5" + id("dev.frozenmilk.doc") version "0.0.5" + id("dev.frozenmilk.build-meta-data") version "0.0.2" } +android.namespace = pluginNamespace + svelteAssets { - webAppPath = "web" - buildDirPath = "dist" - assetsPath = "web/plugins/$pluginNamespace" + assetsPath = assetPathForPlugin(pluginNamespace) } -android { - namespace = pluginNamespace - - defaultConfig { - compileSdk = 34 - minSdk = 24 - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - } - } +dairyPublishing { + gitDir = file("..") +} - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } +version = "${dairyPublishing.version}+$pluginVersion" - kotlinOptions { - jvmTarget = "11" - } +meta { + packagePath = pluginNamespace + name = "Utils" + registerField("name", "String", "\"$pluginNamespace\"") + registerField("clean", "Boolean") { "${dairyPublishing.clean}" } + registerField("gitRef", "String") { "\"${dairyPublishing.gitRef}\"" } + registerField("snapshot", "Boolean") { "${dairyPublishing.snapshot}" } + registerField("version", "String") { "\"$version\"" } +} - publishing { - singleVariant("release") { - withSourcesJar() - } +ftc { + kotlin() + sdk { + compileOnly(RobotCore) + compileOnly(FtcCommon) + compileOnly(RobotServer) } } dependencies { - compileOnly("org.firstinspires.ftc:Inspection:11.0.0") - compileOnly("org.firstinspires.ftc:Blocks:11.0.0") - compileOnly("org.firstinspires.ftc:RobotCore:11.0.0") - compileOnly("org.firstinspires.ftc:RobotServer:11.0.0") - compileOnly("org.firstinspires.ftc:OnBotJava:11.0.0") - compileOnly("org.firstinspires.ftc:Hardware:11.0.0") - compileOnly("org.firstinspires.ftc:FtcCommon:11.0.0") - compileOnly("org.firstinspires.ftc:Vision:11.0.0") - compileOnly(project(":Panels")) } @@ -63,9 +50,11 @@ afterEvaluate { create("release") { from(components["release"]) - groupId = pluginNamespace.substringBeforeLast('.') + groupId = pluginNamespace.substringBeforeLast('.') + ".sloth" artifactId = pluginNamespace.substringAfterLast('.') - version = pluginVersion + + artifact(dairyDoc.dokkaJavadocJar) + artifact(dairyDoc.dokkaHtmlJar) pom { description.set("Panels Utils Plugin") @@ -82,12 +71,5 @@ afterEvaluate { } } } - - repositories { - maven { - name = "localDevRepo" - url = uri("file:///C:/Users/lazar/Documents/GitHub/ftcontrol-maven/releases") - } - } } } diff --git a/library/Utils/web/bun.lock b/library/Utils/web/bun.lock index b8db93ae..0d865e4a 100644 --- a/library/Utils/web/bun.lock +++ b/library/Utils/web/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "panels-plugin", diff --git a/library/build.gradle.kts b/library/build.gradle.kts index 44ecb6e2..232e7af1 100644 --- a/library/build.gradle.kts +++ b/library/build.gradle.kts @@ -1,33 +1,14 @@ -/** - * Top-level build file for ftc_app project. - * - * It is extraordinarily rare that you will ever need to edit this file. - */ - -buildscript { - val kotlin_version by extra("2.1.20") - - repositories { - mavenCentral() - google() - } - - dependencies { - // Note for FTC Teams: Do not modify this yourself. - classpath("com.android.tools.build:gradle:8.7.0") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") +fun makePublishAllTask(repository: String) = tasks.register("publishAllReleasePublicationsTo$repository") { + group = "Publishing" + description = "publish all release publications except ExamplePlugin to $repository" + subprojects.forEach { project -> + if (project.name == "ExamplePlugin") return@forEach + if (project.name == "TeamCode") return@forEach + if (project.name == "FtcRobotController") return@forEach + if (project.name == "plugin-svelte-assets") return@forEach + dependsOn(project.tasks.getByName("publishReleasePublicationTo$repository")) } } -// 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 { - mavenCentral() - google() - } -} - -repositories { - mavenCentral() -} +makePublishAllTask("MavenLocal") +makePublishAllTask("DairyRepository") diff --git a/library/gradle.properties b/library/gradle.properties index f5935e91..e392bd10 100644 --- a/library/gradle.properties +++ b/library/gradle.properties @@ -6,7 +6,10 @@ android.useAndroidX=true # We no longer need to auto-convert third-party libraries to use AndroidX, which slowed down the build android.enableJetifier=false -# Allow Gradle to use up to 1 GB of RAM -org.gradle.jvmargs=-Xmx1024M +# Allow Gradle to use up to 2 GB of RAM +org.gradle.jvmargs=-Xmx2048M -android.nonTransitiveRClass=false \ No newline at end of file +android.nonTransitiveRClass=false + +org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled +org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true \ No newline at end of file diff --git a/library/gradlew b/library/gradlew old mode 100644 new mode 100755 diff --git a/library/plugin-svelte-assets/build.gradle.kts b/library/plugin-svelte-assets/build.gradle.kts index 823e1a69..f375a4fa 100644 --- a/library/plugin-svelte-assets/build.gradle.kts +++ b/library/plugin-svelte-assets/build.gradle.kts @@ -12,6 +12,11 @@ repositories { mavenCentral() } +dependencies { + //noinspection AndroidGradlePluginVersion + compileOnly("com.android.tools.build:gradle:8.7.0") +} + gradlePlugin { plugins { create("svelteAssetsPlugin") { diff --git a/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/SvelteAssetsPlugin.kt b/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/SvelteAssetsPlugin.kt index 061417fa..e81f1dbb 100644 --- a/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/SvelteAssetsPlugin.kt +++ b/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/SvelteAssetsPlugin.kt @@ -1,251 +1,109 @@ package com.bylazar +import com.android.build.api.variant.LibraryAndroidComponentsExtension +import com.android.build.gradle.internal.tasks.factory.dependsOn +import com.bylazar.tasks.BunTask +import com.bylazar.tasks.InstallBunLocally import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.GradleException -import org.gradle.api.logging.LogLevel import org.gradle.api.tasks.Copy import org.gradle.api.tasks.Delete -import org.gradle.api.tasks.Exec -import org.gradle.api.services.BuildService -import org.gradle.api.services.BuildServiceParameters +import org.gradle.kotlin.dsl.register import java.io.File -import java.io.FileOutputStream -import java.io.OutputStream -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter - -open class SvelteAssetsPluginExtension { - var webAppPath: String = "web" - var buildDirPath: String = "build" - var assetsPath: String = "web" - var useNpm: Boolean = false - var maxParallelSvelteBuilds: Int = 2 -} - -abstract class SvelteSingleSlotService : - BuildService, AutoCloseable { - override fun close() {} -} - -class TeeOutputStream( - private val a: OutputStream, - private val b: OutputStream -) : OutputStream() { - override fun write(bte: Int) { - a.write(bte); b.write(bte) - } - override fun write(btes: ByteArray) { - a.write(btes); b.write(btes) - } - override fun write(btes: ByteArray, off: Int, len: Int) { - a.write(btes, off, len); b.write(btes, off, len) - } - override fun flush() { a.flush(); b.flush() } - override fun close() { a.close(); b.close() } -} - -private object StdOutStream : OutputStream() { - override fun write(b: Int) = System.out.write(b) - override fun write(b: ByteArray, off: Int, len: Int) = System.out.write(b, off, len) -} - -private object StdErrStream : OutputStream() { - override fun write(b: Int) = System.err.write(b) - override fun write(b: ByteArray, off: Int, len: Int) = System.err.write(b, off, len) -} +@Suppress("LocalVariableName", "unused") class SvelteAssetsPlugin : Plugin { override fun apply(project: Project) { - val extension = project.extensions.create("svelteAssets", SvelteAssetsPluginExtension::class.java) + val extension = + project.extensions.create("svelteAssets", SvelteAssetsPluginExtension::class.java) - project.plugins.withId("com.android.library") { - configureAfterEvaluate(project, extension) - } - project.plugins.withId("com.android.application") { - configureAfterEvaluate(project, extension) - } + val BUN_INSTALL = project.rootProject.file(".bun") - project.afterEvaluate { - if (!project.plugins.hasPlugin("com.android.library") - && !project.plugins.hasPlugin("com.android.application") - ) { - configure(project, extension) - } - } - } + val generatedAssetsDir = File( + project.layout.buildDirectory.get().asFile, + "/generated/sources/frontend/assets", + ) - private fun configureAfterEvaluate(project: Project, extension: SvelteAssetsPluginExtension) { - project.afterEvaluate { configure(project, extension) } - } + val installBunLocally = project.tasks.register("installBunLocally") - private fun configure(project: Project, extension: SvelteAssetsPluginExtension) { - val isWindows = System.getProperty("os.name").lowercase().contains("windows") - val webDir = File(project.projectDir, extension.webAppPath) - val outputDir = File(project.projectDir, "src/main/assets/${extension.assetsPath}") + project.tasks.register("uninstallBun", Delete::class.java) { + group = "frontend" + description = "Removes the project's local bun installation." + delete(BUN_INSTALL) + } + + val clearFrontendAssets = + project.tasks.register("clearFrontendAssets", Delete::class.java) { + group = "frontend" + description = "Clears frontend assets." - val singleSlot = project.gradle.sharedServices - .registerIfAbsent("svelteSingleSlot", SvelteSingleSlotService::class.java) { - maxParallelUsages.set(extension.maxParallelSvelteBuilds.coerceAtLeast(1)) + delete(generatedAssetsDir) } - val projectSuffix = project.name.replace(Regex("\\W+"), "") - .replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } + val bunBuild = project.tasks.register("bunBuild") { + val webDir = project.file(extension.webAppPath) - val installCmd = when { - extension.useNpm && isWindows -> listOf("cmd", "/c", "npm", "i") - extension.useNpm -> listOf("sh", "-c", "npm i") - !extension.useNpm && isWindows -> listOf("cmd", "/c", "bun", "i") - else -> listOf("sh", "-c", "bun i") - } - val buildCmd = when { - extension.useNpm && isWindows -> listOf("cmd", "/c", "npm", "run", "build") - extension.useNpm -> listOf("sh", "-c", "npm run build") - !extension.useNpm && isWindows -> listOf("cmd", "/c", "bun", "run", "build") - else -> listOf("sh", "-c", "bun run build") - } + group = "frontend" + description = "Installs frontend dependencies, then builds the frontend." - val clearSvelte = project.tasks.register("clearSvelteAssets$projectSuffix", Delete::class.java) { - group = "svelte" - description = "Clears web assets for ${project.path}" - val pluginsDir1 = File(project.projectDir, "src/main/assets/plugins") - if (pluginsDir1.exists()) delete(pluginsDir1.listFiles()?.toList() ?: emptyList()) - val pluginsDir2 = File(project.projectDir, "src/main/assets/${extension.assetsPath}") - if (pluginsDir2.exists()) delete(pluginsDir2.listFiles()?.toList() ?: emptyList()) - } + dependsOn(installBunLocally) - val installSvelteApp = project.tasks.register("installSvelteApp$projectSuffix", Exec::class.java) { - group = "svelte" - description = "Installs web dependencies for ${project.path} (${if (extension.useNpm) "npm" else "bun"})" - dependsOn(clearSvelte) - workingDir = webDir - commandLine = installCmd - isIgnoreExitValue = true - usesService(singleSlot) - } - attachExecLogging(project, installSvelteApp, "install") - - val buildSvelteApp = project.tasks.register("buildSvelteApp$projectSuffix", Exec::class.java) { - group = "svelte" - description = "Builds the Svelte app for ${project.path}" - dependsOn(installSvelteApp) - workingDir = webDir - commandLine = buildCmd - isIgnoreExitValue = true - usesService(singleSlot) - } - attachExecLogging(project, buildSvelteApp, "build") - - val copySvelteToAssets = project.tasks.register("copySvelteToAssets$projectSuffix", Copy::class.java) { - group = "svelte" - description = "Copies the built Svelte assets into ${outputDir.relativeTo(project.projectDir)} for ${project.path}" - dependsOn(buildSvelteApp) - from(File(webDir, extension.buildDirPath)) - into(outputDir) - } + val inputFiles = project.fileTree(webDir) { + exclude(extension.buildDirPath) + exclude("node_modules") + exclude(".panels") + exclude(".svelte-kit") + } - val buildSvelteAggregate = project.tasks.register("buildSvelte$projectSuffix") { - group = "svelte" - description = "Installs, builds, and copies Svelte assets for ${project.path}" - dependsOn(copySvelteToAssets) - usesService(singleSlot) - } + inputs.dir(inputFiles) - val root = project.rootProject - val rootTask = root.tasks.findByName("buildAllSvelte") - ?: root.tasks.create("buildAllSvelte") { - group = "svelte" - description = "Builds Svelte assets for all subprojects" - } - rootTask.dependsOn(buildSvelteAggregate) - - val extra = root.extensions.extraProperties - val keyAggregates = "svelteAggregates" - val keyWired = "svelteAggregatesWired" - - @Suppress("UNCHECKED_CAST") - val aggregates: MutableList> = - if (extra.has(keyAggregates)) { - extra.get(keyAggregates) as MutableList> - } else { - mutableListOf>().also { - extra.set(keyAggregates, it) - } - } - aggregates.add(buildSvelteAggregate) - - if (!extra.has(keyWired)) { - extra.set(keyWired, true) - root.gradle.projectsEvaluated { - @Suppress("UNCHECKED_CAST") - val allProviders = (extra.get(keyAggregates) - as MutableList>).toList() - if (allProviders.isNotEmpty()) { - val allTasks = allProviders.map { it.get() }.sortedWith( - compareBy { it.project.path }.thenBy { it.name } - ) - for (i in 1 until allTasks.size) { - allTasks[i].dependsOn(allTasks[i - 1]) - } - rootTask.setDependsOn(listOf(allTasks.last())) - } - root.tasks.matching { it.name == "publish" }.configureEach { - dependsOn(rootTask) + outputs.dir(File(webDir, extension.buildDirPath)) + outputs.dir(File(webDir, "node_modules")) + outputs.dir(File(webDir, ".panels")) + outputs.dir(File(webDir, ".svelte-kit")) + + doLast { + bunExec("bun i && bun run build") { + workingDir = webDir } } } - } - private fun attachExecLogging( - project: Project, - taskProvider: org.gradle.api.tasks.TaskProvider, - label: String - ) { - taskProvider.configure { - val relProjectPath = project.path.removePrefix(":").ifEmpty { "root" } - val safePath = relProjectPath.replace(':', '_') - val logsDir = File(project.buildDir, "svelte-logs/$safePath").also { it.mkdirs() } - - val timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss")) - val latestLog = File(logsDir, "$label.log") - val tsLog = File(logsDir, "$label-$timestamp.log") - - doFirst { - logsDir.mkdirs() - project.logger.log( - LogLevel.LIFECYCLE, - "[svelte] ${project.path} ${name}: logging to ${latestLog.relativeTo(project.projectDir)} (and ${tsLog.name})" + val copyFrontendToAssets = + project.tasks.register("copyFrontendToAssets", Copy::class.java) { + val assetsPath = requireNotNull(extension.assetsPath) { "assets path must be set" } + val outputDir = File( + generatedAssetsDir, + assetsPath, ) - val fout = FileOutputStream(latestLog, false) - val fts = FileOutputStream(tsLog, false) - val fileTee = TeeOutputStream(fout, fts) - val stdoutTee = TeeOutputStream(StdOutStream, fileTee) - val stderrTee = TeeOutputStream(StdErrStream, fileTee) - standardOutput = stdoutTee - errorOutput = stderrTee - val header = "===== ${project.path} :: $name ($label) :: $timestamp =====\n" - stdoutTee.write(header.toByteArray()) - stdoutTee.flush() + val webDir = project.file(extension.webAppPath) + + group = "frontend" + description = + "Copies the built frontend assets into ${outputDir.relativeTo(project.projectDir)}." + + dependsOn(clearFrontendAssets) + dependsOn(bunBuild) + + from(File(webDir, extension.buildDirPath)) + into(outputDir) } - doLast { - val result = executionResult.get() - val exit = result.exitValue - if (exit != 0) { - val tailLines = 200 - val lines = if (latestLog.exists()) latestLog.readLines() else emptyList() - val tail = lines.takeLast(tailLines) - project.logger.error( - "\n\u001B[31m[svelte] ${project.path} ${name} failed (exit $exit). " + - "Showing last $tailLines log lines from ${latestLog.relativeTo(project.projectDir)}:\u001B[0m" - ) - tail.forEach { project.logger.error(it) } - throw GradleException( - "[svelte] ${project.path} ${name} failed. Full log: ${latestLog.absolutePath}" - ) - } + val buildFrontend = project.tasks.register("buildFrontend") { + group = "frontend" + description = "Builds frontend assets for bundling into the library." + + dependsOn(copyFrontendToAssets) + + outputs.dir(generatedAssetsDir) + } + + project.extensions.getByType(LibraryAndroidComponentsExtension::class.java).finalizeDsl { + it.sourceSets.getByName("main") { + assets.srcDir(generatedAssetsDir) } } + + project.tasks.named("preBuild").dependsOn(buildFrontend) } } diff --git a/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/SvelteAssetsPluginExtension.kt b/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/SvelteAssetsPluginExtension.kt new file mode 100644 index 00000000..4a0fa875 --- /dev/null +++ b/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/SvelteAssetsPluginExtension.kt @@ -0,0 +1,8 @@ +package com.bylazar + +abstract class SvelteAssetsPluginExtension { + fun assetPathForPlugin(pluginNamespace: String) = "web/plugins/$pluginNamespace" + var assetsPath: String? = null + var webAppPath: String = "web" + var buildDirPath: String = "dist" +} \ No newline at end of file diff --git a/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/tasks/BunTask.kt b/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/tasks/BunTask.kt new file mode 100644 index 00000000..9ad4c61e --- /dev/null +++ b/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/tasks/BunTask.kt @@ -0,0 +1,46 @@ +package com.bylazar.tasks + +import org.gradle.api.DefaultTask +import org.gradle.api.tasks.CacheableTask +import org.gradle.api.tasks.Internal +import org.gradle.process.ExecSpec +import java.io.File + +@CacheableTask +abstract class BunTask : DefaultTask() { + companion object { + val isWindows = System.getProperty("os.name").lowercase().contains("windows") + } + + @Suppress("PropertyName") + @get:Internal + val BUN_INSTALL = project.rootProject.file(".bun") + + @get:Internal + val bunInstalledLocally + get() = (isWindows && File(BUN_INSTALL, "bin\\bun.exe").exists())// + || (!isWindows && File(BUN_INSTALL, "bin/bun").exists()) + + @get:Internal + val bunInstalled + get() = System.getenv("BUN_INSTALL") != null || bunInstalledLocally + + /** + * executes [cmd] under powershell or sh, + * with the appropriate env vars set to use the locally installed bun + * if necessary + */ + fun bunExec(cmd: String, action: ExecSpec.() -> Unit = {}) { + project.exec { + commandLine = if (isWindows) listOf("powershell", "-c", cmd) + else listOf("sh", "-c", cmd) + if (bunInstalledLocally) { + environment["BUN_INSTALL"] = BUN_INSTALL.absolutePath + environment["PATH"] = + if (isWindows) "${BUN_INSTALL.absolutePath}\\bin;${System.getenv("PATH")}" + else "${BUN_INSTALL.absolutePath}/bin:${System.getenv("PATH")}" + } + action() + } + } +} \ No newline at end of file diff --git a/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/tasks/InstallBunLocally.kt b/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/tasks/InstallBunLocally.kt new file mode 100644 index 00000000..29ddb79e --- /dev/null +++ b/library/plugin-svelte-assets/src/main/kotlin/com/bylazar/tasks/InstallBunLocally.kt @@ -0,0 +1,21 @@ +package com.bylazar.tasks + +import org.gradle.api.tasks.TaskAction + +abstract class InstallBunLocally : BunTask() { + init { + group = "frontend" + onlyIf { !bunInstalled } + } + + @TaskAction + fun installBun() { + project.exec { + commandLine = if (isWindows) listOf("powershell", "-c", "irm bun.sh/install.ps1|iex") + else listOf("sh", "-c", "curl -fsSL https://bun.com/install | bash\n") + environment["BUN_INSTALL"] = BUN_INSTALL.absolutePath + standardOutput = System.out + errorOutput = System.err + } + } +} \ No newline at end of file diff --git a/library/settings.gradle.kts b/library/settings.gradle.kts index 420e1e84..7351a904 100644 --- a/library/settings.gradle.kts +++ b/library/settings.gradle.kts @@ -2,10 +2,12 @@ pluginManagement { includeBuild("plugin-svelte-assets") repositories { gradlePluginPortal() + google() + mavenCentral() + maven("https://repo.dairy.foundation/releases") } } -include(":FtcRobotController") include(":TeamCode") include(":OpModeControl") include(":ExamplePlugin") @@ -23,4 +25,5 @@ include(":Panels") include(":Utils") include(":Pinger") include(":Graph") -include(":Lights") \ No newline at end of file +include(":Lights") +include(":CameraStream") \ No newline at end of file