Você está na página 1de 4

Carros Inteligentes e FPGA

Paulo Feodrippe
Estudante de Engenharia Eletrônica
POLI - UPE
Recife, PE 50720-001
pfeodrippe@gmail.com

Abstract

Falamos um pouco nesse artigo de como implementar uma ideia de controlo


autônomo em um FPGA e o que podemos esperar do futuro para a Inteligência
Artififical.

1 Introdução

O conceito de ”Carros Inteligentes (ou Autônomos)” sempre esteve na cabeça das pessoas, mas
faltava uma tecnologia que correspondesse à realidade. Nos últimos anos, bons trabalhos têm sido
feitos para colocar à prova algoritmos que, entre outros, usam Redes Neurais Profundas (Deep Neu-
ral Networks - DNN) [1] para o controle autônomo de carros.
Na década de 2010, as pesquisas vêm sendo financiadas por grandes empresas como a Google [2],
Tesla [3], Nvidia [1], Ford [4], e isso atrai ainda mais pesquisas de grupos independentes [5][6].
Grande parte dessas pesquisas vêm sendo feitas com Unidades de Processamento Gráfico (Graphic
Processing Unit - GPU) [1], diferentemente de uma CPU onde as instruções são usualmente sequen-
ciais e há 2 ou 4 cores, a GPU é mais eficiente em termos computacionais por causa da paralelização
dos cálculos nos milhares ou milhões de mini-cores contidos no mesmo.
FPGAs estão começando a surgir na literatura de carros autônomos, e é sobre as vantagens e desvan-
tagens deles que iremos discutir a partir da próxima seção.

2 Seguindo a Estrada com FPGA

Além de técnicas mais avançadas como a já citada DNN, há várias formas de se iniciar um trabalho
em carros autônomos. Wallace et al [7] foram um dos grupos pioneiros nessa área e implementam
um módulo de visão para o carro seguir as faixas de estradas.

2.1 Aquisição das Imagens

Primeiramente, temos que ter as imagens. Imagine uma câmera RGB 8-bit/canal com um streaming
de vı́deo a 30 fps e com resolução de 640 pixels por 640 pixels. Precisamos de um processamento
em tempo real, é aı́ que entra o FPGA com sua grande capacidade de cálculos por segundo. não
vamos nos ater a um modelo especı́fico no momento.
A câmera está ligada ao FPGA através de conexões adequadas e vamos considerar que a aquisição
dos quadros já está sendo feita de forma correta.

1
2.2 Detectando Linhas

Escolhemos uma janela para ser nossa base e, para processar os quadros e detectar linhas, vamos
usar um filtro Sobel. Não vamos escrever o código em VHDL, mas sim em uma linguagem mais
moderna que permite paralelizar as operações mais facilmente, OpenCL, usando como base o código
no site da Altera/Intel [8] e que permite a programação em FPGAs. Código abaixo.

#define VECTORIZE_NUM 16

// Sobel filter kernel


// frame_in and frame_out are different buffers. Specify restrict on
// them so that the compiler knows they do not alias each other.
__kernel
void sobel(global unsigned int * restrict frame_in, global unsigned int * restrict frame_out,
const int iterations, const unsigned int threshold)
{
// Filter coefficients
int Gx[3][3] = {{-1,-2,-1},{0,0,0},{1,2,1}};
int Gy[3][3] = {{-1,0,1},{-2,0,2},{-1,0,1}};

// Pixel buffer of 2 rows and 3 extra pixels


int rows[2 * COLS + 2 + VECTORIZE_NUM];

// The initial iterations are used to initialize the pixel buffer.


int count = -(2 * COLS + 2 + VECTORIZE_NUM);
while (count < iterations) {
// Each cycle, shift a new pixel into the buffer.
// Unrolling this loop allows the compile to infer a shift register.
#pragma unrolll
for (int i = COLS * 2 + 1 + VECTORIZE_NUM; i > (VECTORIZE_NUM - 1); --i) {
rows[i] = rows[i - VECTORIZE_NUM];
}
#pragma unroll
for (int i = 0; i < VECTORIZE_NUM; i++) {
rows[i] = (count+i) >= 0 ? frame_in[count+i] : 0;
}

unsigned int clamped[VECTORIZE_NUM];

#pragma unroll
for (int k = 0; k < VECTORIZE_NUM; k++) {
int x_dir = 0;
int y_dir = 0;

// With these loops unrolled, one convolution can be computed every


// cycle.
#pragma unroll
for (int i = 0; i < 3; ++i) {
#pragma unroll
for (int j = 0; j < 3; ++j) {
unsigned int pixel = rows[i * COLS + j + k];
unsigned int b = pixel & 0xff;
unsigned int g = (pixel >> 8) & 0xff;
unsigned int r = (pixel >> 16) & 0xff;

// RGB -> Luma conversion approximation


// Avoiding floating point math operators greatly reduces
// resource usage.
unsigned int luma = r * 66 + g * 129 + b * 25;
luma = (luma + 128) >> 8;
luma += 16;

x_dir += luma * Gx[i][j];


y_dir += luma * Gy[i][j];
}
}

int temp = abs(x_dir) + abs(y_dir);


if (temp > threshold) {
clamped[k] = 0xffffff;
} else {
clamped[k] = 0;
}
}

#pragma unroll
for (int i = 0; i < VECTORIZE_NUM; i++) {
if (count+i >= 0) {
frame_out[count+i] = clamped[i];
}
}
count += VECTORIZE_NUM;
}
}

