Introdução

Limelight - Visão ao seu robô sem código


A Limelight foi projetada para tornar a percepção de um robô tão fácil e confiável possível sem sacrificar nenhum desempenho!

A Limelight é fácil o suficiente para iniciantes completos e poderoso o suficiente para profissionais.

ezgif.com-video-to-gif-converted.gif

Montagem


Limelight 3

Use quatro parafusos de 1 1/2” #10-32 ou #10-24 e porcas de nylon para prender sua Limelight.

LL3DrawingSmall-a22b3464743fdadb8b4ed88d17b63f4a.png

Limelight 2/2+

Use quatro parafusos de 1 1/2” #10-32 ou #10-24 e porcas de nylon para prender sua Limelight.

LL2DrawingSmall-f4bf56dfab5809654ca4b2e12e343899.png

Conexão


A Limelight recebe 12V de alimentação, porém é construida para funcionar até 4.5V. Os LEDs tem brilho constante até 7V

Não utilize o Radio Power Module da REV para alimentar sua Limelight. A tensão é muito alta

wiring2-735e3fc134120e9d6fb7e5212f37cc0f.png

Credito - Christian Femia

Conexão Padrão

Conexão POE

PoE permite que você adicione tanto energia quanto a conexão de rede a sua Limelight por meio de um cabo Ethernet.

Isto não é padrão IEEE 802.3 (44V-48V) PoE - é por isso que você deve usar um injetor passivo com 12V.

Melhores Práticas de Fiação

Atualizando o LimelightOS


Siga esse guia para atualizar sua Limelight para a versão mais recente do LimelightOS

Limelight 3

Limelight 2/2+

Conecte o cabo USB-C apenas durante a gravação. O Limelight entra em um modo especial de flash enquanto o cabo microUSB está conectado. Você não poderá acessar a interface web enquanto o Limelight estiver no modo flash.

Setup de Comunicação/Network


Nós recomendamos fortemente seguir as instruções de IP estático para confiabilidade durante eventos. Siga estes passos antes de começar:

Definir Número da Equipe

ezgif.com-video-to-gif-converted (1).gif

Definir Endereço IP

Endereçamento Estático

ezgif.com-video-to-gif-converted (2).gif

Endereçamento Dinâmico

Conecte o cabo USB-C apenas durante a gravação de imagem. O Limelight entra em um modo especial de flash enquanto o cabo microUSB está conectado. Você não será capaz de acessar a interface web enquanto o Limelight estiver em modo flash.

Por que recomendamos o uso de um endereço IP estático? Primeiro, isso reduz vários segundos do tempo de inicialização do Limelight. Segundo, as equipes historicamente tiveram problemas em campos FRC reais e com firmwares de rádio de eventos.

Recomendamos configurar endereços IP estáticos no seu robo-rio e driverstation também. As configurações de rede para usar em todos esses dispositivos podem ser encontradas perto da metade inferior desta página web.

Como eu reseto o endereço IP? Após o seu Limelight iniciar, segure o botão de configuração por 10 segundos. Na próxima vez que o Limelight iniciar, sua configuração de rede será redefinida para endereçamento dinâmico.

Antes de se Conectar ao Campo

Nota: Equipes com zeros precisam prestar atenção especial:

Estado das luzes


Luz de status verde

A luz de status verde piscará lentamente se nenhum alvo for detectado pela pipeline atual. Ela piscará rapidamente se algum alvo for detectado pela pipeline atual.

Luz de status amarela

A luz de status amarela piscará quando um endereço IP estático não tiver sido atribuído. Se um endereço IP estático for atribuído, a luz permanecerá constantemente acesa ou apagada, sem piscar.

LEDs de iluminação verde

Os LEDs de iluminação verde no Limelight 1, 2 e 3 são controláveis via interface web e várias APIs, mas existem alguns padrões especiais de piscar projetados para ajudar a solucionar problemas de hardware e software:

Início a Programação


O Limelight suporta os protocolos REST/HTTP, Websocket, Modbus e NetworkTables para dados de mira, dados de status e configuração ao vivo. Formatos de saída JSON, Protobuf e bruto estão disponíveis. Consulte a seção de APIs da documentação para obter mais informações.

Para equipes de FRC, o protocolo recomendado é o NetworkTables. O Limelight envia todos os dados de mira, incluindo um despejo completo em JSON, para o NetworkTables a 100hz. As equipes também podem definir controles, como ledMode, janela de corte e mais via NetworkTables. As equipes de FRC podem usar as bibliotecas Limelight Lib Java e C++ para começar com o Limelight em segundos. Limelight Lib é a maneira mais fácil de começar.

Biblioteca Limelight:

Java, C++

Java

double tx = LimelightHelpers.getTX("");

C++

#include "LimelightHelpers.h"
double tx = LimelightHelpers::getTX("");
double ty = LimelightHelpers::getTY("");

Python

wip

NetworkTables

Java

