דלג לתוכן הראשי

מדריך תכנות FTC Java ו-Blockly

(צילומי מסך של Blockly יגיעו בקרוב!)

וודאו שקראתם את מדריך התחלה מהירה לתכנות FTC.

Javadoc של FTC Limelight: Javadoc

דוגמה בסיסית ל-FTC: דוגמת FTC

מאגר דוגמאות מלא: מאגר דוגמאות Limelight FTC

טיפים להצלחה

  • עשו את הדבר הפשוט קודם. ב-FRC, למדנו שצוותי התוכנה הטובים ביותר משתמשים לעתים קרובות בגישות הפשוטות ביותר. לדוגמה, קבוצת FRC 2056 בשנת 2024 השתמשה בצינור צבע סטנדרטי של 90FPS במקום ברשת נוירונים כדי לעקוב אחר חלקי המשחק.

הנה דוגמה לסוג השאלה שיש לשאול כשמתחילים לתכנת: בטלאופ, האם אתם צריכים לדעת את מיקום הרובוט שלכם במגרש, או שאתם פשוט צריכים להסיט עד שהכוונת שלכם ממורכזת על תג ספציפי (strafeSpeed = result.getTx()*.03)?

מושגי מפתח

1. אתחול

אנחנו צריכים להגדיר את Limelight3A בקוד הרובוט שלנו.

import com.qualcomm.hardware.limelightvision.LLResult;
import com.qualcomm.hardware.limelightvision.LLResultTypes;
import com.qualcomm.hardware.limelightvision.LLStatus;
import com.qualcomm.hardware.limelightvision.Limelight3A;
Limelight3A limelight;

@Override
public void init() {
limelight = hardwareMap.get(Limelight3A.class, "limelight");
limelight.setPollRateHz(100); // זה קובע כמה פעמים נבקש מידע מה-Limelight (100 פעמים בשנייה)
limelight.start(); // זה אומר ל-Limelight להתחיל להסתכל!
}

2. ניהול צינורות (Pipelines)

צינורות הם כמו תוכניות קטנות שניתן להחליף מיד ומשנות את האופן שבו Limelight מסתכל על העולם. אפשר להגדיר 10 צינורות שונים בממשק האינטרנט של Limelight, כל אחד למשימה שונה. כך מחליפים ביניהם:

limelight.pipelineSwitch(0); // עבור לצינור מספר 0

זוהי פעולת "שגר ושכח". Limelight ישנה את הצינור תוך אלפיות שנייה, אך הקוד שלך לא יחכה לכך לפני שימשיך. אם ברצונך לבדוק את אינדקס הצינור הנוכחי, קרא ל-

result.getPipelineIndex()

ראה את הסעיף הבא כדי ללמוד על קבלת אובייקט LLResult.

3. קבלת ושימוש בתוצאות

LLResult הוא כמו מיכל מלא במידע על מה ש-Limelight רואה. כך אנחנו משיגים ומשתמשים במידע הזה:

LLResult result = limelight.getLatestResult();
if (result != null && result.isValid()) {
double tx = result.getTx(); // כמה רחוק המטרה שמאלה או ימינה (מעלות)
double ty = result.getTy(); // כמה רחוק המטרה למעלה או למטה (מעלות)
double ta = result.getTa(); // כמה גדולה המטרה נראית (0%-100% מהתמונה)

telemetry.addData("מיקום X של המטרה", tx);
telemetry.addData("מיקום Y של המטרה", ty);
telemetry.addData("שטח המטרה", ta);
} else {
telemetry.addData("Limelight", "אין מטרות");
}

4. תקשורת עם Python SnapScripts

אתה יכול לכתוב צינורות Python SnapScript משלך בממשק האינטרנט. השתמש במחולל ה-SnapScript מבוסס ה-LLM שלנו כדי לעזור לך לכתוב את הקוד שלך.

כך שולחים מספרים מקוד הרובוט ל-Python ומקבלים מספרים בחזרה:

// שליחת מספרים ל-Python
double[] inputs = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
limelight.updatePythonInputs(inputs);

// קבלת מספרים מ-Python
double[] pythonOutputs = result.getPythonOutput();
if (pythonOutputs != null && pythonOutputs.length > 0) {
double firstOutput = pythonOutputs[0];
telemetry.addData("פלט Python:", firstOutput);
}

5. איפה הרובוט שלי? (MegaTag 1)

Limelight יכול לעזור לגלות איפה הרובוט שלך נמצא במגרש באמצעות AprilTags. ה-Limelight שלך מגיע עם מפת AprilTag מותקנת מראש עבור המשחק הנוכחי, אבל אתה יכול לעצב ולהעלות מפות משלך באמצעות בונה המפות התלת-ממדי שלנו.

לפני שתנסה לקבל את מיקום הרובוט שלך, בצע את הפעולות הבאות:

  1. הפעל "Full 3D" בכרטיסיית "Advanced" של צינור ה-AprilTag בממשק האינטרנט.
  2. השתמש בממשק האינטרנט כדי למקם את המצלמה שלך ביחס למרכז טביעת הרגל של הרובוט שלך.

מערכת הקואורדינטות עבור botPose תואמת למערכת הקואורדינטות הסטנדרטית של FTC.

  • (0,0,0) הוא מרכז רצפת המגרש
  • עבור תצורות שאינן יהלום, 0 מעלות Yaw פירושו שברית הכחולה נמצאת בצד שמאל של הרובוט שלך, וברית האדומה נמצאת בצד ימין של הרובוט שלך.
if (result != null && result.isValid()) {
Pose3D botpose = result.getBotpose();
if (botpose != null) {
double x = botpose.getPosition().x;
double y = botpose.getPosition().y;
telemetry.addData("מיקום MT1", "(" + x + ", " + y + ")");
}
}

6. איפה הרובוט שלי? (MegaTag 2)

MegaTag 2 הוא כמו MegaTag 1, אבל הוא משלב את נתוני ה-IMU שלך לדיוק מוגבר:

// ראשית, ספר ל-Limelight לאיזה כיוון הרובוט שלך פונה
double robotYaw = imu.getAngularOrientation().firstAngle;
limelight.updateRobotOrientation(robotYaw);
if (result != null && result.isValid()) {
Pose3D botpose_mt2 = result.getBotpose_MT2();
if (botpose_mt2 != null) {
double x = botpose_mt2.getPosition().x;
double y = botpose_mt2.getPosition().y;
telemetry.addData("מיקום MT2:", "(" + x + ", " + y + ")");
}
}

7. סוגי תוצאות פנימיים

בהתאם לאופן שבו הגדרת את הצינורות שלך, תהיה לך גישה לסוגים שונים של רשימות תוצאות מפורטות בתוך אובייקט ה-LLResults ההורה.

כנראה שלא תצטרך להשתמש ברשימות תוצאות אלה. אנו ממליצים להשתמש ב-getTx(), getTy() הבסיסיים בכל פעם שאפשר.

7.1 תוצאות צבע

תוצאות צבע עוזרות למצוא מטרות צבעוניות:

List<ColorResult> colorTargets = result.getColorResults();
for (ColorResult colorTarget : colorTargets) {
double x = detection.getTargetXDegrees(); // איפה זה (שמאל-ימין)
double y = detection.getTargetYDegrees(); // איפה זה (למעלה-למטה)
double area = colorTarget.getTargetArea(); // גודל (0-100)
telemetry.addData("מטרת צבע", "תופסת " + area + "% מהתמונה");
}

7.2 תוצאות Fiducial/AprilTag

Fiducials הם סמנים מיוחדים (כמו AprilTags) שעוזרים ל-Limelight להבין איפה הוא נמצא:

