Tutorial · Intermediário · 35 min

LiDAR para robôs: da varredura ao mapa de ocupação

Entenda como um LiDAR giratório constrói uma varredura, por que girar mais rápido reduz a resolução angular e como os raios atualizam uma grade de ocupação.

Introdução

Um sensor de distância informa a distância de um objeto, ao longo de uma linha. Um mapa informa a forma de uma sala. Tudo o que é interessante na navegação está no intervalo entre essas duas coisas, que é o assunto desta página.

Os dois extremos já foram tratados aqui: medição de um único ponto, de um lado, e SLAM e A* em uma grade de ocupação, do outro. Mas ambos pressupõem que uma grade já exista. Nada explica de onde ela veio, e a resposta — projetar uma varredura em células — é simultaneamente simples e cheia de armadilhas.

Um LiDAR 2D é um sensor ToF sobre uma base giratória

Este é o conceito mais útil que você pode conhecer, porque significa que já entende a metade da medição.

Dentro de um LiDAR 2D de hobby há um módulo óptico de medição de tempo de voo, exatamente como o de uma placa de desenvolvimento da série VL53, apontado lateralmente e montado sobre uma base giratória. Um encoder angular informa para onde o módulo estava orientado a cada medição. A alimentação e os dados atravessam a fronteira entre as partes fixa e giratória por meio de um anel deslizante ou de um acoplamento óptico/indutivo.

Portanto, uma “varredura” não é uma fotografia. É uma lista de pares (angle, range), coletados um de cada vez ao longo de uma volta completa. Todas as limitações abaixo decorrem dessa frase.

Isso também explica por que sensores ultrassônicos não são simplesmente girados para virar LiDARs. Um feixe ultrassônico tem dezenas de graus de abertura angular, portanto girá-lo quase não agrega nada — você apenas espalharia um feixe já largo pelo ambiente. Um feixe óptico estreito é o que torna a resolução angular significativa. Fazer um único sensor ToF varrer com um servo, como no tutorial de ultrassônico com varredura, de fato produz um LiDAR lento e de baixa resolução.

O orçamento de amostras é fixo, então atualização e resolução trocam

Esta é a parte que surpreende as pessoas e vale entender antes de comprar qualquer coisa.

O módulo de medição tem um único valor de vazão: quantas medições por segundo ele consegue fazer. Em um RPLIDAR A1, esse valor é de cerca de 8000 amostras por segundo e não muda quando você altera a taxa de rotação. Você escolhe a taxa de rotação, normalmente entre 1–10 Hz.

Assim, os pontos obtidos por volta completa são simplesmente o orçamento dividido pela taxa de rotação:

points per revolution = samples per second ÷ spin rate
angular step          = 360° ÷ points per revolution
Taxa de rotação Pontos por volta Passo angular Período da varredura
5,5 Hz 1455 0,25° 182 ms
10 Hz 800 0,45° 100 ms

Você não pode obter varreduras recentes e boa resolução angular ao mesmo tempo. Girar a 10 Hz reduz pela metade a latência e quase pela metade a resolução angular. Essa única troca influencia mais o comportamento do robô do que o alcance anunciado no produto, e é a primeira configuração que deve ser escolhida deliberadamente, em vez de deixar no padrão do software do sensor.

Para um robô que se move rapidamente em um corredor aberto: gire rápido, porque você precisa de informações recentes e as paredes são grandes. Para um robô lento que mapeia uma sala cheia de objetos: gire lentamente, porque você precisa de detalhe e pode permitir mais latência.

Os feixes divergem, então obstáculos distantes ficam entre eles

Um passo angular é um ângulo, não uma distância. Dois feixes adjacentes se afastam à medida que se propagam:

gap between beams ≈ range × angular step (in radians)

Com 0,45°, isso corresponde a uma lacuna de 7,9 mm a um metro e de 31 mm a quatro metros. Nada amostra o espaço entre eles.

