Skip to content
FRC Article 11 min read

How to Set Up a Limelight on Your FRC Robot (Wiring, Pipelines, AprilTags)

Set up a Limelight on your FRC robot: wiring, power, static IP networking, the web UI, building pipelines, AprilTag botpose, and NetworkTables in Java.

to read
11 min

to read

words
2,438

words

sections
11

sections

A Limelight is the fastest way to give an FRC robot eyes. It is a self-contained smart camera: an image sensor, a small Linux computer, and LEDs in one housing that runs vision pipelines on-board and publishes results to your robot over NetworkTables. You do not process pixels in your roboRIO code — you read a handful of numbers like "how far left is the target" and "where am I on the field," and act on them. That trade of flexibility for speed is exactly why so many teams reach for one when they need aiming or AprilTag localization working before their next event.

This guide walks the whole setup end to end: choosing and mounting the camera, powering and networking it, first configuration in the web UI, building a pipeline, standing up AprilTag pose estimation with MegaTag, and finally reading the values in your Java code. Everything here is checked against the current Limelight documentation as of the 2026 season. Where a detail is model- or firmware-specific, it is called out so you can confirm against the docs for your exact hardware.

Pick the right model

Limelight has shipped several generations — Limelight 1, 2/2+, 3, 3A, 3G, and 4. For AprilTag-heavy games the meaningful split is between the color-capable models and the monochrome long-range models:

  • Limelight 3 / 4 use a color sensor, which you need for any color- or game-piece detection pipeline as well as AprilTags.
  • Limelight 3G uses an OV9281 global-shutter monochrome sensor with a narrower 82° horizontal field of view and a replaceable M12 lens, tuned for accurate long-range AprilTag tracking (up to 50 fps at 640x480). Being monochrome, it is a poor choice if you also want color pipelines.

The exact FOV, sensor, and on-board IMU details differ per model and are version-specific — check the hardware comparison page in the Limelight docs before you buy. If you are still deciding between platforms entirely, our Limelight vs PhotonVision comparison breaks down the trade-offs.

Mounting

Mounting quality determines how much you can trust the numbers coming back. A camera that flexes or vibrates produces noisy tx/ty readings and, worse, unstable pose estimates.

Mounting tips: Bolt the Limelight to a rigid part of the frame or superstructure, not to thin sheet metal or anything that oscillates when the robot drives. Aim it so your primary targets sit in the center third of the frame at typical scoring range. A slight upward tilt often helps see AprilTags on field walls without catching ceiling glare.

For AprilTag localization, the physical position of the camera relative to your robot's center matters just as much as rigidity, because the Limelight uses it to convert what the camera sees into where the robot is. Measure that offset carefully in meters and degrees — you will enter it in the web UI later. Getting it wrong by a few centimeters shifts every pose estimate by the same amount.

Power and wiring

Limelights run on your robot's 12V system, but not directly off an unprotected battery lead. The documented method is to run two 18-20 AWG wires from the camera's power leads to an open slot on your PDP/PDH, protected by a 5A breaker in that slot.

The input range is 4.1V-16V on current models (the 2025 "red button" variant accepts 4.1V-24V, with a 30V absolute maximum). That range comfortably covers a normal FRC battery, but it is why you should never feed it through a boost regulator or an unfused tap.

Limelights can also be powered over Ethernet using a passive PoE injector on the network run — support and connectors vary by model, so confirm the exact scheme for your unit on the Limelight wiring page before cutting anything.

Wiring tip: Keep the Ethernet run to the radio short and strain-relieved. A flaky Ethernet connection is the single most common cause of "the Limelight disappears mid-match." Note that the Limelight talks over Ethernet, not the CAN bus — it does not share the CAN chain with your motor controllers.

Networking: team number and static IP

The Limelight joins your robot's network and speaks NetworkTables. Limelight OS runs a NetworkTables 4 client that auto-connects to the NT4 server on your robot based on the team number you set in the web UI's Settings tab. All of its data is published to a table named after the device (default: limelight).

Set a static IP rather than relying on DHCP. The docs recommend this because a static IP shaves several seconds off boot time and sidesteps DHCP/mDNS problems that teams have historically hit on real FRC fields with event radio firmware. Configure it in Settings as:

  • IP: 10.TE.AM.11 — replace TE.AM with your team number (team 916 → 10.9.16.11)
  • Netmask: 255.255.255.0
  • Gateway: 10.TE.AM.1

The .11 is a convention that keeps the Limelight clear of the roboRIO (.2) and radio (.1); if you run multiple Limelights, give each its own address and its own device name.

First boot: the web interface