Listing 1: Exemplo de código para detecção de linhas

2
Após o código acima ser aplicado, selecionamos as melhores linha com os requisitos de que as
intensidades entre uma linha e outra (que forma uma faixa de um lado) seja a maior possı́vel, ver
Figure 1.

Figure 1: Exemplo de deteção de linhas em estradas em uma janela, retirado de [7]

2.3 Controle

Agora precisamos interpretar nossas saı́das visuais para poder controlar o carro autonomamente
através de um servo motor conectado à sua direção.
Vamos considerar x a distância entre o centro do veı́culo e o centro da estrada na visão da câmera
[7]. Nós queremos que ela seja nula a maior parte do tempo e que, caso não seja, queremos que
o carro volte ao estado de repouso da forma mais suave possı́vel. Também queremos considerar o
motor servo no loop, então vamos calcular o ganho Q do motor e x de acordo com as equações

dx
= −vQ (1)
dt
dQ x
= g(Q ) (2)
dt r
onde g é a constante de gravidade e v é a velocidade do carro.
dQ
As derivadas dx
dt e dt são calculadas no mundo discreto através de iterações no programa onde dt
representa uma iteração com intervalo ∆t.

3 Conclusão e Discussão
Os métodos aqui discutidos foram de 1985, mas já há algoritmos bem mais avançados sendo utiliza-
dos hoje em dia com GPUs e que podem ser codificados para FPGAs utilizandos openCL e outras
tecnologias que surgiram e vão surgir com o direcionamento cada vez mais de recursos para, não só
carros, mas ”coisas” inteligentes em geral.
A área da saúde, segurança, transporte, energia e até mesmo polı́tica precisam processar muito mais
dados do que há 10 anos atrás. GPUs são o presente, FPGAs, o futuro.

3
Agradecimentos
Obrigado a meus amigos Thiago, Jonas e Ana e especialmente aquele abraço para o professor Zilcio,
figura marcante da POLI que deixou uma marca em todos que passaram por ele.
#ForaTemer
#ForçaChape

Referências
[1] Bojarski, M et al (2016) End to End Learning for Self-Driving Cars.
[2] How Google’s Self-Driving Car Will Change Everything -
http://www.investopedia.com/articles/investing/052014/
how-googles-selfdriving-car-will-change-everything.asp. Acessado em 23/12/2016.
[3] Tesla’s Self-Driving Car Plan Seems Insane, But It Just Might Work - https://www.wired.com/
2016/10/teslas-self-driving-car-plan-seems-insane-just-might-work/. Aces-
sado em 23/12/2016.
[4] Will Ford have completely self-driving car by 2021? - http://www.freep.com/story/money/
cars/ford/2016/08/17/ford-ceo-autonomous-vehicles-transform-industry/
88867946/. Acessado em 23/12/2016.
[5] Sallab, A. E. et al (2016) End-to-End Deep Reinforcement Learning for Lane Keeping Assist.
[6] Xiong, X. et al (2016) Combining Deep Reinforcement Learning and Safety Based Control for Autonomous
Driving.
[7] Wallace, R. et al (1985) First Results in Robot Road-Following.
[8] Sobel Filter Design Example - https://www.altera.com/support/support-resources/
design-examples/design-software/opencl/sobel-filter.html. Acessado em
28/12/2016.

Você também pode gostar