Programación FRC con Limelight Lib (WPILib Java & C++)
- https://github.com/LimelightVision/limelightlib-wpijava
- https://github.com/LimelightVision/limelightlib-wpicpp
JavaDocs: https://limelightlib-wpijava-reference.limelightvision.io
Uso
Esta es una biblioteca de un solo archivo. Todo lo que necesitas hacer es copiar el archivo LimelightHelpers.java de la última versión (https://github.com/LimelightVision/limelightlib-wpijava/releases) en la carpeta "robot" de tu proyecto Java. No necesitas crear ningún objeto para tus Limelights - la biblioteca es simple y funcional para maximizar la facilidad de uso y la fiabilidad.
Consejos para el Éxito
- ¡Comienza con lo simple! Muchos equipos exitosos de FRC utilizan enfoques básicos de manera efectiva. Por ejemplo, el Equipo 2056 en 2024 usó una pipeline de color estándar de 90FPS en lugar de redes neuronales para el seguimiento de piezas de juego.
- Piensa en lo que realmente necesitas: ¿Necesitas localización completa en el campo, o bastaría con un simple centrado de objetivo (por ejemplo,
driveSpeed = result.getTx() * 0.03
)?
Conceptos Clave
1. Uso Básico
Cada método acepta un parámetro de nombre Limelight. Déjalo en blanco o null para usar "limelight":
// Datos básicos de objetivo
double tx = LimelightHelpers.getTX(""); // Desplazamiento horizontal desde la mira al objetivo en grados
double ty = LimelightHelpers.getTY(""); // Desplazamiento vertical desde la mira al objetivo en grados
double ta = LimelightHelpers.getTA(""); // Área del objetivo (0% a 100% de la imagen)
boolean hasTarget = LimelightHelpers.getTV(""); // ¿Tienes un objetivo válido?
double txnc = LimelightHelpers.getTXNC(""); // Desplazamiento horizontal desde el píxel/punto principal al objetivo en grados
double tync = LimelightHelpers.getTYNC(""); // Desplazamiento vertical desde el píxel/punto principal al objetivo en grados
2. Gestión de Pipelines
Los pipelines son como programas instantáneamente intercambiables que cambian cómo Limelight procesa las imágenes. Puedes configurar 10 pipelines diferentes en la interfaz web:
// Cambiar al pipeline 0
LimelightHelpers.setPipelineIndex("", 0);
3. Control de LED
Para Limelights con LEDs de iluminación brillante, puedes controlar los LEDs para diferentes situaciones:
// Dejar que el pipeline actual controle los LEDs
LimelightHelpers.setLEDMode_PipelineControl("");
// Forzar LEDs encendido/apagado/parpadeo
LimelightHelpers.setLEDMode_ForceOn("");
LimelightHelpers.setLEDMode_ForceOff("");
LimelightHelpers.setLEDMode_ForceBlink("");
4. Localización en Campo Con MegaTag
(Ver la documentación de MegaTag y el Tutorial de Estimación de Pose Swerve para más detalles.)
// En tu función periódica:
LimelightHelpers.PoseEstimate limelightMeasurement = LimelightHelpers.getBotPoseEstimate_wpiBlue("limelight");
if (limelightMeasurement.tagCount >= 2) { // Solo confiar en la medición si vemos múltiples tags
m_poseEstimator.setVisionMeasurementStdDevs(VecBuilder.fill(0.7, 0.7, 9999999));
m_poseEstimator.addVisionMeasurement(
limelightMeasurement.pose,
limelightMeasurement.timestampSeconds
);
}
5. Localización en Campo Con MegaTag2
(Ver la documentación de MegaTag2 y el Tutorial de Estimación de Pose Swerve para más detalles.)
MegaTag2 mejora la precisión de localización fusionando los datos de orientación del robot con la visión. Al proporcionar datos del giroscopio, ayudas a MegaTag2 a restringir el problema de localización y proporcionar excelentes resultados incluso si solo hay un tag visible:
// Primero, dile a Limelight la orientación actual de tu robot
double robotYaw = m_gyro.getYaw();
LimelightHelpers.SetRobotOrientation("", robotYaw, 0.0, 0.0, 0.0, 0.0, 0.0);
// Obtener la estimación de pose
LimelightHelpers.PoseEstimate limelightMeasurement = LimelightHelpers.getBotPoseEstimate_wpiBlue("");
// Añadirla a tu estimador de pose
m_poseEstimator.setVisionMeasurementStdDevs(VecBuilder.fill(.5, .5, 9999999));
m_poseEstimator.addVisionMeasurement(
limelightMeasurement.pose,
limelightMeasurement.timestampSeconds
);
6. Funcionalidad Especial de AprilTag
// Establecer una ventana de recorte personalizada para mejor rendimiento (-1 a 1 para cada valor)
LimelightHelpers.setCropWindow("", -0.5, 0.5, -0.5, 0.5);
// Cambiar la pose de la cámara relativa al centro del robot (x adelante, y izquierda, z arriba, grados)
LimelightHelpers.setCameraPose_RobotSpace("",
0.5, // Desplazamiento hacia adelante (metros)
0.0, // Desplazamiento lateral (metros)
0.5, // Desplazamiento de altura (metros)
0.0, // Rotación (grados)
30.0, // Inclinación (grados)
0.0 // Guiñada (grados)
);
// Establecer punto de seguimiento de desplazamiento AprilTag (metros)
LimelightHelpers.setFiducial3DOffset("",
0.0, // Desplazamiento hacia adelante
0.0, // Desplazamiento lateral
0.5 // Desplazamiento de altura
);
// Configurar detección de AprilTag
LimelightHelpers.SetFiducialIDFiltersOverride("", new int[]{1, 2, 3, 4}); // Solo seguir estos IDs de tag
LimelightHelpers.SetFiducialDownscalingOverride("", 2.0f); // Procesar a mitad de resolución para mejor velocidad de cuadros y rango reducido
7. Integración con Python
Comunicarse con SnapScripts personalizados de Python:
// Enviar datos a Python
double[] dataToSend = {1.0, 2.0, 3.0};
LimelightHelpers.setPythonScriptData("", dataToSend);
// Obtener datos de Python
double[] dataFromPython = LimelightHelpers.getPythonScriptData("");
8. Obtener Resultados Detallados De NetworkTables (RawTargets)
Para máximo rendimiento, puedes acceder a datos brutos de objetivos directamente desde NetworkTables, evitando el análisis JSON:
// Obtener datos brutos de AprilTag/Fiducial
RawFiducial[] fiducials = LimelightHelpers.getRawFiducials("");
for (RawFiducial fiducial : fiducials) {
int id = fiducial.id; // ID del Tag
double txnc = fiducial.txnc; // Desplazamiento X (sin mira)
double tync = fiducial.tync; // Desplazamiento Y (sin mira)
double ta = fiducial.ta; // Área del objetivo
double distToCamera = fiducial.distToCamera; // Distancia a la cámara
double distToRobot = fiducial.distToRobot; // Distancia al robot
double ambiguity = fiducial.ambiguity; // Ambigüedad de pose del tag
}
// Obtener resultados brutos del detector neural
RawDetection[] detections = LimelightHelpers.getRawDetections("");
for (RawDetection detection : detections) {
int classID = detection.classId;
double txnc = detection.txnc;
double tync = detection.tync;
double ta = detection.ta;
// Acceder a coordenadas de esquinas si es necesario
double corner0X = detection.corner0_X;
double corner0Y = detection.corner0_Y;
// ... esquinas 1-3 disponibles similarmente
}
9. Obtener Resultados Detallados De JSON (Objeto Results)
El objeto Results proporciona acceso completo a todos los tipos de datos de Limelight. Puede tomar hasta 2 ms para analizar en el RoboRIO, por lo que no recomendamos usar este enfoque en FRC:
LimelightResults results = LimelightHelpers.getLatestResults("");
if (results.valid) {
// Objetivos de Color/Retroreflectivos
if (results.targets_Retro.length > 0) {
LimelightTarget_Retro target = results.targets_Retro[0];
double skew = target.ts; // Inclinación/rotación del objetivo
double shortSide = target.short_side; // Lado más corto en píxeles
double longSide = target.long_side; // Lado más largo en píxeles
Pose3d targetPose = target.getCameraPose_TargetSpace();
}
// AprilTags/Fiduciales
if (results.targets_Fiducials.length > 0) {
LimelightTarget_Fiducial tag = results.targets_Fiducials[0];
double id = tag.fiducialID; // ID del Tag
String family = tag.fiducialFamily; // Familia del tag (ej., "16h5")
// Datos de Pose 3D
Pose3d robotPoseField = tag.getRobotPose_FieldSpace(); // Pose del robot en espacio de campo
Pose3d cameraPoseTag = tag.getCameraPose_TargetSpace(); // Pose de la cámara relativa al tag
Pose3d robotPoseTag = tag.getRobotPose_TargetSpace(); // Pose del robot relativa al tag
Pose3d tagPoseCamera = tag.getTargetPose_CameraSpace(); // Pose del tag relativa a la cámara
Pose3d tagPoseRobot = tag.getTargetPose_RobotSpace(); // Pose del tag relativa al robot
// Datos de objetivo 2D
double tx = tag.tx; // Desplazamiento horizontal desde la mira
double ty = tag.ty; // Desplazamiento vertical desde la mira
double ta = tag.ta; // Área del objetivo (0-100% de la imagen)
}
// Detecciones de red neuronal
if (results.targets_Detector.length > 0) {
LimelightTarget_Detector detection = results.targets_Detector[0];
String className = detection.className;
double confidence = detection.confidence;
double area = detection.ta;
}
// Resultados del clasificador
if (results.targets_Classifier.length > 0) {
LimelightTarget_Classifier result = results.targets_Classifier[0];
String class_name = result.className;
double confidence = result.confidence;
int classID = (int)result.classID;
}
// Resultados de código de barras/QR
if (results.targets_Barcode.length > 0) {
LimelightTarget_Barcode barcode = results.targets_Barcode[0];
String data = barcode.data;
String family = barcode.family;
}
}
10. Gestión de Capturas
Tomar capturas para ajuste de pipeline fuera de línea:
// Tomar una captura para verla más tarde en la interfaz web
LimelightHelpers.takeSnapshot("", "auto_shot_1");
11. Funcionalidad Miscelánea
// Cambiar modos de transmisión
LimelightHelpers.setStreamMode_Standard(""); // Transmisiones lado a lado
LimelightHelpers.setStreamMode_PiPMain(""); // Transmisión secundaria en esquina
LimelightHelpers.setStreamMode_PiPSecondary(""); // Transmisión primaria en esquina
Métodos Estáticos de LimelightHelpers
Datos del Objetivo
public static boolean getTV(String limelightName)
public static double getTX(String limelightName)
public static double getTY(String limelightName)
public static double getTXNC(String limelightName)
public static double getTYNC(String limelightName)
public static double getTA(String limelightName)
public static double[] getT2DArray(String limelightName)
public static int getTargetCount(String limelightName)
public static RawFiducial[] getRawFiducials(String limelightName)
public static RawDetection[] getRawDetections(String limelightName)
Resultados de Red Neuronal
public static int getClassifierClassIndex(String limelightName)
public static int getDetectorClassIndex(String limelightName)
public static String getClassifierClass(String limelightName)
public static String getDetectorClass(String limelightName)
Estimación de Pose
public static PoseEstimate getBotPoseEstimate_wpiBlue(String limelightName)
public static PoseEstimate getBotPoseEstimate_wpiRed(String limelightName)
public static PoseEstimate getBotPoseEstimate_wpiBlue_MegaTag2(String limelightName)
public static PoseEstimate getBotPoseEstimate_wpiRed_MegaTag2(String limelightName)
public static Pose3d getBotPose3d(String limelightName)
public static Pose3d getBotPose3d_wpiRed(String limelightName)
public static Pose3d getBotPose3d_wpiBlue(String limelightName)
public static Pose3d getBotPose3d_TargetSpace(String limelightName)
public static Pose3d getCameraPose3d_TargetSpace(String limelightName)
public static Pose3d getTargetPose3d_CameraSpace(String limelightName)
public static Pose3d getTargetPose3d_RobotSpace(String limelightName)
public static Pose3d getCameraPose3d_RobotSpace(String limelightName)
public static Pose2d getBotPose2d(String limelightName)
public static Pose2d getBotPose2d_wpiBlue(String limelightName)
public static Pose2d getBotPose2d_wpiRed(String limelightName)
public static double[] getBotPose(String limelightName)
public static double[] getBotPose_wpiRed(String limelightName)
public static double[] getBotPose_wpiBlue(String limelightName)
public static double[] getBotPose_TargetSpace(String limelightName)
public static double[] getCameraPose_TargetSpace(String limelightName)
public static double[] getTargetPose_CameraSpace(String limelightName)
public static double[] getTargetPose_RobotSpace(String limelightName)
Configuración de Cámara/Pipeline
public static void setPipelineIndex(String limelightName, int pipelineIndex)
public static void setPriorityTagID(String limelightName, int ID)
public static double getCurrentPipelineIndex(String limelightName)
public static String getCurrentPipelineType(String limelightName)
public static void setLEDMode_PipelineControl(String limelightName)
public static void setLEDMode_ForceOff(String limelightName)
public static void setLEDMode_ForceBlink(String limelightName)
public static void setLEDMode_ForceOn(String limelightName)
public static void setStreamMode_Standard(String limelightName)
public static void setStreamMode_PiPMain(String limelightName)
public static void setStreamMode_PiPSecondary(String limelightName)
public static void setCropWindow(String limelightName, double cropXMin, double cropXMax, double cropYMin, double cropYMax)
public static void setCameraPose_RobotSpace(String limelightName, double forward, double side, double up, double roll, double pitch, double yaw)
Configuración Avanzada de AprilTag/Fiducial
public static void setFiducial3DOffset(String limelightName, double offsetX, double offsetY, double offsetZ)
public static void SetRobotOrientation(String limelightName, double yaw, double yawRate, double pitch, double pitchRate, double roll, double rollRate)
public static void SetFiducialIDFiltersOverride(String limelightName, int[] validIDs)
public static void SetFiducialDownscalingOverride(String limelightName, float downscale)
Resultados y Acceso a Datos
public static double getLatency_Pipeline(String limelightName)
public static double getLatency_Capture(String limelightName)
public static double[] getTargetColor(String limelightName)
public static double getFiducialID(String limelightName)
public static String getNeuralClassID(String limelightName)
public static String[] getRawBarcodeData(String limelightName)
public static String getJSONDump(String limelightName)
public static LimelightResults getLatestResults(String limelightName)
Interfaz de Script Python
public static void setPythonScriptData(String limelightName, double[] outgoingPythonData)
public static double[] getPythonScriptData(String limelightName)
Métodos de Utilidad
public static CompletableFuture<Boolean> takeSnapshot(String tableName, String snapshotName)
public static NetworkTable getLimelightNTTable(String tableName)
public static NetworkTableEntry getLimelightNTTableEntry(String tableName, String entryName)
public static double getLimelightNTDouble(String tableName, String entryName)
public static void setLimelightNTDouble(String tableName, String entryName, double val)
public static void setLimelightNTDoubleArray(String tableName, String entryName, double[] val)
public static double[] getLimelightNTDoubleArray(String tableName, String entryName)
public static String getLimelightNTString(String tableName, String entryName)
public static URL getLimelightURLString(String tableName, String request)
Clases Principales
PoseEstimate
Representa una Estimación de Pose 3D
Propiedades Públicas:
Pose2d pose
- La pose estimadadouble timestampSeconds
- Marca de tiempo de la estimacióndouble latency
- Latencia de procesamientoint tagCount
- Número de tags utilizadosdouble tagSpan
- Separación entre tags detectadosdouble avgTagDist
- Distancia promedio a los tagsdouble avgTagArea
- Área promedio de los tagsRawFiducial[] rawFiducials
- Detecciones de fiduciales sin procesarboolean isMegaTag2
- Si este es un resultado de MegaTag2
(Derivado de NetworkTables) RawFiducial
Representa datos de detección de AprilTag/Fiducial sin procesar
Propiedades Públicas:
int id
- Número ID del AprilTagdouble txnc
- Desplazamiento horizontal desde el centro de la cámara en gradosdouble tync
- Desplazamiento vertical desde el centro de la cámara en gradosdouble ta
- Área del objetivo (0-100% de la imagen)double distToCamera
- Distancia de la cámara al objetivo en metrosdouble distToRobot
- Distancia del robot al objetivo en metrosdouble ambiguity
- Puntuación de ambigüedad de pose del AprilTag
(Derivado de NetworkTables) RawDetection
Representa datos de detección de red neuronal sin procesar
Propiedades Públicas:
int classId
- ID de clase de la red neuronaldouble txnc
- Desplazamiento horizontal desde el centro de la cámara en gradosdouble tync
- Desplazamiento vertical desde el centro de la cámara en gradosdouble ta
- Área del objetivo (0-100% de la imagen)double corner0_X
- Coordenada X de la primera esquinadouble corner0_Y
- Coordenada Y de la primera esquinadouble corner1_X
- Coordenada X de la segunda esquinadouble corner1_Y
- Coordenada Y de la segunda esquinadouble corner2_X
- Coordenada X de la tercera esquinadouble corner2_Y
- Coordenada Y de la tercera esquinadouble corner3_X
- Coordenada X de la cuarta esquinadouble corner3_Y
- Coordenada Y de la cuarta esquina
(Derivado de JSON) LimelightResults
Contiene todos los resultados de la salida JSON de un Limelight
Propiedades Públicas:
String error
- Mensaje de error si existedouble pipelineID
- Índice de pipeline actualdouble latency_pipeline
- Latencia de procesamiento del pipeline (ms)double latency_capture
- Latencia de captura de imagen (ms)double latency_jsonParse
- Latencia de análisis JSON (ms)double timestamp_LIMELIGHT_publish
- Marca de tiempo cuando se publicaron los datosdouble timestamp_RIOFPGA_capture
- Marca de tiempo cuando el FPGA RoboRIO capturó los datosboolean valid
- Si el objetivo es válidodouble[] botpose
- Pose del robot en el espacio del campodouble[] botpose_wpired
- Pose del robot en el espacio de alianza Roja WPILibdouble[] botpose_wpiblue
- Pose del robot en el espacio de alianza Azul WPILibdouble botpose_tagcount
- Número de tags usados para la estimación de posedouble botpose_span
- Separación entre tags detectadosdouble botpose_avgdist
- Distancia promedio a los tags detectadosdouble botpose_avgarea
- Área promedio de los tags detectadosdouble[] camerapose_robotspace
- Pose de la cámara relativa al robotLimelightTarget_Retro[] targets_Retro
- Array de objetivos retroreflectivosLimelightTarget_Fiducial[] targets_Fiducials
- Array de objetivos AprilTagLimelightTarget_Classifier[] targets_Classifier
- Array de resultados del clasificadorLimelightTarget_Detector[] targets_Detector
- Array de resultados del detectorLimelightTarget_Barcode[] targets_Barcode
- Array de resultados de códigos de barras
Métodos Públicos:
Pose3d getBotPose3d()
Pose3d getBotPose3d_wpiRed()
Pose3d getBotPose3d_wpiBlue()
Pose2d getBotPose2d()
Pose2d getBotPose2d_wpiRed()
Pose2d getBotPose2d_wpiBlue()
(Derivado de JSON) LimelightTarget_Retro
Representa un Resultado de Objetivo Color/Retroreflectivo
Propiedades Públicas:
double ta
- Área del objetivo (0-100% de la imagen)double tx
- Desplazamiento horizontal desde la mira al objetivo (-29.8 a 29.8 grados)double ty
- Desplazamiento vertical desde la mira al objetivo (-24.85 a 24.85 grados)double tx_pixels
- Desplazamiento horizontal en píxelesdouble ty_pixels
- Desplazamiento vertical en píxelesdouble tx_nocrosshair
- Desplazamiento horizontal desde el centro de la cámaradouble ty_nocrosshair
- Desplazamiento vertical desde el centro de la cámaradouble ts
- Inclinación o rotación del objetivo (-90 a 0 grados)
Métodos Públicos:
Pose3d getCameraPose_TargetSpace()
Pose3d getRobotPose_FieldSpace()
Pose3d getRobotPose_TargetSpace()
Pose3d getTargetPose_CameraSpace()
Pose3d getTargetPose_RobotSpace()
Pose2d getCameraPose_TargetSpace2D()
Pose2d getRobotPose_FieldSpace2D()
Pose2d getRobotPose_TargetSpace2D()
Pose2d getTargetPose_CameraSpace2D()
Pose2d getTargetPose_RobotSpace2D()
(Derivado de JSON) LimelightTarget_Fiducial
Representa un Resultado de Objetivo AprilTag/Fiducial
Propiedades Públicas:
double fiducialID
- Número ID del AprilTagString fiducialFamily
- Tipo de familia AprilTag- Todas las propiedades de LimelightTarget_Retro
Métodos Públicos:
- Todos los métodos de LimelightTarget_Retro
(Derivado de JSON) LimelightTarget_Barcode
Representa un Resultado de Objetivo de Código de Barras
Propiedades Públicas:
String family
- Tipo de familia del código de barras (ej. "QR", "DataMatrix")String data
- Contenido decodificado del código de barrasdouble tx_pixels
- Desplazamiento horizontal en píxelesdouble ty_pixels
- Desplazamiento vertical en píxelesdouble tx
- Desplazamiento horizontal desde la miradouble ty
- Desplazamiento vertical desde la miradouble tx_nocrosshair
- Desplazamiento horizontal desde el centro de la cámaradouble ty_nocrosshair
- Desplazamiento vertical desde el centro de la cámaradouble ta
- Área del objetivodouble[][] corners
- Coordenadas de las esquinas
Métodos Públicos:
String getFamily()
(Derivado de JSON) LimelightTarget_Classifier
Representa un Resultado de Pipeline de Clasificador Neural
Propiedades Públicas:
String className
- Nombre de la clase detectadadouble classID
- Número ID de la clase detectadadouble confidence
- Confianza de la detección (0-100%)double zone
- Zona de deteccióndouble tx
- Desplazamiento horizontal desde la miradouble ty
- Desplazamiento vertical desde la miradouble txp
- Desplazamiento horizontal en píxelesdouble typ
- Desplazamiento vertical en píxeles
(Derivado de JSON) LimelightTarget_Detector
Representa un Resultado de Pipeline de Detector Neural
Propiedades Públicas:
String className
- Nombre de la clase detectadadouble classID
- Número ID de la clase detectadadouble confidence
- Confianza de la detección (0-100%)double ta
- Área del objetivodouble tx
- Desplazamiento horizontal desde la miradouble ty
- Desplazamiento vertical desde la miradouble txp
- Desplazamiento horizontal en píxelesdouble typ
- Desplazamiento vertical en píxelesdouble tx_nocrosshair
- Desplazamiento horizontal desde el centro de la cámaradouble ty_nocrosshair
- Desplazamiento vertical desde el centro de la cámara