Power the robot, connect to the same network, and open the Limelight dashboard at http://limelight.local:5801, or at http://<your-static-ip>:5801 once you have set one. You can also launch the Limelight Hardware Manager to scan for devices on the network. If the camera is brand new, use the Hardware Manager's Flash OS tab over a USB-C cable to image it with the latest Limelight OS before anything else.

The dashboard shows a live camera feed, the current pipeline's tuning controls on the side panels, and the live NetworkTables values at the bottom. This is where you will spend most of your setup time. A second stream is available at http://<ip>:5800 for putting the feed on a driver-station dashboard like Shuffleboard or Elastic.

Build your first pipeline

A pipeline is a saved set of vision settings. The Limelight stores up to 10 (indices 0-9), and you switch between them at runtime by writing the pipeline key. Each pipeline has a type, and the two you will use most are:

  • Color / retroreflective — HSV thresholding to find a colored blob or a retroreflective strip lit by the LEDs. You tune hue/saturation/value ranges until only the target is highlighted, then filter by area, aspect ratio, and fullness to reject noise. Output is tx, ty, ta, and tv.
  • AprilTag / fiducial — detects the field's AprilTags by ID. This is the modern default for most tasks: tags give you tx/ty to a specific ID and full 3D field localization.

To build a color pipeline, put a target in view, drop the exposure until the image is dark except for your lit target, then widen the HSV thresholds just enough to cover the target under match lighting. Lower exposure is your friend — it cuts ambient light and makes thresholding stable. Save it to a pipeline index and note that index for your code.

AprilTags and botpose