import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
NetworkTable table = NetworkTableInstance.getDefault().getTable("limelight");
NetworkTableEntry tx = table.getEntry("tx");
NetworkTableEntry ty = table.getEntry("ty");
NetworkTableEntry ta = table.getEntry("ta");

//Lê os valores periodicamente
double x = tx.getDouble(0.0);
double y = ty.getDouble(0.0);
double area = ta.getDouble(0.0);

//Manda o valor para a smart dashboard periodicamente
SmartDashboard.putNumber("LimelightX", x);
SmartDashboard.putNumber("LimelightY", y);
SmartDashboard.putNumber("LimelightArea", area);

C++

#include "frc/smartdashboard/Smartdashboard.h"
#include "networktables/NetworkTable.h"
#include "networktables/NetworkTableInstance.h"
#include "networktables/NetworkTableEntry.h"
#include "networktables/NetworkTableValue.h"
#include "wpi/span.h"

std::shared_ptr<nt::NetworkTable> table = nt::NetworkTableInstance::GetDefault().GetTable("limelight");
double targetOffsetAngle_Horizontal = table->GetNumber("tx",0.0);
double targetOffsetAngle_Vertical = table->GetNumber("ty",0.0);
double targetArea = table->GetNumber("ta",0.0);
double targetSkew = table->GetNumber("ts",0.0);

LabVIEW

Labview_10-7a12740da0d9ffa505ee79e94cdb9df0.png


Python

import cv2
import numpy as np

# runPipeline() é chamado todo frame pelo backend da Limelight
def runPipeline(image, llrobot):
    # converte a imagem de input para o espaço de cor do HSV
    img_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    # converte o hsv para uma imagem binaria removendo qualquer pixel
    # que não sejam de acordo com os seguintes valores minimos e máximos do HSV
    img_threshold = cv2.inRange(img_hsv, (60, 70, 70), (85, 255, 255))

    # ache contornos na nova imagem binaria
    contours, _ = cv2.findContours(img_threshold,
    cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    largestContour = np.array([[]])

    # inicializa um array vazio para mandar devolta ao robô
    llpython = [0,0,0,0,0,0,0,0]

    # se os contornos foram detectados, desenhe eles
    if len(contours) > 0:
        cv2.drawContours(image, contours, -1, 255, 2)
        # grava o maior contorno
        largestContour = max(contours, key=cv2.contourArea)

        # pega a caixa delimitadora não rotacionada que envolve o contorno
        x,y,w,h = cv2.boundingRect(largestContour)

        # desenha a caixa delimitadora não rotacionada
        cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,255),2)

        # grave alguns dados customizados para mandar devolta ao robô
        llpython = [1,x,y,w,h,9,8,7]

    #retorna o maior contor para a mira da LL, a imagem modificada, e os dados customizados
    return largestContour, image, llpython

Melhores práticas


Lista de Verificação de Preparação para o Evento

Java

    import edu.wpi.first.wpiutil.net.PortForwarder;
    @Override
    public void robotInit() 
    {
        // Certifique-se de configurar o encaminhamento de porta apenas uma vez no código do robô.
        // Não coloque essas chamadas de funções em funções periodicas
        for (int port = 5800; port <= 5807; port++) {
            PortForwarder.add(port, "limelight.local", port);
        }
    }

C++

    import edu.wpi.first.wpiutil.net.PortForwarder;
    @Override
    public void robotInit() 
    {
        // Certifique-se de configurar o encaminhamento de porta apenas uma vez no código do robô.
        // Não coloque essas chamadas de funções em funções periodicas
        for (int port = 5800; port <= 5807; port++) {
            PortForwarder.add(port, "limelight.local", port);
        }
    }

Calibração durante o evento

Melhorando o pipeline

Antes de conectar ao campo

- _Team 916 uses 10.9.16.xx,_
- _Team 9106 uses 10.91.6.xx_
- _Team 9016 uses 10.90.16.xx_

Informação adicional: https://docs.wpilib.org/en/stable/docs/networking/networking-introduction/ip-configurations.html

Lista de checagem Pré-Partida

Largura de banda

Solução de erros

Calibração de mira


As miras do Limelight transformam a calibração angular 2D em um processo simplificado. Em vez de armazenar desvios angulares no código, você pode alinhar manualmente seu robô a um alvo e clicar no botão "calibrar".

Calibrar uma mira move o "zero" dos seus dados de mira. Isso é muito útil se o Limelight não estiver perfeitamente centrado no seu robô.

ezgif.com-video-to-gif-converted (3).gif

Modo de mira única

Posicione o seu robô na sua localização e rotação ideais para pontuar e clique em "calibrar". Agora, um tx e ty de "zero" equivalem a um robô perfeitamente alinhado. Se o seu robô precisar ser recalibrado para um novo campo, simplesmente realize uma partida de treino para encontrar o alinhamento perfeito para o seu robô e clique em "calibrar" durante a partida.

Modo de mira dupla

