FTC Java 和 Blockly 编程指南
(Blockly 截图即将推出!)
请确保您已阅读 FTC 编程快速入门。
Javadoc: [Javadoc 链接即将推出]
完整示例仓库: 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. 管道管理
管道就像小型的、可即时切换的程序,可以改变 Limelight 观察世界的方式。您可以在 Limelight 网页界面中设置 10 个不同的管道,每个用于不同的任务。以下是如何在它们之间切换:
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 管道。使用我们基于 LLM 的 SnapScript 生成器来帮助您编写代码。
以下是如何从机器人代码向 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 地图,但您可以使用我们的 3D 地图构建器设计和上传自己的地图。
在尝试获取机器人位置之前,请执行以下操作:
- 在网页界面的 AprilTag 管道的"高级"选项卡中启用"完全 3D"。
- 使用网页界面将相机相对于机器人足迹中心定位。
botPose 的坐标系与标准 FTC 坐标系匹配。
- (0,0,0) 是场地地板的中心
- 对于非菱形配置,0 度偏航意味着蓝色联盟在机器人的左侧,红色联盟在机器人的右侧。
if (result != null && result.isValid()) {
Pose3D botpose = result.getBotpose();
if (botpose != null) {
double x = botpose.getX();
double y = botpose.getY();
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.getX();
double y = botpose_mt2.getY();
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 基准/AprilTag 结果
基准是特殊的标记(如 AprilTags),可帮助 Limelight 确定其位置:
List<FiducialResult> fiducials = result.getFiducialResults();
for (FiducialResult fiducial : fiducials) {
int id = fiducial.getFiducialId(); // 基准的 ID 号
double x = detection.getTargetXDegrees(); // 它的位置(左右)
double y = detection.getTargetYDegrees(); // 它的位置(上下)
double StrafeDistance_3D = fiducial.getRobotPoseTargetSpace().getY();
telemetry.addData("基准 " + id, "距离 " + distance + " 米");
}
如果您想利用每个 FiducialResult 中的 3D 姿态信息,可以使用以下方法:
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 + ") 度");
}