Gráfico da distância entre feixes adjacentes de LiDAR em função do alcance até o alvo, para 5,5 Hz (1455 pontos por revolução, 0,25 grau) e 10 Hz (800 pontos por revolução, 0,45 grau). As duas linhas sobem linearmente a partir de zero, e a linha de 10 Hz sobe com o dobro da inclinação. Uma linha horizontal tracejada marca uma perna de cadeira de 20 mm, e marcadores mostram o espaçamento dos feixes de 10 Hz ultrapassando essa largura além de 2,5 metros e o de 5,5 Hz além de 4,6 metros.
A lacuna de amostragem cresce linearmente com a distância e cresce duas vezes mais rápido a 10 Hz do que a 5,5 Hz. Onde cada linha cruza a largura da perna da cadeira, a perna deixa de ser detectável. Baixar SVG

Considere uma perna de cadeira de 20 mm. Girando a 10 Hz, a lacuna entre feixes ultrapassa 20 mm em cerca de 2,5 m — além disso, a perna pode ficar inteiramente entre dois feixes e não produzir nenhum retorno. A 5,5 Hz, você chega a cerca de 4,6 m antes de a mesma coisa acontecer.

A mesma perna de cadeira de 20 mm desenhada em relação a dois feixes adjacentes, em duas distâncias. A 2 metros, os feixes estão separados por 16 mm e a perna é mais larga que a lacuna, então um feixe incide nela e ela é detectada. A 5 metros, os feixes estão separados por 39 mm e a perna é mais estreita que a lacuna, então fica entre os feixes e nada retorna.
O mesmo objeto e o mesmo sensor, duas vezes. Nada na perna mudou — apenas se um feixe por acaso estava apontado para ela. Baixar SVG

Isso explica um comportamento que, de outro modo, parece um sensor quebrado: obstáculos finos aparecem quando o robô se aproxima e entram no mapa a um ou dois metros de distância. O LiDAR não estava falhando. A perna nunca havia sido amostrada.

Ao orientar o projeto, leve em conta duas consequências:

  • Não confie em uma única varredura para detectar obstáculos finos. Acumular várias varreduras em uma grade, como veremos adiante, é o que realmente encontra pernas de mesa — cada varredura amostra ângulos ligeiramente diferentes.
  • Pernas de cadeira e mesa são uma falha clássica de robôs domésticos, porque são finas, ficam exatamente na altura do LiDAR e o robô só as descobre tarde.

Uma varredura não é uma fotografia

Os pontos de uma volta completa não foram medidos no mesmo instante. A 5,5 Hz, a varredura leva 182 ms, e o robô não espera educadamente.

  • A 0,5 m/s, o robô percorre 91 mm durante uma volta completa.
  • A 1 rad/s, a varredura é borrada ao longo de 10,4°.

Tratar essa lista de pontos como uma única fotografia rígida, tirada em uma única pose, deforma a representação do mundo. Paredes retas ficam curvas ou duplicadas, e a correspondência de varreduras passa a lutar contra correções que são realmente consequência do movimento do próprio robô.

É por isso que sensor_msgs/LaserScan transporta scan_time e time_increment junto com as distâncias: eles permitem ao consumidor determinar quando cada feixe foi medido. A correção — transformar cada ponto pela pose que o robô tinha no carimbo de data/hora daquele feixe — chama-se compensação de movimento, e boas camadas de processamento de SLAM fazem isso automaticamente.

Na prática, se seus mapas ficam limpos com o robô parado e borrados durante o movimento, suspeite da compensação de movimento e dos carimbos de data/hora muito antes de suspeitar do sensor. E diminua a velocidade durante o mapeamento. Metade da velocidade significa metade da distorção, sem custo adicional.

Você só obtém um plano horizontal

Um LiDAR 2D mede um plano. Tudo o que fica acima ou abaixo desse plano não existe para ele.

As três falhas clássicas são:

  • Saliências. Um tampo de mesa a 700 mm é invisível para um LiDAR a 150 mm. O robô passa confiante por baixo e fica preso.
  • Obstáculos baixos. Uma soleira, um cabo, uma meia. Todos abaixo do plano.
  • Quedas de nível. Uma escada descendente é espaço vazio em todas as direções que o LiDAR consegue ver. Ela parece um piso perfeitamente livre.