List<FiducialResult> fiducials = result.getFiducialResults();
for (FiducialResult fiducial : fiducials) {
int id = fiducial.getFiducialId(); // מספר הזיהוי של ה-fiducial
double x = detection.getTargetXDegrees(); // איפה זה (שמאל-ימין)
double y = detection.getTargetYDegrees(); // איפה זה (למעלה-למטה)
double StrafeDistance_3D = fiducial.getRobotPoseTargetSpace().getY();
telemetry.addData("Fiducial " + id, "נמצא " + distance + " מטרים");
}

אם ברצונך להשתמש במידע התלת-ממדי בתוך כל FiducialResult, תוכל להשתמש בשיטות הבאות:

fiducial.getRobotPoseTargetSpace(); // מיקום הרובוט ביחס למערכת הקואורדינטות של AprilTag (השימושי ביותר)
fiducial.getCameraPoseTargetSpace(); // מיקום המצלמה ביחס ל-AprilTag (שימושי)
fiducial.getRobotPoseFieldSpace(); // מיקום הרובוט במערכת הקואורדינטות של המגרש בהתבסס על תג זה בלבד (שימושי)
fiducial.getTargetPoseCameraSpace(); // מיקום ה-AprilTag במערכת הקואורדינטות של המצלמה (לא מאוד שימושי)
fiducial.getTargetPoseRobotSpace(); // מיקום ה-AprilTag במערכת הקואורדינטות של הרובוט (לא מאוד שימושי)

7.3 תוצאות ברקוד

צינור הברקוד של Limelight טוב בזיהוי ומעקב אחר קודי QR.

List<BarcodeResult> barcodes = result.getBarcodeResults();
for (BarcodeResult barcode : barcodes) {
String data = barcode.getData(); // מה הברקוד אומר
String family = barcode.getFamily(); // איזה סוג של ברקוד זה
telemetry.addData("ברקוד", data + " (" + family + ")");
}

7.4 תוצאות מסווג

מסווגים נוירונים מאפשרים ל-Limelight לומר "אני חושב שזו תמונה של...".

List<ClassifierResult> classifications = result.getClassifierResults();
for (ClassifierResult classification : classifications) {
String className = classification.getClassName(); // מה Limelight חושב שהוא רואה
double confidence = classification.getConfidence(); // ציון ביטחון
telemetry.addData("אני רואה", className + " (" + confidence + "%)");
}

7.5 תוצאות גלאי

גלאים מוצאים אובייקטים ספציפיים ואומרים לנו איפה הם:

List<DetectorResult> detections = result.getDetectorResults();
for (DetectorResult detection : detections) {
String className = detection.getClassName(); // מה זוהה
double x = detection.getTargetXDegrees(); // איפה זה (שמאל-ימין)
double y = detection.getTargetYDegrees(); // איפה זה (למעלה-למטה)
telemetry.addData(className, "ב-(" + x + ", " + y + ") מעלות");
}

8. האם המידע טרי?

לפעמים, אנחנו רוצים לדעת את הגיל (במילישניות) של נתוני התוצאות שלנו.

long staleness = result.getStaleness();
if (staleness < 100) { // פחות מ-100 מילישניות ישן
telemetry.addData("נתונים", "טובים");
} else {
telemetry.addData("נתונים", "ישנים (" + staleness + " ms)");
}

9. מפות מגרש מותאמות אישית

אתה יכול לספר ל-Limelight על פריסת המגרש הספציפית שלך:

LLFieldMap fieldMap = new LLFieldMap(); // תצטרך למלא את זה עם נתוני המגרש
boolean success = limelight.uploadFieldmap(fieldMap, null); // null אומר להשתמש בחריץ ברירת המחדל
if (success) {
telemetry.addData("מפת מגרש", "הועלתה בהצלחה!");
} else {
telemetry.addData("מפת מגרש", "אופס, ההעלאה נכשלה");
}

10. צילום תמונות:

Limelight יכול לצלם תמונות כדי לעזור לך לאתר באגים בצינורות מחוץ למגרש:

limelight.captureSnapshot