Imagine um robô com uma câmera ou atirador fora do eixo que precisa lançar objetos do jogo em um gol de várias posições no campo. À medida que o robô se aproxima do gol, sua mira deve ajustar em tempo real para compensar. O modo de mira dupla foi criado para essa funcionalidade. Alinhe o seu robô na sua posição e rotação mais próxima de pontuação e calibre a mira "A". Alinhe o seu robô na sua posição e rotação mais distante de pontuação e calibre a mira "B". Ao calibrar no modo de mira dupla, as miras também armazenam um valor de área. Você perceberá que, à medida que o seu robô se move entre as distâncias mínima e máxima de pontuação, a mira se move entre a mira "A" e a mira "B". Isso é feito verificando a área do alvo e comparando-a com as duas áreas de alvo vistas durante a calibração.

Configuração Pipeline


O LimelightOS armazena até 10 pipelines de visão exclusivas. Você pode alterar a pipeline ativa em tempo real com o LimelightLib.

Para editar várias pipelines, você deve primeiro marcar a caixa "Ignore NetworkTables Index" na interface web. Isso forçará o robô a permitir temporariamente que você altere o índice da pipeline por meio da interface web, em vez de por meio do NetworkTables.

Para baixar suas pipelines para backup e compartilhamento, basta clicar no botão "download" próximo ao nome da sua pipeline. Para carregar uma pipeline, clique no botão "upload".

Aqui está um exemplo de um robô que utiliza duas pipelines:

Exemplo de Robô com Duas Pipelines

A primeira pipeline é ajustada para identificar faixas verticais únicas. A segunda pipeline é ajustada para encontrar uma combinação de duas faixas horizontais. O código para este robô está disponível no estudo de caso "Aim and Range".

Observe que, quando o robô alterna entre pipelines, a interface web carrega automaticamente a nova pipeline.

Aba de entrada


A guia de entrada (Input Tab) oferece controles para alterar a imagem da câmera antes que ela seja processada pela pipeline de processamento.

Tipo da pipeline

Controla o tipo desejado de pipeline (AprilTags, Redes Neurais, Python, etc.).

Imagem de origem

Controla a fonte da imagem que é passada pela pipeline. Mude para "Snapshot" para testar suas pipelines de visão em snapshots armazenados.

Este controle é redefinido automaticamente para "Camera" quando a interface gráfica é fechada.

ezgif.com-video-to-gif-converted (4).gif

Resolução + zoom

Controla a resolução da câmera e da pipeline de visão. Recomendamos o uso da pipeline 320x240, a menos que você esteja utilizando funcionalidades 3D.

Pipelines de 320x240 executam a 90fps, enquanto pipelines de 960x720 executam a 22 fps. Em 2020, foram adicionadas opções de Zoom de Hardware 2x e 3x para este campo. As opções de zoom não são digitais e usam pixels reais do sensor a 100%.

LEDs

Controla o modo padrão de LED para esta pipeline. Isso pode ser substituído durante uma partida com a opção de tabela de rede "LED".

Usuários do Limelight 2+ têm acesso a um controle deslizante de "Brilho do LED" que permite ajustar o brilho dos LEDs.

Orientação

Controla a orientação dos frames de entrada. Defina como "inverted" se sua câmera estiver montada de cabeça para baixo.

ezgif.com-video-to-gif-converted (5).gif

Exposição

Controla a configuração de exposição da câmera em intervalos de 0,01 milissegundos. Pense em uma câmera como uma grade de "buckets" (recipientes) para coletar luz - o tempo de exposição controla por quanto tempo os "buckets" da sua câmera ficam abertos por quadro. Reduzir o tempo de exposição efetivamente escurecerá sua imagem. Tempos de exposição baixos e fixos são cruciais no FRC, pois escurecem a maior parte dos dados de imagem recebidos. Fitas retrorrefletivas bem iluminadas se destacarão em uma imagem principalmente escura, tornando o processamento de visão um processo direto.

ezgif.com-video-to-gif-converted (6).gif

Deslocamento do nível de preto

Aumentar o deslocamento do nível de preto pode escurecer significativamente o stream da sua câmera. Isso deve ser aumentado para remover ainda mais as luzes da arena e pontos brilhantes da sua imagem. Esta é uma configuração de nível de sensor e não uma configuração de brilho digital falso.

ezgif.com-video-to-gif-converted (7).gif

Ganho do Sensor

Aumentar o ganho do sensor efetivamente aumentará o brilho da imagem, mas geralmente adicionará ruído à imagem também. Você pode usar o Ganho do Sensor e o Deslocamento do Nível de Preto para iluminar a imagem sem aumentar o tempo de exposição. Isso minimizará o desfoque de movimento para aplicações de rastreamento em alta velocidade.

ezgif.com-video-to-gif-converted (8).gif

Balanço de Vermelho, Balanço de Azul

Controla a intensidade dos componentes de cor vermelha e azul na sua imagem. Isso controla coletivamente o balanço de branco do seu Limelight. Recomendamos deixar esses valores inalterados.

ezgif.com-video-to-gif-converted (9).gif