Nenhum processamento de varredura corrige isso, porque a informação nunca foi capturada. Robôs reais mantêm um sensor de contato, sensores de borda e muitas vezes um sensor apontado para baixo ou para a frente junto com o LiDAR — não porque o LiDAR seja ruim, mas porque um plano é um plano. Quando você lê que um robô aspirador “tem LiDAR e ainda tem sensores de contato”, esta é a razão.

Da varredura à grade: projeção de raios

Agora, a metade de mapeamento. Uma grade de ocupação divide o mundo em células quadradas e armazena, para cada uma, o grau de crença de que esteja ocupada.

A ideia que faz esse processo funcionar é simples: uma leitura de distância informa sobre todas as células ao longo do raio, não apenas sobre a célula em sua extremidade. Se um feixe percorreu 3 m antes de atingir algo, todo o espaço que ele cruzou deve estar vazio — caso contrário, teria sido interrompido antes.

Portanto, cada feixe produz três atualizações:

Grade de células quadradas com um sensor à esquerda e um raio traçado até uma célula acima e à direita. As células atravessadas pelo raio são sombreadas como livres, a célula onde a leitura de alcance cai é sombreada como ocupada, e as células que continuam no mesmo rumo além desse impacto são sombreadas como desconhecidas. Uma legenda informa que as células atravessadas se tornam livres e seus log-odds diminuem, o impacto se torna ocupado e seu log-odds aumenta, e as células atrás do impacto permanecem desconhecidas e não são tocadas em vez de serem marcadas como livres.
Um feixe atualiza uma linha inteira de células. As células atrás do impacto ficam na sombra — o feixe nunca as alcançou, então permanecem desconhecidas, o que é diferente de estarem livres. Baixar SVG
  1. Células atravessadas pelo raio → evidência de estarem livres. Percorra a linha do sensor até o impacto e atualize cada célula no sentido de vazio.
  2. Célula na qual a leitura terminou → evidência de estar ocupada. Atualize-a no sentido de ocupada.
  3. Células além do impacto → nenhuma informação. O feixe foi interrompido. Você não aprendeu nada sobre o que está atrás daquela parede e, portanto, deve deixar essas células intactas.

Percorrer a linha é apenas rasterização de linha — o algoritmo de Bresenham, o mesmo que desenha uma linha em uma tela.

Uma leitura no alcance máximo exige tratamento próprio. Muitos controladores de sensor informam o valor máximo, ou infinito, quando nenhum retorno foi obtido. Isso não significa “há uma parede a 12 m” — significa “não foi encontrado nada”. Marque o trajeto do raio como livre e não marque nenhuma célula ocupada no final.

Log-odds: por que somar em vez de multiplicar

Você poderia armazenar uma probabilidade por célula e multiplicar as atualizações de Bayes. Na prática, todos armazenam log-odds:

l = ln( p / (1 - p) )          p = 1 / (1 + e^(-l) )

Há dois motivos. Multiplicar muitas probabilidades pequenas causa subfluxo numérico; somar logs não. Além disso, isso reduz a atualização a uma única adição, barata o suficiente para ser realizada em cada célula de cada feixe de cada varredura.

Com p = 0.5 (nenhuma informação) mapeando para l = 0, escolha um valor para um impacto e outro para um feixe que passou sem encontrar um obstáculo — digamos p_occ = 0.7 (l = +0.847) e p_free = 0.4 (l = −0.405) — e a atualização é:

l_cell += l_occ     # this beam hit this cell
l_cell -= 0.405     # this beam passed through this cell

Uma célula começando em l = 0 após três impactos:

Observação Log-odds Probabilidade
início (desconhecida) 0.000 0.500
impacto +0.847 0.700
impacto +1.695 0.845
impacto +2.542 0.927
atravessada +2.136 0.894
atravessada +1.731 0.850