For AprilTag work, set pipeline 0 to the AprilTag type and enable its 3D/localization functionality. Then do two things in the web UI:

  1. Upload the field map (the season's .fmap) so the Limelight knows where every tag lives on the field.
  2. Enter the camera's pose relative to robot center — the offset you measured while mounting. This is what lets the camera report the robot's location instead of just the camera's.

With both set, the Limelight computes botpose: your robot's position and rotation in field space, published as an array of x, y, z (meters) and roll, pitch, yaw (degrees) plus latency data. For 2024 and later, always use the blue-origin variant — botpose_wpiblue — because WPILib and path-planning tools standardize on a blue-corner field origin regardless of alliance. Our AprilTags explainer covers the tag families and field layout in more depth.

MegaTag vs MegaTag2

Limelight offers two localization solvers:

  • MegaTag (MT1) derives the full pose — including heading — from the tag geometry alone. It works, but a single tag viewed head-on can be ambiguous, producing two plausible poses that flip back and forth.
  • MegaTag2 (MT2) assumes you already know your heading and feeds it in from your gyro. Because yaw is fixed, MT2 resolves the ambiguity, stays accurate from a single tag at any distance, and tolerates image noise and slight tag-placement error far better. It is the recommended solver for 2024+.

MT2's cost is one obligation: you must call SetRobotOrientation(name, yaw, 0,0,0,0,0) every loop before you read the estimate, so the camera has a current heading. Read the result from botpose_orb_wpiblue (or getBotPoseEstimate_wpiBlue_MegaTag2() in code). The 3G and 4 can fuse an external/on-board IMU for even steadier MT2 headings.

NetworkTables values you will read

Everything the Limelight knows shows up as keys in its NetworkTables table. These are the ones you will actually use:

KeyMeaningNotes
tvValid target?1 if a target exists, 0 if not
txHorizontal offset to targetDegrees, negative = target is left of crosshair (~±29.8° on LL2-class lenses)
tyVertical offset to targetDegrees; pair with a known height to estimate distance
taTarget areaPercent of the image, 0-100; a rough distance proxy
tlPipeline latencyMilliseconds; add capture latency cl for the total
tidPrimary AprilTag IDThe in-view tag the solver is keyed on
getpipeActive pipeline index0-9, the pipeline currently running
botpose_wpiblueRobot pose, blue origin[x, y, z, roll, pitch, yaw, latency, …]; MegaTag1
botpose_orb_wpiblueRobot pose, blue originMegaTag2 estimate; requires SetRobotOrientation
pipelineSet active pipelineWrite 0-9 to switch pipelines
ledModeLED controlForce on/off/blink or let the pipeline decide
snapshotCapture a stillIncrement to trigger a snapshot for later tuning

Reading the values in code

You can read these keys straight from the NetworkTable, but the official LimelightHelpers class (a single Java file you drop into your project) wraps all of them cleanly. Here is a minimal proportional-aim example that turns the robot until the target is centered:

import frc.robot.LimelightHelpers;

public void teleopPeriodic() {
    boolean hasTarget = LimelightHelpers.getTV("limelight"); // valid target?
    double tx = LimelightHelpers.getTX("limelight");         // degrees left/right of crosshair
    double ty = LimelightHelpers.getTY("limelight");         // degrees up/down
    double ta = LimelightHelpers.getTA("limelight");         // % of image filled

    if (hasTarget) {
        double kP = 0.02;               // tune this
        double turn = -tx * kP;         // drive tx toward 0
        drivetrain.arcadeDrive(0.0, turn);
    }
}

Pass the device name ("limelight", or whatever you named it) to every call so the code works even with multiple cameras. For per-tag detail, LimelightHelpers.getRawFiducials("limelight") returns a RawFiducial[], each with id, txnc, tync, ta, distToCamera, distToRobot, and ambiguity.

Feeding pose into your estimator

For localization you do not aim — you fuse the Limelight's field pose into your drivetrain's pose estimator. The MT2 pattern each loop is: call LimelightHelpers.SetRobotOrientation("limelight", gyro.getYaw(), 0,0,0,0,0), then grab LimelightHelpers.PoseEstimate mt = LimelightHelpers.getBotPoseEstimate_wpiBlue_MegaTag2("limelight"). The PoseEstimate gives you mt.pose (a Pose2d), mt.timestampSeconds, and mt.tagCount. Reject bad frames — skip when mt.tagCount == 0 or when your gyro's angular velocity exceeds 360°/s — then hand the rest to WPILib:

m_poseEstimator.addVisionMeasurement(mt.pose, mt.timestampSeconds);

That single call blends vision into your odometry, correcting drift while your wheel encoders and gyro carry you between tag sightings.

Calibration and tuning tips

  • Verify the crosshair. For aiming, a small mechanical offset between camera and shooter is normal. Rather than fudge it in code, dual-calibrate the crosshair in the web UI so tx = 0 means "on target" for your mechanism.
  • Trust ty over ta for distance. Target area changes with pipeline settings and lighting; ty combined with a fixed mounting angle and known target height gives a much steadier distance estimate.
  • Lower exposure until it hurts, then back off. For both retroreflective and AprilTag pipelines, the darkest usable image is the most reliable one. AprilTag detection wants sharp black-white edges, not brightness.
  • Watch latency. Always use the timestamp from the PoseEstimate (or tl + cl) when feeding the estimator, so WPILib knows the measurement describes where you were, not where you are.
  • Log and replay. Use the snapshot key to capture frames during a real match, then re-tune against them in the pit instead of guessing.

Frequently asked questions

Do I need a static IP, or will DHCP work?

DHCP usually works on the bench, but the docs recommend a static IP (10.TE.AM.11, netmask 255.255.255.0) for competition. It boots faster and avoids DHCP/mDNS issues that have historically bitten teams on real fields with event radio firmware.

Why is my botpose always zero or empty?

Almost always one of three things: no AprilTag is in view, you have not uploaded the season field map, or the pipeline is not set to the AprilTag type with 3D enabled. Confirm a valid tid first, then check that botpose_wpiblue populates.

MegaTag1 or MegaTag2 — which should I use?

MegaTag2 for nearly everyone. It resolves the single-tag ambiguity that makes MT1 jittery, but it requires feeding your gyro heading via SetRobotOrientation every loop. If you have a reliable gyro, MT2 is more accurate and more stable.

Can I aim and localize with one Limelight at the same time?

You can switch a single camera between an aiming pipeline and an AprilTag pipeline by writing the pipeline key, but you cannot do both simultaneously on one unit. Teams that need both at once typically run two Limelights with different device names.

How do I read Limelight values without LimelightHelpers?

Grab the table with NetworkTableInstance.getDefault().getTable("limelight") and read entries like getEntry("tx").getDouble(0.0). LimelightHelpers just wraps this and adds typed pose parsing, so it is worth using, but the raw keys are always available.

Does the Limelight use up a CAN or PWM channel?

No. It communicates entirely over Ethernet/NetworkTables and draws power from a PDP/PDH slot behind a 5A breaker. It does not occupy a CAN ID, a PWM port, or a roboRIO DIO.


Once the camera is mounted rigidly, powered through a 5A breaker, addressed statically, and publishing a clean botpose, the hard part is over — the rest is tuning kP values and deciding which vision measurements to trust. Start with a single AprilTag pipeline and MegaTag2 into your pose estimator, get that solid, and add aiming pipelines from there. For more programming and hardware walkthroughs, browse the rest of our guides.

Spot an error or something out of date?Create a free account to suggest an edit

Keep reading

More from the pit

Start learning FRC — free

Structured lessons and quizzes across every department. Create a free account to save your progress, track your team, and earn a certificate.

394lessons
11departments
100%free