· 6 years ago · Sep 25, 2019, 02:06 AM
1/* Copyright (c) 2019 FIRST. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without modification,
4 * are permitted (subject to the limitations in the disclaimer below) provided that
5 * the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this list
8 * of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution.
13 *
14 * Neither the name of FIRST nor the names of its contributors may be used to endorse or
15 * promote products derived from this software without specific prior written permission.
16 *
17 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS
18 * LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30package org.firstinspires.ftc.robotcontroller.external.samples;
31
32import com.qualcomm.robotcore.eventloop.opmode.Disabled;
33import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
34import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
35import java.util.List;
36import org.firstinspires.ftc.robotcore.external.ClassFactory;
37import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName;
38import org.firstinspires.ftc.robotcore.external.navigation.VuforiaLocalizer;
39import org.firstinspires.ftc.robotcore.external.tfod.TFObjectDetector;
40import org.firstinspires.ftc.robotcore.external.tfod.Recognition;
41
42/**
43 * This 2019-2020 OpMode illustrates the basics of using the TensorFlow Object Detection API to
44 * determine the position of the Skystone game elements.
45 *
46 * Use Android Studio to Copy this Class, and Paste it into your team's code folder with a new name.
47 * Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list.
48 *
49 * IMPORTANT: In order to use this OpMode, you need to obtain your own Vuforia license key as
50 * is explained below.
51 */
52@TeleOp(name = "Concept: TensorFlow Object Detection Webcam", group = "Concept")
53@Disabled
54public class ConceptTensorFlowObjectDetectionWebcam extends LinearOpMode {
55 private static final String TFOD_MODEL_ASSET = "Skystone.tflite";
56 private static final String LABEL_FIRST_ELEMENT = "Stone";
57 private static final String LABEL_SECOND_ELEMENT = "Skystone";
58
59 /*
60 * IMPORTANT: You need to obtain your own license key to use Vuforia. The string below with which
61 * 'parameters.vuforiaLicenseKey' is initialized is for illustration only, and will not function.
62 * A Vuforia 'Development' license key, can be obtained free of charge from the Vuforia developer
63 * web site at https://developer.vuforia.com/license-manager.
64 *
65 * Vuforia license keys are always 380 characters long, and look as if they contain mostly
66 * random data. As an example, here is a example of a fragment of a valid key:
67 * ... yIgIzTqZ4mWjk9wd3cZO9T1axEqzuhxoGlfOOI2dRzKS4T0hQ8kT ...
68 * Once you've obtained a license key, copy the string from the Vuforia web site
69 * and paste it in to your code on the next line, between the double quotes.
70 */
71 private static final String VUFORIA_KEY =
72 " -- YOUR NEW VUFORIA KEY GOES HERE --- ";
73
74 /**
75 * {@link #vuforia} is the variable we will use to store our instance of the Vuforia
76 * localization engine.
77 */
78 private VuforiaLocalizer vuforia;
79
80 /**
81 * {@link #tfod} is the variable we will use to store our instance of the TensorFlow Object
82 * Detection engine.
83 */
84 private TFObjectDetector tfod;
85
86 @Override
87 public void runOpMode() {
88 // The TFObjectDetector uses the camera frames from the VuforiaLocalizer, so we create that
89 // first.
90 initVuforia();
91
92 if (ClassFactory.getInstance().canCreateTFObjectDetector()) {
93 initTfod();
94 } else {
95 telemetry.addData("Sorry!", "This device is not compatible with TFOD");
96 }
97
98 /**
99 * Activate TensorFlow Object Detection before we wait for the start command.
100 * Do it here so that the Camera Stream window will have the TensorFlow annotations visible.
101 **/
102 if (tfod != null) {
103 tfod.activate();
104 }
105
106 /** Wait for the game to begin */
107 telemetry.addData(">", "Press Play to start op mode");
108 telemetry.update();
109 waitForStart();
110
111 if (opModeIsActive()) {
112 while (opModeIsActive()) {
113 if (tfod != null) {
114 // getUpdatedRecognitions() will return null if no new information is available since
115 // the last time that call was made.
116 List<Recognition> updatedRecognitions = tfod.getUpdatedRecognitions();
117 if (updatedRecognitions != null) {
118 telemetry.addData("# Object Detected", updatedRecognitions.size());
119 // step through the list of recognitions and display boundary info.
120 int i = 0;
121 for (Recognition recognition : updatedRecognitions) {
122 telemetry.addData(String.format("label (%d)", i), recognition.getLabel());
123 telemetry.addData(String.format(" left,top (%d)", i), "%.03f , %.03f",
124 recognition.getLeft(), recognition.getTop());
125 telemetry.addData(String.format(" right,bottom (%d)", i), "%.03f , %.03f",
126 recognition.getRight(), recognition.getBottom());
127 }
128 telemetry.update();
129 }
130 }
131 }
132 }
133
134 if (tfod != null) {
135 tfod.shutdown();
136 }
137 }
138
139 /**
140 * Initialize the Vuforia localization engine.
141 */
142 private void initVuforia() {
143 /*
144 * Configure Vuforia by creating a Parameter object, and passing it to the Vuforia engine.
145 */
146 VuforiaLocalizer.Parameters parameters = new VuforiaLocalizer.Parameters();
147
148 parameters.vuforiaLicenseKey = VUFORIA_KEY;
149 parameters.cameraName = hardwareMap.get(WebcamName.class, "Webcam 1");
150
151 // Instantiate the Vuforia engine
152 vuforia = ClassFactory.getInstance().createVuforia(parameters);
153
154 // Loading trackables is not necessary for the TensorFlow Object Detection engine.
155 }
156
157 /**
158 * Initialize the TensorFlow Object Detection engine.
159 */
160 private void initTfod() {
161 int tfodMonitorViewId = hardwareMap.appContext.getResources().getIdentifier(
162 "tfodMonitorViewId", "id", hardwareMap.appContext.getPackageName());
163 TFObjectDetector.Parameters tfodParameters = new TFObjectDetector.Parameters(tfodMonitorViewId);
164 tfodParameters.minimumConfidence = 0.8;
165 tfod = ClassFactory.getInstance().createTFObjectDetector(tfodParameters, vuforia);
166 tfod.loadModelFromAsset(TFOD_MODEL_ASSET, LABEL_FIRST_ELEMENT, LABEL_SECOND_ELEMENT);
167 }
168}