As evidências se acumulam, e a discordância puxa a estimativa de volta. Esse é todo o algoritmo.

Limite os totais. Isso importa mais do que parece. Vinte impactos consecutivos sem limite colocam uma célula em l = 16.9, correspondente a p = 0.999999. Agora alguém move a cadeira. Desfazer essa certeza exige 42 observações livres. A cadeira deixa um fantasma permanente, e o planejador continua contornando nada.

Limitar l a algo como ±3,5 resolve o problema: uma crença forte continua forte, mas algumas varreduras contraditórias podem revertê-la. Se seus mapas acumulam fantasmas de objetos que já saíram, essa é quase sempre a razão.

Desconhecido é um terceiro estado, não sinônimo de livre

Este é o erro que produz planos confiantes e perigosos.

Uma grade recém-inicializada é inteiramente desconhecida. Se seu planejador tratar o estado desconhecido como atravessável, ele traçará uma rota diretamente pelas regiões do mundo que você nunca observou — e essas regiões, por serem inexploradas, são exatamente onde as surpresas se escondem. Se tratar o estado desconhecido como bloqueado, o robô recusará se mover no início, porque tudo é desconhecido.

As duas abordagens estão erradas; mantenha os três estados distintos e decida deliberadamente:

  • Ocupada — não planeje através dela.
  • Livre — planeje através dela.
  • Desconhecida — planeje através dela apenas com um custo, ou apenas durante uma exploração deliberada.

A exploração de fronteira, que é como um robô escolhe onde procurar em seguida, baseia-se inteiramente na fronteira entre células livres e desconhecidas. Colapsar os dois estados descarta essa capacidade.

Escolhendo o tamanho da célula

A resposta usual é 5 cm para robôs internos, e há uma razão para não usar células menores só porque é possível.

Uma célula menor que o espaçamento dos feixes na distância típica está inventando uma precisão que você não tem — a 4 m, os feixes estão separados por 31 mm; portanto, células de 1 cm deixam buracos permanentes entre raios que nunca se preenchem. Células muito maiores que a margem de folga do seu robô, por outro lado, fazem portas parecerem intransponíveis, porque uma única célula ocupada pode engolir a abertura.

Regra prática: use células um pouco menores que a passagem mais estreita pela qual você precisa passar e nem menores que o espaçamento dos feixes na região em que realmente opera. Depois infle os obstáculos pelo raio do robô no momento do planejamento, em vez de diminuir as células para compensar.

Quando dá errado

Sintoma Normalmente
Obstáculos finos aparecem somente quando estão próximos O espaçamento dos feixes superou a largura deles na distância — comportamento esperado, não uma falha
Paredes curvam ou duplicam durante o movimento Varredura sem compensação de movimento; pontos tratados como pertencentes a um único instante
Mapa limpo quando parado, mas borrado durante o movimento Mesma causa; também tente mapear mais devagar
Robô passa sob uma mesa e fica preso O plano 2D não vê saliências; é preciso um segundo sensor
Escadas parecem piso aberto Quedas de nível são invisíveis a um plano horizontal; use sensores de borda
Obstáculos removidos continuam no mapa Log-odds não foram limitados, então a certeza não pode ser desfeita
O mapa inteiro se enche de obstáculos nas bordas Leituras de alcance máximo “sem retorno” marcadas como impactos
O planejador traça uma rota pelo espaço inexplorado Estado desconhecido confundido com livre
Grade fina cheia de pequenos buracos Células menores que o espaçamento dos feixes; nada amostra entre os raios
Paredes de vidro desaparecem completamente Retornos ópticos passam diretamente — o único caso em que o ultrassônico vence

A última linha é a ressalva honesta para toda a página. O LiDAR supera o sonar em resolução, taxa e alcance e depois perde completamente para ele em uma porta de vidro, que o som reflete e a luz não. É o argumento mais claro para não escolher apenas um sensor e considerar o problema resolvido.

Explore o grafo

Faz parte destas montagens

Projetos e caminhos de aprendizagem que incluem este tutorial.

Leitura complementar

Referências