SlideShare uma empresa Scribd logo
1 de 39
Baixar para ler offline
INSTITUTO TECNOLÓGICO DE AERONÁUTICA 
CONSELHO NACIONAL DE DESENVOLVIMENTO CIENTÍFICO E 
TECNOLÓGICO - CNPq 
CNPq 
CONSELHO NACIONAL DE DESENVOLVIMENTO 
CIENTÍFICO E TECNOLÓGICO 
PROGRAMA INSTITUCIONAL DE BOLSAS DE INICIAÇÃO CIENTÍFICA - 
PIBIC 
Desenvolvimento de um Sistema de 
Navegação Indoor por Imagens para um 
Veículo Aéreo não Tripulado do tipo 
Quadricóptero 
Roberto Brusnicki 
RELATÓRIO FINAL DE ATIVIDADES 
Orientador: 
Dr. Davi Antônio dos Santos 
08 / 2013
INSTITUTO TECNOLÓGICO DE AERONÁUTICA 
CONSELHO NACIONAL DE DESENVOLVIMENTO CIENTÍFICO E 
TECNOLÓGICO - CNPq 
CNPq 
CONSELHO NACIONAL DE DESENVOLVIMENTO 
CIENTÍFICO E TECNOLÓGICO 
PROGRAMA INSTITUCIONAL DE BOLSAS DE INICIAÇÃO CIENTÍFICA - 
PIBIC 
Relatório Final de Atividades 
Desenvolvimento de um Sistema de 
Navegação indoor por Imagens para um 
Veículo Aéreo não Tripulado do tipo 
Quadricóptero 
São José dos Campos, 03 / 08 / 2013 
Nome do aluno 
Roberto Brusnicki 
Assinatura do aluno 
Nome do orientador 
Davi Antônio dos Santos 
Assinatura do orientador
INSTITUTO TECNOLÓGICO DE AERONÁUTICA 
PROGRAMA INSTITUCIONAL DE BOLSAS DE INICIAÇÃO CIENTÍFICA - PIBIC 
Formulário de Aprovação de Relatório pelo Orientador 
Relatório: 
Rel. Parcial 
X 
Rel. Final 
1- CONSIDERO O RELATÓRIO APROVADO COM BASE NOS SEGUINTES ASPECTOS 
2- APRECIAÇÕES DO ORIENTADOR SOBRE O DESEMPENHO DO BOLSISTA NA EXECUÇÃO DO TRABALHO DE INICIAÇÃO CIENTÍFICA 
Local e data: 
Assinatura do Orientador:
ÍNDICE 
1. INTRODUÇÃO .................................................................................................................... 4 
2. ANDAMENTO E PLANEJAMENTO ........................................................................................... 6 
2.1. RESUMO DO PLANO INICIAL ............................................................................................. 6 
2.2. RESUMO DAS ATIVIDADES REALIZADAS ............................................................................... 7 
3. DEFINIÇÃO DO PROBLEMA ................................................................................................... 9 
4. FORMULAÇÃO DO FILTRO .................................................................................................. 10 
4.1. ESTIMAÇÃO DE QUATÉRNIO ........................................................................................... 10 
4.2. QEKF ....................................................................................................................... 13 
4.2. OBTENÇÃO DOS VETORES UNITÁRIOS .............................................................................. 14 
5. SIMULAÇÕES COMPUTACIONAIS ......................................................................................... 16 
6. OBTENÇÃO DOS DADOS EM TEMPO REAL POR COMUNICAÇÃO SERIAL ........................................ 21 
7. CONCLUSÕES .................................................................................................................. 22 
8. AGRADECIMENTOS........................................................................................................... 23 
9. BIBLIOGRAFIA ................................................................................................................. 23 
CÓDIGOS DO FILTRO DE KALMAN PARA ESTIMAÇÃO DE QUATÉRNIO DE ROTAÇÃO 
ANEXO 1: (MATLAB) ............................................................................................................. 24 
ANEXO 2: (C - ARDUINO)....................................................................................................... 27 
1. INTRODUÇÃO 
Este trabalho está envolvido com VANTS do tipo quadricóptero, que consiste em veículo com capacidade de decolagem e aterrissagem verticais constituído de quatro rotores acionados por motores elétricos individuais e independentes. 
Para que um VANT quadricóptero tenha sua trajetória controlada em malha fechada e de forma autônoma, faz-se necessário que esse veículo embarque um Sistema de Navegação (SN), que consiste em um dispositivo capaz de estimar, em tempo real, sua posição, sua velocidade linear, sua atitude (orientação) e sua velocidade angular. A função de um sistema de controle por realimentação é essencialmente fazer com que medidas/estimativas de variáveis dinâmicas (como atitude, posição e velocidade) rastreiem trajetórias desejadas. Por essa razão, um controle confiável, acurado e robusto requer um SN com as mesmas propriedades qualitativas. A importância de um SN para o funcionamento adequado de VANTs autônomos motiva uma avaliação detalhada de seus componentes e métodos. 
Em particular, a chamada navegação inercial é a forma tradicional de se realizar navegação por meio da integração das medidas dos sensores inerciais (acelerômetros e girômetros) embarcados no veículo de interesse. A principal vantagem da navegação inercial pura é sua independência em relação a sinais externos e a condições de visibilidade e sua imunidade a interferências intencionais, como o jamming. Graças a essas características, os sensores inerciais são bastante apropriados para operar em ambientes como túneis, cavernas e interiores de prédios.
A despeito de sua independência em relação a sinais externos ao sistema, a navegação inercial pura apresenta a significativa desvantagem de produzir estimativas de posição, velocidade e atitude cujos erros divergem sem limites com o tempo. Essa é uma característica bem conhecida, que é explicada, em breves palavras, pelo fato de que junto com acelerações e velocidades angulares, o sistema também integra ao longo do tempo os vieses e derivas dos sensores. De forma a limitar os erros divergentes de sistemas de navegação inerciais puros, invoca-se frequentemente o uso de fusão de sensores para permitir a combinação das medidas inerciais com aquelas providas por outros sensores, como magnetômetros, sensores ultrassônicos, GPS, câmera, entre outros. 
Os métodos de fusão sensorial mais comuns são aqueles baseados no filtro de Kalman, ferramenta que provê um framework para estimar variáveis dinâmicas (estados) de um sistema a partir de sequências de medidas adquiridas de diversos sensores. 
A fusão de dados de GPS e sensores inerciais é um tópico importante e já bem estudado. Os esquemas de fusão GPS-INS têm aplicações em diversas áreas, como aviação, guiamento de satélites, aproximação e pouso automáticos de aeronaves, aplicações marítimas e, em especial, em navegação de VANTs. O sucesso desses esquemas se deve principalmente à complementaridade das características típicas dos erros de medição de GPS e de sensores inerciais. A navegação baseada apenas na integração de medidas dos sensores inerciais (navegação inercial pura) é precisa num curto intervalo de tempo, no entanto, resulta em estimativas de posição que se degradam sem limites devido à existência de vieses em acelerômetros e de derivas em girômetros. Com base na estrutura do filtro de Kalman, medidas de sensores inerciais e de GPS podem ser fundidas, segundo uma variedade de esquemas de implementação, permitindo um desempenho de estimação (de posição, velocidade e atitude) superior a ambos os subsistemas individualmente. 
Infelizmente, a navegação inercial assistida por GPS pode carecer de confiabilidade quando opera em lugares com linhas de visada deficientes em relação aos satélites do sistema GPS. Exemplos de tais lugares são: interiores de prédios, cavernas, minas, cânions urbanos e em florestas (entre árvores, por exemplo). De forma a compensar essas limitações, o uso de câmera digital como auxílio à navegação tem recentemente atraído o interesse de pesquisadores. A fusão INS-Câmera basicamente consiste no uso de câmera(s) digital(is) para medir/rastrear a posição de features numa sequência de imagens e, com base na estrutura do filtro de Kalman, usar tais informações para estimar erros de navegação/erros de sensores e compensá-los nas estimativas de posição, velocidade e atitude. Esses esquemas de fusão parecem ser especialmente adequados para a navegação em ambientes indoor contendo landmarks, que oferecem informações substancialmente ricas para a navegação do veículo. 
O restante deste trabalho está organizado da seguinte maneira. O Capítulo 2 apresenta um resumo da proposta inicial, a descrição dos trabalhos realizados durante o
período 2012/2 e o planejamento para as próximas atividades. O Capítulo 3 define o problema de controle de determinação de atitude e navegação usando sensores inerciais e uma câmera embarcada apontada verticalmente para baixo. O Capítulo 4 apresenta a formulação de um filtro de Kalman que soluciona o problema de determinação de atitude. O Capítulo 5 apresenta alguns resultados de avaliações realizadas por simulações computacionais. Por fim, o Capítulo 6 apresenta as conclusões da etapa parcial a que se refere este relatório. 
2. ANDAMENTO E PLANEJAMENTO 
2.1. RESUMO DO PLANO INICIAL 
Este trabalho tem como objetivo desenvolver um sistema de navegação de baixo custo apropriado para voo indoor equipado com, dentre outros sensores, uma câmera, a ser utilizado em um VANT (Veículo Aéreo Não Tripulado) de pequeno porte do tipo quadricóptero (que consiste de um veículo com capacidade de decolagem e aterrissagem verticais constituído de quatro rotores acionados por motores elétricos individuais e independentes), que será projetado, fabricado e posteriormente avaliado experimentalmente. 
Para alcançar-se tal objetivo, faz-se necessário dotar o sistema de navegação a ser desenvolvido para o VANT de vários sensores que por meio de medidas possibilite o voo autônomo estável e controlado. Esse sistema deve ser equipado com um acelerômetro de 3 eixos para determinação de acelerações lineares, um giroscópio de 3 eixos para determinação de velocidades angulares, um sensor ultrassônico para medição de altitude, e de uma câmera para obtenção de imagens. 
A Metodologia adotada consiste em inicialmente construir-se um quadricóptero elétrico utilizando componentes de aeromodelismo, e verificar seu funcionamento através de testes rádio controlados. Dado isto, integrar ao quadricóptero a parte física do sistema de navegação a ser desenvolvido, ou seja, uma plataforma em que se encontrem os sensores supracitados. Posteriormente, o desenvolvimento do software do sistema de navegação, o qual consiste basicamente de um filtro de Kalman para fusão dos sensores inerciais, sensor ultrassônico de altitude e a câmera. Este último passo possui implícito todo o estudo a cerca de processos estocásticos, bem como o estudo do filtro de Kalman, e da física do problema, assim como simulação de seu funcionamento anteriormente a sua utilização no VANT propriamente dito.
2.2. RESUMO DAS ATIVIDADES REALIZADAS 
1) Construção 
Inicialmente construiu-se o quadricóptero com peças de aeromodelismo. O que se consiste basicamente do frame em formato de cruz, os 4 motores elétricos do tipo brushless, suas respectivas hélices, e o sistema de alimentação, constituído pelos eletronic speed controllers (ESC’s) cabos de alimentação e da bateria de polímero de Lítio. Além disto, tal quadricóptero possui também um Arduíno Mega como micro controlador utilizado para seu sistema de navegação. O software utilizado para fazer a estabilização de atitude consiste do Aeroquad open-sourse. 
Esta primeira fase permitiu a familiarização com o funcionamento deste modelo relativamente novo de VANTs, sem que houvesse excessiva preocupação com eventuais danos causados aos seus componentes devido a um mau controle de seu voo, pois não estaria voando de maneira autônoma, mas sim de maneira radio-controlada. 
2) Embasamento Teórico 
Com a finalidade de se adquirir o embasamento matemático necessário para a realização deste trabalho, foram estudados os seguintes tópicos: 
 Variáveis aleatórias e processos estocásticos. Parte dessa preparação foi realizada através da disciplina de graduação MOQ-13 (Probabilidade e Estatística); 
 Filtro de Kalman. Foram estudadas diversas formulações do filtro de Kalman: discreta-discreta, contínua-discreta tando para o filtro linear quanto para o filtro de Kalman estendido. As referências utilizadas foram (Gelb, 1974) [1] e (Hwang e Brown, 1997) [2]; 
 Cinemática de atitude. Foram estudadas as diversas representações de atitude bem como as respectivas equações diferenciais que modelam a dinâmica de atitude em função das velocidades angulares do veículo ao longo do tempo. Existem várias possibilidades de parametrização de atitude, dentre elas, as mais recorrentes são: ângulos de Euler, matriz de cossenos diretores (DCM), quaternion de rotação e parâmetros modificados de Rodrigues. A referência adotada foi (Shuster, 1993) [4]. 
3) Simulações computacionais 
Adotou-se o MATLAB como ambiente de simulação. Foram simuladas a cinemática de atitude do veículo bem como as medidas dos sensores, que são uma
câmera embarcada com apontamento vertical voltado para baixo e uma tríade de girômetros. Nesse mesmo ambiente, implementou-se também as equações de um filtro de Kalman estendido discreto-discreto para estimação da atitude representada por quaternion de rotação. Foram realizados diversos testes que possibilitaram uma boa sintonia do filtro e comprovaram sua capacidade de convergência e robustez. 
4) Familiarização com os sensores utilizados 
Adotou-se o uso do sensor GY-521 para obtenção das medidas de velocidade angular, e a CMUCam4 como sensor de rastreamento de cores para obtenção dos vetores unitários indicados na figura 3. Ambos os sensores escolhidos atendem ao proposto pelo projeto, sendo sensores de baixo custo, mas que com sistema de navegação desenvolvido fornecem dados bom o suficiente para se fazer a estimação da atitude do quadricóptero com alta precisão. Uma das vantagens de se ter trabalho com o sensor GY-521, é que este também possui um acelerômetro de 3 eixos, sendo estas medidas necessárias em um trabalho posterior em que utilizará o sistema de navegação em movimento. A CMUCam4 consiste em um sensor de visão computacional programável, que pode ser utilizado como rastreador de cor, entre inúmeras outras funções. Ambos os sensores foram utilizados neste projeto em conjunto com o microprocessador Arduino Mega, tendo sido necessário um tempo de estudo de suas bibliotecas, funções, configurações, e utilização de modo a otimizar a obtenção dos dados necessários. 
Figura 1: (a) Sensor de rastreamento de cores CMUCam4. (b) IMU de 6 graus GY-521.
5) Simulações computacionais com obtenção dos dados em tempo real, e familiarização com comunicação serial entre Arduino e MATLAB 
Tendo-se o código no MATLAB funcionando de maneira precisa com a simulação, adaptou-se este para que utilizasse os dados provenientes em tempo real dos sensores acoplados ao Arduino Mega. Para tal utilização, foi-se necessário significativo tempo na familiarização com a comunicação serial necessária entre ambos os softwares (Arduino IDE, e MATLAB). Além disto, foi-se necessário escrever o código do Arduíno que obtivesse os dados dos sensores, e os enviassem para o computador através da porta serial. Foram realizados alguns testes, como levantamento das distribuições das medidas dos sensores, que possibilitaram uma excelente sintonia do filtro e uma vez mais comprovaram sua capacidade de convergência e robustez. 
6) Tradução do código do Filtro de Kalman para linguagem C. 
Após atingido o sucesso na simulação com com obtenção de dados em tempo real, passou-se à tradução completa do código do MATLAB para a linguagem C utilizada pelo Arduino, a fim de poder-se testar a viabilidade de utilização do sistema de navegação desenvolvido de maneira totalmente embarcada, não dependendo mais de um computador para nenhum tipo de cálculo. O código completo em linguagem C encontra- se ao término deste relatório no anexo 2. 
3. DEFINIÇÃO DO PROBLEMA 
Com o intuito de modelar o problema de determinação de atitude a partir de medidas vetoriais obtidas pela câmera, considera-se um sistema de eixos cartesianos SB solidário ao corpo do quadricóptero, um sistema de eixos cartesianos SR de referencia, e outro sistema de eixos cartesianos em um referencial inercial (a Terra, por exemplo, assumindo que seu movimento é desprezível). Tais sistemas podem ser visualizados na figura 2. Tanto SB como SR possuem suas origens no centro geométrico do quadricóptero. 
A câmera utilizada será a CMUCam, que já predispõe de um processamento de imagens e fornece alguns dados, como por exemplo o centroide de regiões de determinada cor. Juntamente com o sensor ultrassônico utilizado (Maxbotix LV-EZ0) obtêm-se as medidas vetoriais que fornecem a direção (do ponto de vista da câmera) de landmarks coloridas dispostas no chão. A câmera encontrara-se fixa ao corpo do quadricóptero, portanto as medidas vetoriais obtidas serão em relação ao sistema de eixos SB. As landmarks estão dispostas no chão de modo a sempre terem-se ao menos duas no campo de visão da câmera. Tais especificações podem ser visualizadas na figura 3.
O problema proposto consiste em estimar em tempo real a posição e atitude do quadricóptero como exposto acima. Para estimar-se a atitude, além das medidas vetoriais, utilizam-se também os valores de velocidade angular obtidos pelo girômetro. Além disso, para estimar-se a posição utilizam-se também acelerômetros. 
Figura 2: Sistemas de eixos cartesianos utilizados para a determinação de atitude. SB, SR e SI correspondem respectivamente aos sistemas de eixos coordenados solidário ao corpo do VANT, de referência e inercial (i.e. no referencial da Terra). 
Figura 3: Câmera fixa ao quadricóptero, e disposição das landmarks no chão de modo à sempre haver no mínimo duas no campo de visão da câmera a fim de se obter vetores unitários que apontam para as mesmas.
4. FORMULAÇÃO DO FILTRO 
O método escolhido para resolver o problema definido na Seção 2 consiste num filtro de Kalman estendido para estimação de quatérnio a partir de medidas vetoriais. Para manter a norma do quatérnio estimado próxima de unitária, emprega-se simplesmente uma etapa de normalização Euclidiana das estimativas. Esse filtro será referido como QEKF (quaternion extended Kalman filter). Em seguida, as equações do QEKF são revisadas com base em (SANTOS, 2008). 
4.1. Estimação de quatérnio 
O vetor de estado do estimador de quatérnio de rotação, QEKF, é dado por , onde q1 e são as representações escalar e vetorial, respectivamente, dos componentes real e imaginário de q. Assim, tem-se que a equação de medidas não-linear discreta no tempo dos estimadores de quatérnio de rotação é: 
( ) 
(1) 
onde, ( ) [ ( ) ( ) ( ) ( ) ( ) ( ) ] 
: medidas vetoriais feitas no sistema de eixos cartesianos do VANT; 
: medidas vetoriais em relação ao sistema de referência; 
: ruído de medição. 
O modelo de cinemática de atitude para o quatérnio de rotação é dado pela seguinte equação diferencial linear: 
̇( ) ( ) ( ) 
(2) 
onde, 
( ) [ ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ] 
(3)
Em que ( ) ( ) ( ) correspondem respectivamente as velocidades angulares do VANT em relação aos eixos . 
Integrando (2) de , obtém-se: 
( ) 
(4) 
Onde ( ) é a matriz de transição de estado. Considerando-se que a velocidade angular ( ) ( ) ( ) ( ) seja constante durante o intervalo de tempo entre amostragens sucessivas das medidas vetoriais, essa matriz é dada por: 
( ) 
(5) 
onde é computada por (3), mas utilizando em vez de ( ) Substituindo, então, ( ) ̂( ) ( ) na equação anterior: 
( ) ( ̂ ) ̂ 
(6) 
onde as matrizes ̂ são dadas por (3), porém substituindo ( ) ̂ , respectivamente. Representando o segundo fator do lado direito de (6) pela correspondente série de potências, obtém-se: 
( ) ̂ ( ) 
(7) 
Considerando-se que sejam ambos pequenos, o truncamento da série em (7) após termos de primeira ordem permite que (4) seja aproximada por: 
̂ ̂ 
(8) 
Pode-se verificar que: 
(9) 
onde, 
[ ] 
(10) 
Sendo assim, utilizando (9) na manipulação do segundo termo do lado direito de (8), finalmente se obtém a seguinte equação de estado discreta no tempo:
̂ ̂ 
(11) 
Onde é dado por (10), mas utilizando o quatérnio verdadeiro no instante , no lugar de . Para fins de implementação dos estimadores de quatérnio, a covariância do ruído de estado (segundo termo à direita em (11)) é aproximada por: 
(12) 
onde, 
̂ ̂ 
(13) 
e ̂ é computada por (10), porém utilizando ̂ no lugar de . 
A exponencial matricial que define a matriz de transição de estado em (5) é aqui computada por: 
(‖ ‖ ) ‖ ‖ (‖ ‖ ) 
(14) 
O quatérnio de rotação apresenta norma unitária e, dessa forma, seus componentes obedecem à restrição . No entanto, a atualização linear do KF, por envolver a operação de soma, não garante que as estimativas de mantenham essa propriedade ao longo da estimação. A forma mais simples de lidar com tal restrição consiste no uso de normalização Euclidiana das estimativas após o estágio de atualização aditiva. 
Em seguida é apresentado o estimador QEKF, o qual utiliza normalização Euclidiana para garantir que as estimativas tenham normas unitárias. 
4.2. QEKF 
Mediante uso do EKF (Extended Kalman Filter) e tendo-se em vista a equação de estado linear (11) e a equação de medidas não linear (1), obtêm-se os estágios de propagação e de atualização do QEKF. Para garantir que as normas de suas estimativas sejam unitárias, utiliza-se normalização Euclidiana. 
A estimativa normalizada ̂ ‖ ̂ ‖, apresenta um erro cuja covariância é aproximada no QEKF simplesmente por: 
(15) 
O QEKF requer a matriz Jacobiana das medidas,
( ) | ̂ 
(16) 
A Tabela 1 apresenta o QEKF. 
Tabela 1: Estimador de quatérnio de rotação – QEKF (SANTOS, 2008 – pg. 31). 
Em anexo, ao fim deste relatório encontram-se os códigos do Filtro descrito acima. 
4.3. Obtenção dos vetores unitários 
Após algumas soluções iniciais, em que seriam necessários um sensor a mais a fim de obter-se também uma medida de distância entre a câmera, e o plano em que se encontra a landmark, (neste caso utilizar-se-ia o sensor sonar: Parallax's PING), ou então obter-se a altitude do quadricóptero (para este caso, foi escolhido o sensor altímetro: Sparkfun’s BMP085), e após alguns experimentos com ambos os sensores para determinação da qualidade das medidas fornecidas por estes, abandonou-se ambas as abordagens iniciais, e optou-se por outra cuja necessidade de novo sensor tornou-se desnecessária.
Somente com a imagem fornecida pela CMUCam4, é possível determinar-se as coordenadas do vetor unitário que aponta para uma landmark no sistema de eixos do quadricóptero (que consiste no mesmo da câmera). Para tal, faz-se necessário o levantamento de um parâmetro da câmera, denotado aqui por K. 
K representa a distância entre o plano da imagem vista pela câmera, e a câmera propriamente dita. Porém, o valor de K é dado pelo número de pixels que esta distancia ocuparia (no eixo x ou y) em uma imagem obtida pela câmera, caso esta medida fosse posta em um plano perpendicular ao eixo ótico da câmera afastado exatamente da mesma medida. 
O valor obtido para K foi de aproximadamente 171, isto significa que para a câmera, em uma imagem visualizada a 1 metro de distância, um objeto com 171 pixels em linha reta (no eixo x ou y da imagem obtida) de dimensão, possui na realidade dimensão de 1 metro. Em uma imagem obtida pela câmera a uma distancia 2 metros de uma parede, 171 pixels desta imagem corresponderiam a um comprimento de 2 metros na parede. E assim por diante. 
Figura 4: Significado do parâmetro K: Na imagem obtida, K pixels em linha reta correspondem a uma medida no anteparo equivalente à distância entre a câmera e o anteparo. 
A imagem de trabalho da CMUCam4 consiste em uma matriz de pixels de 120x160, sendo estes numerados de 0 a 119 para o primeiro eixo, e de 0 a 159 para o segundo eixo da imagem. Sendo possível obter esta numeração para os pixels rastreados. Apesar de a CMUCam4 ser, em sua essência, um sensor de cor, por fornecer os valores de RGB de cada pixel de seu campo de visão, é possível utiliza-la para tirar fotos (porém de maneira muito ineficiente e demorada). Sendo assim, foi-se possível realizar experimentos de medições para determinar-se o valor de K com alta precisão.
Tendo este parâmetro determinado, por simplicidade supondo-se o centro da imagem vista pela câmera como sendo o pixel com coordenadas ( ), e tendo o eixo ótico da câmera perfeitamente alinhado com o eixo z do sistema de eixos , um vetor que aponta para uma landmark com coordenadas do centroide dadas por ( ) (na imagem fornecida pela CMUCam4, ou seja, x e y são a numeração dos pixels), e com origem na própria câmera, é dado por: 
⃗ ( ) 
(17) 
Foi-se utilizado o sinal de menos na coordenada z, pois a câmera estará acoplada à parte inferior do quadricóptero, tendo assim sem campo de visão direcionado à parte negativa do semi-eixo z do sistema de eixos . Portanto, sendo a norma do vetor dada por: 
‖ ⃗‖ √ 
(18) 
Tem-se então que o vetor unitário necessário ao algoritmo desenvolvido é dado por: 
⃗⃗ ( ‖ ⃗‖) ⃗ 
(19) 
5. SIMULAÇÕES COMPUTACIONAIS 
Concentram-se aqui os resultados posteriores as fases de construção e estudos, já que estes são mais significativos como um todo para o trabalho. 
Inicialmente, a fim de simular os dados de entrada provenientes dos sensores relativos à determinação de atitude, ou seja, girômetros e câmera, plotou-se arbitrariamente funções senoidais bem comportadas para as velocidades angulares (o motivo desta escolha deve-se puramente a tentativa de evitar-se que as velocidades angulares escolhidas impliquem em um movimento muito brusco e distante do que ocorre na realidade com o VANT, fornecendo assim dados mais fidedignos a posterior análise da simulação). A partir destas funções, colhendo-se seus valores em pontos igualmente espaçados de tempo, e adicionando-se um ruído aleatório normalmente distribuído, obtém-se um bom exemplo de valores de medidas provenientes dos giroscópios. Um exemplo deste procedimento pode ser verificado na figura 5.
Figura 5: Simulação de velocidades angulares medidas pelos girômetros. Respectivamente em azul, vermelho e verde tem-se: velocidade angular em relação ao eixo x, y e z. Onde x, y e z correspondem a um sistema de eixos ortogonais solidário ao quadricóptero. 
A partir das funções que geraram as medidas de velocidades angulares, obteve- se qual seria o movimento descrito pelo VANT, ou seja, como os valores dos ângulos que descrevem sua atitude variam com o tempo. Para tal, utilizou-se o método de Runge-Kutta de 4ª ordem, o resultado pode ser visto na figura 6. 
Figura 6: Atitude parametrizada pelos ângulos de Euler obtida a partir das velocidades angulares escolhidas. Respectivamente em verde, azul e vermelho tem-se 휑, 휃 e 휙. 
Este último gráfico foi plotado apenas para fim de melhor visualização do movimento descrito pelo quadricóptero. O estudo apresentado aqui trabalha com a parametrização de atitude através de quatérnio de rotação. Sendo assim, segue o correspondente gráfico da variação dos parâmetros do real quatérnio de rotação que descreve o movimento:
Figura 7: Variação dos parâmetros do real quatérnio de rotação q=[q0 q1 q2 q3]T. Respectivamente em verde, azul, vermelho e preto tem-se q0, q1, q2 e q3. 
A partir dos valores do real quatérnio de rotação correspondente ao movimento, determinou-se quais deveriam ser os reais vetores unitários que, a parte de um ruído gaussiano, correspondem as medidas vetoriais a serem obtidas pela câmera que representam as direções de landmarks postas no chão. 
Para obterem-se tais medidas, rotacionou-se dois vetores conhecidos, supostos serem as medidas iniciais da câmera para as landmarks, utilizando-se os valores do quatérnio do gráfico anterior. Os vetores iniciais escolhidos foram r1=[0, 5/13, -12/13]T e r2=[0, -5/13, -12/13]T (representações em relação a um sistema de eixos fixo ao solo coincidente com o sistema de eixos solidário ao VANT na situação inicial). No intuito de fornecer uma visão mais limpa deste último resultado, na figura 8 é fornecida uma visualização das primeiras 30 medidas dos vetores, ainda não acrescidas do respectivo ruído. 
Acrescentando-se o devido ruído a este ultimo resultado, obtemos assim dados coerentes que simulam bem velocidades angulares e medidas vetoriais obtidos respectivamente pelos girômetros e pela câmera a partir de um determinado movimento do quadricóptero. Estes dados podem agora ser utilizados como dados de entrada para a implementação do filtro de Kalman que irá estimar o quatérnio de rotação a partir destes dado.
Figura 8: Primeiras 30 medidas dos vetores unitários que apontam para as landmarks em relação ao sistema de eixos fixo ao quadricóptero. Nesta imagem, para melhor visualização, está suprimido o ruído acrescido aos vetores, o que corresponde de maneira mais fidedigna às medidas vetoriais obtida pela câmera. 
Na figura 9 pode-se verificar a estimação obtida para o quatérnio de rotação correspondente ao caso real da figura 7. Percebem-se pouquíssimas diferenças. Na figura 10 é possível verificar-se em detalhe ambos os gráficos superpostos para outro caso. Nota-se que o filtro estima de maneira bastante razoável os parâmetros do quatérnio de rotação, mesmo depois de passado um grande período de tempo, e inúmeras medições já efetuadas. 
Figura 9: Variação dos parâmetros do quatérnio de rotação estimado pelo filtro de Kalman qe=[q0 q1 q2 q3]T. Respectivamente em verde, azul, vermelho e preto tem-se q0, q1, q2 e q3.
Figura 10: Detalhe de comparação entre quatérnio real e quatérnio estimado pelo filtro de Kalman. Em linha continua encontram-se os valores reais, enquanto os pontos correspondem às estimativas obtidas pelo filtro. 
Figura 11: Índice de ortogonalidade e erro angular em função do tempo. A escala vertical do primeiro gráfico está multiplicada pelo fator .
6. OBTENÇÃO DOS DADOS EM TEMPO REAL POR COMUNIÇÃO SERIAL 
Concentram-se aqui os resultados posteriores à fase de formulação e simulação do filtro proposto. 
Inicialmente, pretendia-se reescrever todo o código implementado no MATLAB em linguagem C (o que foi feito posteriormente), e verificar diretamente seu funcionamento final rodando o algoritmo de maneira totalmente embarcada no quadricóptero. Porém, em vista dos inúmeros problemas que poderiam surgir nesta grande passagem do projeto, optou-se por um passo intermediário, que consiste na simulação com obtenção dos dados em tempo real. A rotina implementada anteriormente foi adaptada para utilizar os dados provenientes dos sensores, através de comunicação serial entre o Arduino e o MATLAB, correspondendo assim ao real movimento destes, e não de uma simulação. Houve a necessidade de abordar-se o problema da determinação dos vetores unitários que apontam da câmera para a landmark, explicitada na seção 4.3. 
Os demais valores que antes eram provenientes da simulação de uma dinâmica do quadricóptero, ou seja, as velocidades angulares, são diretamente lidas através do valor fornecido pelo girômetro, sendo apenas necessário fazer uma correção de unidade. 
O giroscópio presente no sensor GY-521 possui 4 configurações possíveis de ranges para se trabalhar, sendo a escolhida para este trabalho a que apresenta maior precisão das medidas, porém menor range. Esta decisão foi tomada levando-se em consideração que os testes preliminares seriam executados com movimentos de pequenas e médias amplitudes, pois o campo de visão da câmera escolhida apresenta um campo de visão de cerca de 30º apenas. Além disto, verificou-se experimentalmente que com o menor range, a distribuição das medidas obtidas com o sensor aproxima-se melhor de uma gaussiana, o que melhoraria o desempenho do filtro, dado que esta é uma das premissas de sua formulação. Esta verificação está indicada na figura 12. 
Figura 12: Dados de velocidade angular em relação ao mesmo eixo obtido com o giromêtro configurado para as duas opções extremas de range. Em (a) e (b), tem-se respectivamente as configurações que fornecem ranges com amplitudes de 2000º/s, e 250º/s. Os dados apresentados
na figura encontram-se em rad/s. O pico de (a) encontra-se com cerca de 1600 amostras, e o pico de (b) com cerca de 500 amostras. 
Com isso, pode-se executar-se novamente a rotina do filtro, e plotar os valores das inovações de todas as componentes de ambos os vetores. Verificou-se que como esperado, estes gráficos possuem média nula, são descorrelacionados. Para cada um dos 6 gráficos, plotou-se também o sigma correspondente (raiz quadrada do respectivo elemento da diagonal principal da matriz de covariância da inovação). 
Figura 13: Em azul, valores da inovação de cada uma das componentes de ambos os vetores obtidos. E verde, respectivo valor de sigma, proveniente da matriz de covariância da inovação. Sendo de cima para baixo, as coordenadas de x, y e z, sendo os 3 gráficos iniciais correspondentes aos valores do vetor B1 (no código em MATLAB) e os últimos 3, correspondentes aos valores do vetor B2.
7. CONCLUSÕES 
O projeto obtido significativo progresso, obtendo bom resultados nas simulações, e nas primeiras fases de sua parte prática. Pode-se verificar até o momento que o filtro tem bom desempenho não só em simulações, mas também em na prática, em que o sistema de navegação apesar de ainda não ter sido testado em voo no VANT construído inicialmente, foi testado inúmeras vezes em uma plataforma similar, estimando a atitude da mesma de maneira acurada. Contudo, o teste em voo é sem dúvida uma fase crucial do projeto, e que se espera ser executado em breve a fim de alcançar-se o objetivo pré-estabelecido, isto é, desenvolver um sistema de navegação de baixo custo, porém de excelente qualidade. Ainda assim, a idealização do sistema, e a verificação de sua viabilidade, e performance já foram plenamente confirmadas neste projeto. 
Como extensão ao trabalho aqui realizado, sugere-se as seguintes atividades: 
 Alterar o firmware da CMUCam4 de modo a obter dados de maneira mais rápida, e assim não haver-se a necessidade de utilizar mais de uma câmera. No estágio atual em que se encontra o projeto, a alteração dos parâmetros de qual cor deve ser rastreada pela câmera faz com que sua taxa de amostragem caia de 30 fps para 4 fps, os motivos desta perda está relacionado com o modo de implementação das funções utilizadas no código deste sensor. A possibilidade de utilização de uma firmware costumizada já foi esclarecida e confirmada com o fabricante do mesmo; 
. 
 Realizar testes experimentais de bancada, tendo uma plataforma com determinação de atitude de modo independente (por exemplo: guimbals instrumentados com encoders), sendo assim, poder-se-ia comparar a atitude estimada pelo sistema de navegação desenvolvido com a fornecida pela plataforma. 
8. AGRADECIMENTOS 
Agradeço ao Prof. Davi Antônio dos Santos por ter cedido seu tempo e paciência ao fornecer auxílio no desenvolvimento deste projeto, e pelo seu sempre constante incentivo. Ao Instituto Tecnológico de Aeronáutica pelo ensino de qualidade, sem o qual este trabalho não teria sido possível, e pelas inúmeras outras oportunidades oferecidas. Agradeço ainda em especial ao CNPq que financiou este projeto através do programa PIBIC. Este incentivo é de suma importância ao desenvolvimento da pesquisa científica no Brasil.
9. BIBLIOGRAFIA 
1. GELB, A. Applied Optimal Estimation. Boston: M.I.T. Press, 1974. 
2. BROWN, R.G.; HWANG, P.Y.C. Introduction to Random Signals and Applied Kalman Filtering. New York: John Wiley & Sons, 1997. 
3. ANDERSON, B.D.O.; MOORE, J.B. Optimal Filtering. New Jersey: Prentice- Hall, 1979. 
4. SHUSTER, M. D. A Survey of Attitude Representations. The Journal of the Astronautical Sciences, Vol. 41, No. 4. October-December 1993, pp.439-517. 
5. SANTOS, D. A. Estimação de Atitude e Velocidade Angular de Satélites Utilizando Medidas do Campo Geomagnético e da Direção do Sol. Dissertação de Mestrado. Instituto Tecnológico de Aeronáutica, São José dos Campos, 2008. 
ANEXO 1: 
CÓDIGOS DO FILTRO DE KALMAN PARA ESTIMAÇÃO DE QUATÉRNIO DE ROTAÇÃO (MATLAB) 
A) TESTE_GERAL.m 
clc; 
clear; 
% parâmetros de tempo 
dt = 0.1; %intervalo de tempo entre medidas 
Tmax=100; %intervalo total de tempo em que são feitas medidas 
%% covariâncias usadas na simulação do sistema 
sigma_w = 0.005; %incerteza na medição da velocidades angulares 
sigma_b=0.01; %incerteza nas medidas das coordenadas dos vetores b1 e b2 
Rb = sigma_b^2*eye(6); %covariância do ruído de medidas no sistema Sb 
Rw = sigma_w^2*eye(3); %covariância do ruído de medidas dos girômetros 
%% Covariância usadas no filtro 
R = Rb; Q = 0.005^2*eye(3); 
%% posições das landmarks 
r1= [0; 5/13; -12/13]; %representações em Sr das observações vetoriais 
r2= [0; -5/13; -12/13]; 
%% Condições iniciais do sistema 
P(:,:,1)=0.01*eye(4); %covariância do erro de estimação no instante 0 
q(:,1) = [1 0 0 0]'; 
%% Condições iniciais do filtro 
qe(:,1) = [1 0 0 0]'; 
for k=1:Tmax/dt+1, %loop único para a simulação e o filtro de Kalman 
[q(:,k+1),wm(:,k), b1k1, b2k1]=simulacao(q(:,k),r1,r2,Rb,Rw,dt,k); 
[qe(:,k+1),P(:,:,k+1)] = 
KalmanFilter(qe(:,k),P(:,:,k),wm(:,k),Q,R,r1,r2,b1k1,b2k1,dt); 
% Calcula figuras de mérito 
% Ik - erro angular; Jk - índice de ortogonalidade 
[Ik(k+1),Jk(k+1)] = figuras_de_merito(q(:,k+1),qe(:,k+1)); 
end 
figure; hold on; 
plot(wm');title('Velocidade angular medida em rad/s');
figure; plot(qe','b'); plot(q','r'); 
figure; plot(Jk); title('Índice de Ortogonalidade'); 
figure; plot(Ik); title('Erro Angular em graus'); 
B) simulacao.m 
function [qk1,wm, b1k1, b2k1] = simulacao(qk,r1,r2,Rb,Rw,dt,i) 
%% simulação da velocidade angular. 
wk = [0.1*sin(i*dt) 0.1*cos(i*dt) -0.1*sin(i*dt)*cos(i*dt)]'; 
%% propagação de atitude 
[qk1,fi]=propaga_q(qk,wk,dt); 
qk1 = (1/norm(qk1))*qk1; 
% atitude representada em DCM 
D = q2DCM(qk1); 
%% simulação das medidas 
wm = wk + sqrtm(Rw)*randn(3,1); % girômetros no instante k 
b=[D*r1;D*r2]+sqrtm(Rb)*randn(6,1);% medidas vet. no instante k+1 
b1k1 = b(1:3); 
b2k1 = b(4:6); 
C) KalmanFilter.m 
function [qk1,Pk1] = KalmanFilter(qk,Pk,wk,Q,R,r1,r2,b1,b2,dt) 
% Inputs: 
% qk – estimativa do quaternio no instante k 
% Pk - convariância do erro estimado correspondente à qk 
% wk – medida de velocidade angular no instante k 
% dt – tempo de amostra 
% Q - covariância do ruído de processamento 
% R - covariância do ruído das medidas 
% r1, r2, b1, b2 – medidas vetoriais no instante k+1 
% Outputs: 
% qk1 - quaternio estimado no instante k+1 
% Pk1 – covariância do erro de estimação correspondente à qk1 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
%1a - Propagação do estado estimado 
[q_,fi] = propaga_q(qk,wk,dt); 
Csi_k = [-qk(2) -qk(3) -qk(4); 
qk(1) -qk(4) qk(3); 
qk(4) qk(1) -qk(2); 
-qk(3) qk(2) qk(1)]; 
Gama_k=dt/2*fi*Csi_k; 
Q_q_k=Gama_k*Q*Gama_k'; 
P_=fi*Pk*fi'+Q_q_k; 
%--------------------------------------------------------------------- 
%1b - Predição das medidas 
D_q_k= q2DCM(q_); 
b_estimado=[(D_q_k*r1)' (D_q_k*r2)']'; 
dDdq1 = [ 2*q_(1) 2*q_(4) -2*q_(3); 
-2*q_(4) 2*q_(1) 2*q_(2); 
2*q_(3) -2*q_(2) 2*q_(1)]; 
dDdq2 = [ 2*q_(2) 2*q_(3) 2*q_(4); 
2*q_(3) -2*q_(2) 2*q_(1); 
2*q_(4) -2*q_(1) -2*q_(2)]; 
dDdq3 = [-2*q_(3) 2*q_(2) -2*q_(1); 
2*q_(2) 2*q_(3) 2*q_(4); 
2*q_(1) 2*q_(4) -2*q_(3)];
dDdq4 = [-2*q_(4) 2*q_(1) 2*q_(2); 
-2*q_(1) -2*q_(4) 2*q_(3); 
2*q_(2) 2*q_(3) 2*q_(4)]; 
H_1_q = [dDdq1*r1 dDdq2*r1 dDdq3*r1 dDdq4*r1]; 
H_2_q = [dDdq1*r2 dDdq2*r2 dDdq3*r2 dDdq4*r2]; 
H_q = [H_1_q; H_2_q]; 
P_b = H_q*P_*H_q' + R; 
%--------------------------------------------------------------------- 
%1c - Covariância cruzada 
P_b_q = P_*H_q'; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
%2a - Ganho 
K = P_b_q*inv(P_b); 
%--------------------------------------------------------------------- 
%2b - Atualização da estimativa 
qk1 = q_ + K*( [b1' b2']' - b_estimado ); 
Pk1 = P_ - K*P_b*K'; 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
%3 - Normalização 
qk1 = (1/norm(qk1))*qk1; 
D) Figuras_de_merito.m 
function [Ik,Jk]=figuras_de_merito(q,qe) 
De = q2DCM(qe); % DCM estimada 
D = q2DCM(q); % DCM verdadeira 
Ik = 180/pi*abs(acos(0.5*(trace(De'*D) - 1))); %erro angular em graus 
Jk = trace((De'*De-eye(3))*(De'*De-eye(3))');%Índice de ortogonalidade 
E) propaga_q.m 
function [q2,fi] = propaga_q(q1,w1,dt) 
% cálculo da matriz de transição de estado 
W = 0.5*[0 -w1(1) -w1(2) -w1(3); 
w1(1) 0 w1(3) -w1(2); 
w1(2) -w1(3) 0 w1(1); 
w1(3) w1(2) -w1(1) 0]; 
n_w = norm(w1); 
fi=cos(n_w*dt/2)*eye(4)+1/n_w*sin(n_w*dt/2)*W; 
%matriz de transição de estado 
q2 = fi*q1; % propagacão do quatérnion 
F) q2DCM.m 
function D = q2DCM(q) 
D11 = 1-2*q(3)^2-2*q(4)^2; 
D12 = 2*(q(2)*q(3)+q(1)*q(4)); 
D13 = 2*(q(2)*q(4)-q(1)*q(3)); 
D21 = 2*(q(2)*q(3)-q(1)*q(4)); 
D22 = 1-2*q(2)^2-2*q(4)^2; 
D23 = 2*(q(4)*q(3)+q(1)*q(2)); 
D31 = 2*(q(2)*q(4)+q(1)*q(3)); 
D32 = 2*(q(4)*q(3)-q(1)*q(2)); 
D33 = 1-2*q(2)^2-2*q(3)^2; 
D = [ D11 D12 D13; 
D21 D22 D23; 
D31 D32 D33];
ANEXO 2: 
CÓDIGOS DO FILTRO DE KALMAN PARA ESTIMAÇÃO DE QUATÉRNIO DE ROTAÇÃO (C - ARDUINO) 
A) arduino_matlab_serial.ino 
#include <CMUcam4.h> 
#include <CMUcom4.h> 
#define R_MIN_1 235 //amarelo 
#define R_MAX_1 255 
#define G_MIN_1 235 
#define G_MAX_1 255 
#define B_MIN_1 160 
#define B_MAX_1 190 
#define R_MIN_2 235 //vermelho 
#define R_MAX_2 255 
#define G_MIN_2 160 
#define G_MAX_2 210 
#define B_MIN_2 140 
#define B_MAX_2 200 
#define LED_BLINK 5 // 5 Hz 
#define WAIT_TIME 1000 // 5 seconds 
#define FILTRO 12 
#define K1 683 
#define pi 3.1416 
#define LED_PIN 13 
//----------------------------------------------------------- #include "Wire.h" 
#include "I2Cdev.h" 
#include "MPU6050.h" 
//----------------------------------------------------------- 
//########################################################### // Variáveis globais 
bool blinkState = false; 
CMUcam4 cam1(CMUCOM4_SERIAL1); 
CMUcam4 cam2(CMUCOM4_SERIAL2); 
CMUcam4_tracking_data_t data1, data2; 
MPU6050 accelgyro; 
int16_t ax, ay, az; int16_t gx, gy, gz; 
float a_x, a_y, a_z; 
float g_x, g_y, g_z; 
unsigned long T1, T2; 
//###########################################################
//########################################################### void setup() 
{ 
cam1.begin(); 
cam2.begin(); 
cam1.LEDOn(LED_BLINK); 
cam2.LEDOn(LED_BLINK); 
delay(WAIT_TIME); 
cam1.autoGainControl(false); cam2.autoGainControl(false); 
cam1.autoWhiteBalance(false); cam2.autoWhiteBalance(false); cam1.LEDOn(CMUCAM4_LED_ON); 
cam2.LEDOn(CMUCAM4_LED_ON); 
//----------------------------------------------------------- Wire.begin(); 
accelgyro.initialize(); 
//----------------------------------------------------------- 
Serial.begin(9600); 
} //########################################################### void loop(){ 
cam1.trackColor(R_MIN_1, R_MAX_1, G_MIN_1, G_MAX_1, B_MIN_1, B_MAX_1); 
cam2.trackColor(R_MIN_2, R_MAX_2, G_MIN_2, G_MAX_2, B_MIN_2, B_MAX_2); 
delay(WAIT_TIME); 
cam1.getTypeTDataPacket(&data1); 
cam2.getTypeTDataPacket(&data2); Serial.println(data1.mx); 
Serial.println(data1.my); 
Serial.println(data2.mx); 
Serial.println(data2.my); 
for(;;){ 
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //medidas feitas juntas 
cam1.getTypeTDataPacket(&data1); cam2.getTypeTDataPacket(&data2); 
g_x=gx*pi/(131*180)-0.0244; // conversão para 
g_y=gy*pi/(131*180)-0.0155; // a unidade correta 
g_z=gz*pi/(131*180)+0.0069; // e calibração 
Serial.println(g_y,5); 
Serial.println(g_x,5); 
Serial.println(g_z,5); 
Serial.println(data1.mx); 
Serial.println(data1.my); 
Serial.println(data2.mx); 
Serial.println(data2.my); 
} 
}
B) KF_C.ino 
#include <CMUcam4.h> 
#include <CMUcom4.h> 
#define R_MIN_1 75 
#define R_MAX_1 255 
#define G_MIN_1 0 
#define G_MAX_1 125 
#define B_MIN_1 0 
#define B_MAX_1 100 
#define R_MIN_2 75 
#define R_MAX_2 255 
#define G_MIN_2 0 
#define G_MAX_2 125 
#define B_MIN_2 0 
#define B_MAX_2 100 
#define LED_BLINK 5 // 5 Hz 
#define WAIT_TIME 5000 // 5 seconds 
#define FILTRO 12 
#define K1 171 
#define pi 3.1416 
//----------------------------------------------------------- #include "Wire.h" 
#include "I2Cdev.h" 
#include "MPU6050.h" 
//########################################################### 
// Variáveis globais 
CMUcam4 cam1(CMUCOM4_SERIAL1); 
CMUcam4 cam2(CMUCOM4_SERIAL2); 
CMUcam4_tracking_data_t data1, data2; 
MPU6050 accelgyro; 
int16_t gx, gy, gz; 
double n_w, c, s, **C, **S, **fi, **q, **wm, dt=0.03, **W, 
**Csi_k, **Gama_k, **Q_q_k, **Q, **Pk, **D_q_k, 
**b_e, **b1_e, **b2_e, **r1, **r2, **dDdq1, 
**dDdq2, **dDdq3, **dDdq4, **H_1_q1, **H_1_q2, 
**H_1_q3, **H_1_q4, **H_2_q1, **H_2_q2, **H_2_q3, 
**H_2_q4, **H_q, **P_b, **R, **P_b_q, **K, **P_b_n_inv, **b; 
//########################################################### 
// Produto de Escalar por Matriz 
double** PdeEeM(double e, double** A, int a, int b ) 
{ 
for(int i=0; i<a; i++) 
for(int j=0; j<b; j++) 
A[i][j]=e*A[i][j]; 
return A; 
} //###########################################################
// Produto de matrizes 
double** PdeM(double** A, double** B, int a, int b, int c ) 
{ 
double **P, aux; 
P=(double **) malloc (a * sizeof(double*)); 
for(int i=0; i<a; i++) 
P[i]=(double *) malloc (c * sizeof(double)); 
for(int i=0; i<a; i++) 
for(int j=0; j<c; j++){ 
aux=0; 
for(int k=0; k<b; k++) 
aux=aux+A[i][k]*B[k][j]; 
P[i][j]=aux; 
} 
return P; 
} //############################################################ // Transposta de Matriz 
double** TdeM(double** A, int a, int b) 
{ 
double **B; 
B=(double **) malloc (b * sizeof(double*)); 
for(int i=0; i<b; i++) 
B[i]=(double *) malloc (a * sizeof(double)); 
for(int i=0; i<b; i++) 
for(int j=0; j<a; j++) 
B[i][j]=A[j][i]; 
return B; 
} //############################################################ // Soma de Matriz 
double** SdeM(double** A, double** B, int a, int b) 
{ 
double **C; 
C=(double **) malloc (a * sizeof(double*)); 
for(int i=0; i<a; i++) 
C[i]=(double *) malloc (b * sizeof(double)); 
for(int i=0; i<a; i++) 
for(int j=0; j<b; j++) 
C[i][j]=B[i][j]+A[i][j]; 
return C; 
} //############################################################ // Subtração de Matriz 
double** SUdeM(double** A, double** B, int a, int b) 
{ 
double **C; 
C=(double **) malloc (a * sizeof(double*)); 
for(int i=0; i<a; i++) 
C[i]=(double *) malloc (b * sizeof(double)); 
for(int i=0; i<a; i++) 
for(int j=0; j<b; j++) 
C[i][j]=A[i][j]-B[i][j]; 
return C; 
}
//########################################################### void propaga_q (){ 
W[0][0] = 0; 
W[0][1] = -wm[0][0]/2; 
W[0][2] = -wm[1][0]/2; 
W[0][3] = -wm[2][0]/2; 
W[1][0] = wm[0][0]/2; 
W[1][1] = 0; 
W[1][2] = wm[2][0]/2; 
W[1][3] = -wm[1][0]/2; 
W[2][0] = wm[1][0]/2; 
W[2][1] = -wm[2][0]/2; 
W[2][2] = 0; 
W[2][3] = wm[0][0]/2; 
W[3][0] = wm[2][0]/2; 
W[3][1] = wm[1][0]/2; 
W[3][2] = -wm[0][0]/2; 
W[3][3] = 0; 
n_w = sqrt(wm[0][0]*wm[0][0] 
+wm[1][0]*wm[1][0] 
+wm[2][0]*wm[2][0]); 
c = cos(n_w*dt/2); 
s = sin(n_w*dt/2)/n_w; 
for(int i=0; i<4; i++) 
for(int j=0; j<4; j++) 
if(i==j){ 
S[i][j] = s; 
C[i][j] = c; 
} 
else{ 
S[i][j] = 0; 
C[i][j] = 0; 
} 
S = PdeM(S, W, 4, 4, 4); 
fi = SdeM(C, S, 4, 4); //matriz de transição de estado 
q = PdeM(fi, q, 4, 4, 1); // propagacão do quatérnion 
} //########################################################### void FCsi_k(){ 
Csi_k[0][0] = -q[1][0]; 
Csi_k[0][1] = -q[2][0]; 
Csi_k[0][2] = -q[3][0]; 
Csi_k[1][0] = q[0][0]; 
Csi_k[1][1] = -q[3][0]; 
Csi_k[1][2] = q[2][0]; 
Csi_k[2][0] = q[3][0]; 
Csi_k[2][1] = q[0][0]; 
Csi_k[2][2] = -q[1][0]; 
Csi_k[3][0] = -q[2][0]; 
Csi_k[3][1] = q[1][0]; 
Csi_k[3][2] = q[0][0]; 
}
//########################################################## void q2DCM() { 
D_q_k[0][0] = 1-2*(q[2][0]*q[2][0]-q[3][0]*q[3][0]); D_q_k[0][1] = 2*(q[1][0]*q[2][0]+q[0][0]*q[3][0]); D_q_k[0][2] = 2*(q[1][0]*q[3][0]-q[0][0]*q[2][0]); D_q_k[1][0] = 2*(q[1][0]*q[2][0]-q[0][0]*q[3][0]); D_q_k[1][1] = 1-2*(q[1][0]*q[1][0]-q[3][0]*q[3][0]); D_q_k[1][2] = 2*(q[3][0]*q[2][0]+q[0][0]*q[1][0]); D_q_k[2][0] = 2*(q[1][0]*q[3][0]+q[0][0]*q[2][0]); D_q_k[2][1] = 2*(q[3][0]*q[2][0]-q[0][0]*q[1][0]); D_q_k[2][2] = 1-2*(q[1][0]*q[1][0]-q[2][0]*q[2][0]); 
} //########################################################## void dDdq() { 
dDdq1[0][0] = 2*q[0][0]; 
dDdq1[0][1] = 2*q[3][0]; 
dDdq1[0][2] = -2*q[2][0]; 
dDdq1[1][0] = -2*q[3][0]; 
dDdq1[1][1] = 2*q[0][0]; 
dDdq1[1][2] = 2*q[1][0]; 
dDdq1[2][0] = 2*q[2][0]; 
dDdq1[2][1] = -2*q[1][0]; 
dDdq1[2][2] = 2*q[0][0]; 
dDdq2[0][0] = 2*q[1][0]; 
dDdq2[0][1] = 2*q[2][0]; 
dDdq2[0][2] = 2*q[3][0]; 
dDdq2[1][0] = 2*q[2][0]; 
dDdq2[1][1] = -2*q[1][0]; 
dDdq2[1][2] = 2*q[0][0]; 
dDdq2[2][0] = 2*q[3][0]; 
dDdq2[2][1] = -2*q[0][0]; 
dDdq2[2][2] = -2*q[1][0]; 
dDdq3[0][0] = -2*q[2][0]; 
dDdq3[0][1] = 2*q[1][0]; 
dDdq3[0][2] = -2*q[0][0]; 
dDdq3[1][0] = 2*q[1][0]; 
dDdq3[1][1] = 2*q[2][0]; 
dDdq3[1][2] = 2*q[3][0]; 
dDdq3[2][0] = 2*q[0][0]; 
dDdq3[2][1] = 2*q[3][0]; 
dDdq3[2][2] = -2*q[2][0]; 
dDdq4[0][0] = -2*q[3][0]; 
dDdq4[0][1] = 2*q[0][0]; 
dDdq4[0][2] = 2*q[1][0]; 
dDdq4[1][0] = -2*q[0][0]; 
dDdq4[1][1] = -2*q[3][0]; 
dDdq4[1][2] = 2*q[2][0]; 
dDdq4[2][0] = 2*q[1][0]; 
dDdq4[2][1] = 2*q[2][0]; 
dDdq4[2][2] = 2*q[3][0]; 
}
//########################################################## void FH_q() { 
H_1_q1 = PdeM(dDdq1, r1, 3, 3, 1); 
H_1_q2 = PdeM(dDdq2, r1, 3, 3, 1); 
H_1_q3 = PdeM(dDdq3, r1, 3, 3, 1); 
H_1_q4 = PdeM(dDdq4, r1, 3, 3, 1); 
H_2_q1 = PdeM(dDdq1, r2, 3, 3, 1); 
H_2_q2 = PdeM(dDdq2, r2, 3, 3, 1); 
H_2_q3 = PdeM(dDdq3, r2, 3, 3, 1); 
H_2_q4 = PdeM(dDdq4, r2, 3, 3, 1); 
H_q[0][0] = H_1_q1[0][0]; 
H_q[0][1] = H_1_q2[0][0]; 
H_q[0][2] = H_1_q3[0][0]; 
H_q[0][3] = H_1_q4[0][0]; 
H_q[1][0] = H_1_q1[1][0]; 
H_q[1][1] = H_1_q2[1][0]; 
H_q[1][2] = H_1_q3[1][0]; 
H_q[1][3] = H_1_q4[1][0]; 
H_q[2][0] = H_1_q1[2][0]; 
H_q[2][1] = H_1_q2[2][0]; 
H_q[2][2] = H_1_q3[2][0]; 
H_q[2][3] = H_1_q4[2][0]; 
H_q[3][0] = H_2_q1[0][0]; 
H_q[3][1] = H_2_q2[0][0]; 
H_q[3][2] = H_2_q3[0][0]; 
H_q[3][3] = H_2_q4[0][0]; 
H_q[4][0] = H_2_q1[1][0]; 
H_q[4][1] = H_2_q2[1][0]; 
H_q[4][2] = H_2_q3[1][0]; 
H_q[4][3] = H_2_q4[1][0]; 
H_q[5][0] = H_2_q1[2][0]; 
H_q[5][1] = H_2_q2[2][0]; 
H_q[5][2] = H_2_q3[2][0]; 
H_q[5][3] = H_2_q4[2][0]; 
} 
//########################################################## //Inversão de Matriz utilizando o método de Gauss-Jordam 
int inv(double **A, int n) { 
// A = matriz de entrada e também de saida 
int pivrow; 
int k,i,j; 
int* pivrows; 
pivrows=(int *) malloc (n * sizeof(int)); 
float tmp; 
for (k = 0; k < n; k++) { 
tmp = 0; 
for (i = k; i < n; i++) 
if (abs(A[i][k]) >= tmp) { 
tmp = abs(A[i][k]); 
pivrow = i; 
} 
if (A[pivrow][k] == 0.0f) 
return 0; //Inversão falha pois é matriz 
//singular
if (pivrow != k) { 
for (j = 0; j < n; j++) { 
tmp = A[k][j]; 
A[k][j] = A[pivrow][j]; 
A[pivrow][j] = tmp; 
} 
} 
pivrows[k] = pivrow; 
tmp = 1.0f/A[k][k]; 
A[k][k] = 1.0f; 
for (j = 0; j < n; j++) 
A[k][j] = A[k][j]*tmp; 
for (i = 0; i < n; i++) { 
if (i != k) { 
tmp = A[i][k]; 
A[i][k] = 0.0f; 
for (j = 0; j < n; j++) { 
A[i][j] = A[i][j] - A[k][j]*tmp; 
} 
} 
} 
} 
for (k = n-1; k >= 0; k--) { 
if (pivrows[k] != k) { 
for (i = 0; i < n; i++) { 
tmp = A[i][k]; 
A[i][k] = A[i][pivrows[k]]; 
A[i][pivrows[k]] = tmp; 
} 
} 
} 
return 1; 
} 
//########################################################## 
void setup() { 
cam1.begin(); 
cam2.begin(); 
cam1.LEDOn(LED_BLINK); 
cam2.LEDOn(LED_BLINK); 
delay(WAIT_TIME); 
cam1.autoGainControl(false); cam2.autoGainControl(false); 
cam1.autoWhiteBalance(false); cam2.autoWhiteBalance(false); 
cam1.LEDOn(CMUCAM4_LED_ON); 
cam2.LEDOn(CMUCAM4_LED_ON); 
//---------------------------------------------------------- Wire.begin(); 
accelgyro.initialize(); 
//----------------------------------------------------------
C = (double **) malloc (4 * sizeof(double*)); 
for(int i=0; i<4; i++) 
C[i]=(double *) malloc (4 * sizeof(double)); 
S = (double **) malloc (4 * sizeof(double*)); 
for(int i=0; i<4; i++) 
S[i]=(double *) malloc (4 * sizeof(double)); 
fi = (double **) malloc (4 * sizeof(double*)); 
for(int i=0; i<4; i++) 
fi[i]=(double *) malloc (4 * sizeof(double)); 
q=(double **) malloc (4 * sizeof(double*)); 
for(int i=0; i<4; i++) 
q[i]=(double *) malloc (sizeof(double)); 
wm=(double **) malloc (3 * sizeof(double*)); 
for(int i=0; i<3; i++) 
wm[i]=(double *) malloc (sizeof(double)); 
W=(double **) malloc (4 * sizeof(double*)); 
for(int i=0; i<4; i++) 
W[i]=(double *) malloc (4 * sizeof(double)); 
Csi_k=(double **) malloc (4 * sizeof(double*)); 
for(int i=0; i<4; i++) 
Csi_k[i]=(double *) malloc (3 * sizeof(double)); 
Gama_k=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) 
Gama_k[i]=(double *) malloc (3 * sizeof(double)); 
Q_q_k=(double **) malloc (4 * sizeof(double*)); 
for(int i=0; i<4; i++) 
Q_q_k[i]=(double *) malloc (4 * sizeof(double)); 
Q=(double **) malloc (3 * sizeof(double*)); 
for(int i=0; i<3; i++) 
Q[i]=(double *) malloc (3 * sizeof(double)); 
Pk=(double **) malloc (4 * sizeof(double*)); 
for(int i=0; i<4; i++) 
Pk[i]=(double *) malloc (4 * sizeof(double)); 
D_q_k=(double **) malloc (3 * sizeof(double*)); 
for(int i=0; i<3; i++) 
D_q_k[i]=(double *) malloc (3 * sizeof(double)); 
b_e=(double **) malloc (6 * sizeof(double*)); 
for(int i=0; i<6; i++) 
b_e[i]=(double *) malloc (6 * sizeof(double));
b1_e=(double **) malloc (3 * sizeof(double*)); 
for(int i=0; i<3; i++) 
b1_e[i]=(double *) malloc (3 * sizeof(double)); 
b2_e=(double **) malloc (3 * sizeof(double*)); 
for(int i=0; i<3; i++) 
b2_e[i]=(double *) malloc (3 * sizeof(double)); 
r1=(double **) malloc (3 * sizeof(double*)); 
for(int i=0; i<3; i++) 
r1[i]=(double *) malloc (3 * sizeof(double)); 
r2=(double **) malloc (3 * sizeof(double*)); 
for(int i=0; i<3; i++) 
r2[i]=(double *) malloc (3 * sizeof(double)); 
dDdq1=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
dDdq1[i]=(double *) malloc (3 * sizeof(double)); 
dDdq2=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
dDdq2[i]=(double *) malloc (3 * sizeof(double)); 
dDdq3=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
dDdq3[i]=(double *) malloc (3 * sizeof(double)); 
dDdq4=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
dDdq4[i]=(double *) malloc (3 * sizeof(double)); 
H_1_q1=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
H_1_q1[i]=(double *) malloc (sizeof(double)); 
H_1_q2=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
H_1_q2[i]=(double *) malloc (sizeof(double)); 
H_1_q3=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
H_1_q3[i]=(double *) malloc (sizeof(double)); 
H_1_q4=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
H_1_q4[i]=(double *) malloc (sizeof(double)); 
H_2_q1=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
H_2_q1[i]=(double *) malloc (sizeof(double));
H_2_q2=(double **) malloc (3 * sizeof(double*)); 
for(int i=0; i<3; i++) 
H_2_q2[i]=(double *) malloc (sizeof(double)); 
H_2_q3=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
H_2_q3[i]=(double *) malloc (sizeof(double)); 
H_2_q4=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) 
H_2_q4[i]=(double *) malloc (sizeof(double)); 
H_q=(double **) malloc (6 * sizeof(double*)); 
for(int i=0; i<6; i++) 
H_q[i]=(double *) malloc (4 * sizeof(double)); 
P_b=(double **) malloc (6 * sizeof(double*)); 
for(int i=0; i<6; i++) 
P_b[i]=(double *) malloc (6 * sizeof(double)); 
R=(double **) malloc (6 * sizeof(double*)); 
for(int i=0; i<6; i++) 
R[i]=(double *) malloc (6 * sizeof(double)); 
P_b_q=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) 
P_b_q[i]=(double *) malloc (6 * sizeof(double)); 
K=(double **) malloc (4 * sizeof(double*)); 
for(int i=0; i<4; i++) 
K[i]=(double *) malloc (6 * sizeof(double)); 
P_b_n_inv=(double **) malloc (6 * sizeof(double*)); for(int i=0; i<6; i++) 
P_b_n_inv[i]=(double *)malloc(6*sizeof(double)); 
b=(double **) malloc (6 * sizeof(double*)); 
for(int i=0; i<6; i++) 
b[i]=(double *) malloc (sizeof(double)); 
for(int i=0; i<3; i++) 
for(int j=0; j<3; j++) 
if(i==j) 
Q[i][j] = 0.000025; 
else 
Q[i][j] = 0; 
for(int i=0; i<4; i++) 
for(int j=0; j<4; j++) 
if(i==j) Pk[i][j] = 0.01; 
else Pk[i][j] = 0;
for(int i=0; i<6; i++) 
for(int j=0; j<6; j++) 
if(i==j) 
R[i][j] = 0.0001; 
else 
R[i][j] = 0; 
q[0][0]=1; 
q[1][0]=0; 
q[2][0]=0; 
q[3][0]=0; 
} 
//########################################################## void loop() { 
cam1.trackColor(R_MIN_1, R_MAX_1, G_MIN_1, G_MAX_1, 
B_MIN_1, B_MAX_1); 
cam2.trackColor(R_MIN_2, R_MAX_2, G_MIN_2, G_MAX_2, 
B_MIN_2, B_MAX_2); 
delay(WAIT_TIME); 
cam1.getTypeTDataPacket(&data1); cam2.getTypeTDataPacket(&data2); 
r1[0][0] = sin(atan((data1.mx-80)/K1)); 
r1[1][0] = sin(atan((data1.my-60)/K1)); 
r1[2][0] = sqrt(1-r1[0][0]*r1[0][0]-r1[1][0]*r1[1][0]); r2[0][0] = sin(atan((data2.mx-80)/K1)); 
r2[1][0] = sin(atan((data2.my-60)/K1)); 
r2[2][0] = sqrt(1-r2[0][0]*r2[0][0]-r2[1][0]*r2[1][0]); 
for(;;) { 
accelgyro.getRotation(&gx, &gy, &gz); 
//medidas feitas juntas 
cam1.getTypeTDataPacket(&data1); 
cam2.getTypeTDataPacket(&data2); 
wm[0][0]=gx*pi/(16.4*180); 
wm[1][0]=gy*pi/(16.4*180); 
wm[2][0]=gz*pi/(16.4*180); 
//---------------------------------------------------------- //1a - Propagação do estado estimado 
FCsi_k(); 
propaga_q(); 
Gama_k = PdeEeM((dt/2),PdeM(fi,Csi_k,4,4,3),4,3); 
Q_q_k = PdeM(Gama_k,PdeM(Q,TdeM(Gama_k,4,3), 
3,3,4),4,3,4); 
Pk = SdeM(PdeM(PdeM(fi,Pk,4,4,4), 
TdeM(fi,4,4),4,4,4),Q_q_k,4,4); 
//---------------------------------------------------------- //1b - Predição das medidas 
q2DCM(); 
b1_e = PdeM(D_q_k, r1, 3, 3, 1); 
b2_e = PdeM(D_q_k, r2, 3, 3, 1);
b_e[0][0] = b1_e[0][0]; 
b_e[1][0] = b1_e[1][0]; 
b_e[2][0] = b1_e[2][0]; 
b_e[3][0] = b2_e[0][0]; 
b_e[4][0] = b2_e[1][0]; 
b_e[5][0] = b2_e[2][0]; 
dDdq(); 
FH_q(); 
P_b = SdeM(PdeM(PdeM(H_q,Pk,6,4,4), 
TdeM(H_q,6,4),6,4,6),R,6,6); 
//---------------------------------------------------------- //1c - Covariância cruzada 
P_b_q = PdeM(Pk, TdeM(H_q, 6, 4), 4, 4, 6); 
//---------------------------------------------------------- 
//2a - Ganho 
for(int i=0; i<6; i++) 
for(int k=0; k<6; k++) 
P_b_n_inv[i][k]=P_b[i][k]; 
inv(P_b, 6); //retorna 0 em falha, e 1 em sucesso 
K = PdeM(P_b_q, P_b, 4, 6, 6); 
//---------------------------------------------------------- //2b - Atualização da estimativa 
b[0][0] = sin(atan((data1.mx-80)/K1)); 
b[1][0] = sin(atan((data1.my-60)/K1)); 
b[2][0] = sqrt(1-b[0][0]*b[0][0]-b[1][0]*b[1][0]); 
b[3][0] = sin(atan((data2.mx-80)/K1)); 
b[4][0] = sin(atan((data2.my-60)/K1)); 
b[5][0] = sqrt(1-b[3][0]*b[3][0]-b[4][0]*b[4][0]); 
q = SdeM(q,PdeM(K,SUdeM(b,b_e,6,1),4,6,1),4,1); 
Pk = SUdeM(Pk,PdeM(PdeM(K,P_b_n_inv,4,6,6), 
TdeM(K,4,6),4,6,4),4,4); 
//########################################################## 
//3 - Normalização 
q = PdeEeM((1/sqrt( q[0][0]*q[0][0] 
+q[1][0]*q[1][0] 
+q[2][0]*q[2][0] 
+q[3][0]*q[3][0])),q,4,1); 
} 
}

Mais conteúdo relacionado

Semelhante a Sistema de Navegação Indoor por Imagens para VANT Quadricóptero

Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...Johnnatan Messias
 
(Horus) aerofotogrametria com drones
(Horus) aerofotogrametria com drones(Horus) aerofotogrametria com drones
(Horus) aerofotogrametria com dronesMarcos Martins
 
18.ago ouro i 12.00_211_cesp
18.ago ouro i 12.00_211_cesp18.ago ouro i 12.00_211_cesp
18.ago ouro i 12.00_211_cespitgfiles
 
FInal Project Report - PT
FInal Project Report - PTFInal Project Report - PT
FInal Project Report - PTJoão Cardoso
 
SIGGESC 8 EUE-Portugal
SIGGESC 8 EUE-PortugalSIGGESC 8 EUE-Portugal
SIGGESC 8 EUE-PortugalTiago Oliveira
 
Recom gps internet
Recom gps internetRecom gps internet
Recom gps internetHudson777
 
Gps wi fi para ambientes fechados (indoor)
Gps wi fi para ambientes fechados (indoor)Gps wi fi para ambientes fechados (indoor)
Gps wi fi para ambientes fechados (indoor)Ricardo Francoti
 
Implementation of a Participatory Sensing Solution to Collect Data About Pave...
Implementation of a Participatory Sensing Solution to Collect Data About Pave...Implementation of a Participatory Sensing Solution to Collect Data About Pave...
Implementation of a Participatory Sensing Solution to Collect Data About Pave...Eduardo Carrara de Araujo
 
Controle De Estabilidade de Aeromodelo Tipo Quadcopter Autômato Por Lei De Co...
Controle De Estabilidade de Aeromodelo Tipo Quadcopter Autômato Por Lei De Co...Controle De Estabilidade de Aeromodelo Tipo Quadcopter Autômato Por Lei De Co...
Controle De Estabilidade de Aeromodelo Tipo Quadcopter Autômato Por Lei De Co...Daniel de Castro Ribeiro Resende
 
rua para os cegos
rua para os cegosrua para os cegos
rua para os cegosj397675
 
Sensoriamento Remoto
Sensoriamento RemotoSensoriamento Remoto
Sensoriamento Remotonaiararohling
 
Apresentação do Projeto SIVAM
Apresentação do Projeto SIVAMApresentação do Projeto SIVAM
Apresentação do Projeto SIVAMEdni CP
 
Modelagem de Ambientes de Computação Ubíqua Utilizando Simulação
Modelagem de Ambientes de Computação Ubíqua Utilizando SimulaçãoModelagem de Ambientes de Computação Ubíqua Utilizando Simulação
Modelagem de Ambientes de Computação Ubíqua Utilizando SimulaçãoJurmir Canal Neto
 

Semelhante a Sistema de Navegação Indoor por Imagens para VANT Quadricóptero (20)

Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
Monografia: Framework Para Sistemas de Navegação de Veículos Aéreos Não Tripu...
 
(Horus) aerofotogrametria com drones
(Horus) aerofotogrametria com drones(Horus) aerofotogrametria com drones
(Horus) aerofotogrametria com drones
 
18.ago ouro i 12.00_211_cesp
18.ago ouro i 12.00_211_cesp18.ago ouro i 12.00_211_cesp
18.ago ouro i 12.00_211_cesp
 
CI2018_Simuladores
CI2018_Simuladores CI2018_Simuladores
CI2018_Simuladores
 
Gerencia_Portugal.pdf
Gerencia_Portugal.pdfGerencia_Portugal.pdf
Gerencia_Portugal.pdf
 
FInal Project Report - PT
FInal Project Report - PTFInal Project Report - PT
FInal Project Report - PT
 
SIGGESC 8 EUE-Portugal
SIGGESC 8 EUE-PortugalSIGGESC 8 EUE-Portugal
SIGGESC 8 EUE-Portugal
 
Recom gps internet
Recom gps internetRecom gps internet
Recom gps internet
 
NAV INERCIAL
NAV INERCIALNAV INERCIAL
NAV INERCIAL
 
Gps wi fi para ambientes fechados (indoor)
Gps wi fi para ambientes fechados (indoor)Gps wi fi para ambientes fechados (indoor)
Gps wi fi para ambientes fechados (indoor)
 
RodoCap no JustJava 2008
RodoCap no JustJava 2008RodoCap no JustJava 2008
RodoCap no JustJava 2008
 
Mr1
Mr1Mr1
Mr1
 
Implementation of a Participatory Sensing Solution to Collect Data About Pave...
Implementation of a Participatory Sensing Solution to Collect Data About Pave...Implementation of a Participatory Sensing Solution to Collect Data About Pave...
Implementation of a Participatory Sensing Solution to Collect Data About Pave...
 
Controle De Estabilidade de Aeromodelo Tipo Quadcopter Autômato Por Lei De Co...
Controle De Estabilidade de Aeromodelo Tipo Quadcopter Autômato Por Lei De Co...Controle De Estabilidade de Aeromodelo Tipo Quadcopter Autômato Por Lei De Co...
Controle De Estabilidade de Aeromodelo Tipo Quadcopter Autômato Por Lei De Co...
 
rua para os cegos
rua para os cegosrua para os cegos
rua para os cegos
 
Monopoli10005898
Monopoli10005898Monopoli10005898
Monopoli10005898
 
Sensoriamento Remoto
Sensoriamento RemotoSensoriamento Remoto
Sensoriamento Remoto
 
Apresentação do Projeto SIVAM
Apresentação do Projeto SIVAMApresentação do Projeto SIVAM
Apresentação do Projeto SIVAM
 
Sbai2003
Sbai2003Sbai2003
Sbai2003
 
Modelagem de Ambientes de Computação Ubíqua Utilizando Simulação
Modelagem de Ambientes de Computação Ubíqua Utilizando SimulaçãoModelagem de Ambientes de Computação Ubíqua Utilizando Simulação
Modelagem de Ambientes de Computação Ubíqua Utilizando Simulação
 

Sistema de Navegação Indoor por Imagens para VANT Quadricóptero

  • 1. INSTITUTO TECNOLÓGICO DE AERONÁUTICA CONSELHO NACIONAL DE DESENVOLVIMENTO CIENTÍFICO E TECNOLÓGICO - CNPq CNPq CONSELHO NACIONAL DE DESENVOLVIMENTO CIENTÍFICO E TECNOLÓGICO PROGRAMA INSTITUCIONAL DE BOLSAS DE INICIAÇÃO CIENTÍFICA - PIBIC Desenvolvimento de um Sistema de Navegação Indoor por Imagens para um Veículo Aéreo não Tripulado do tipo Quadricóptero Roberto Brusnicki RELATÓRIO FINAL DE ATIVIDADES Orientador: Dr. Davi Antônio dos Santos 08 / 2013
  • 2. INSTITUTO TECNOLÓGICO DE AERONÁUTICA CONSELHO NACIONAL DE DESENVOLVIMENTO CIENTÍFICO E TECNOLÓGICO - CNPq CNPq CONSELHO NACIONAL DE DESENVOLVIMENTO CIENTÍFICO E TECNOLÓGICO PROGRAMA INSTITUCIONAL DE BOLSAS DE INICIAÇÃO CIENTÍFICA - PIBIC Relatório Final de Atividades Desenvolvimento de um Sistema de Navegação indoor por Imagens para um Veículo Aéreo não Tripulado do tipo Quadricóptero São José dos Campos, 03 / 08 / 2013 Nome do aluno Roberto Brusnicki Assinatura do aluno Nome do orientador Davi Antônio dos Santos Assinatura do orientador
  • 3. INSTITUTO TECNOLÓGICO DE AERONÁUTICA PROGRAMA INSTITUCIONAL DE BOLSAS DE INICIAÇÃO CIENTÍFICA - PIBIC Formulário de Aprovação de Relatório pelo Orientador Relatório: Rel. Parcial X Rel. Final 1- CONSIDERO O RELATÓRIO APROVADO COM BASE NOS SEGUINTES ASPECTOS 2- APRECIAÇÕES DO ORIENTADOR SOBRE O DESEMPENHO DO BOLSISTA NA EXECUÇÃO DO TRABALHO DE INICIAÇÃO CIENTÍFICA Local e data: Assinatura do Orientador:
  • 4. ÍNDICE 1. INTRODUÇÃO .................................................................................................................... 4 2. ANDAMENTO E PLANEJAMENTO ........................................................................................... 6 2.1. RESUMO DO PLANO INICIAL ............................................................................................. 6 2.2. RESUMO DAS ATIVIDADES REALIZADAS ............................................................................... 7 3. DEFINIÇÃO DO PROBLEMA ................................................................................................... 9 4. FORMULAÇÃO DO FILTRO .................................................................................................. 10 4.1. ESTIMAÇÃO DE QUATÉRNIO ........................................................................................... 10 4.2. QEKF ....................................................................................................................... 13 4.2. OBTENÇÃO DOS VETORES UNITÁRIOS .............................................................................. 14 5. SIMULAÇÕES COMPUTACIONAIS ......................................................................................... 16 6. OBTENÇÃO DOS DADOS EM TEMPO REAL POR COMUNICAÇÃO SERIAL ........................................ 21 7. CONCLUSÕES .................................................................................................................. 22 8. AGRADECIMENTOS........................................................................................................... 23 9. BIBLIOGRAFIA ................................................................................................................. 23 CÓDIGOS DO FILTRO DE KALMAN PARA ESTIMAÇÃO DE QUATÉRNIO DE ROTAÇÃO ANEXO 1: (MATLAB) ............................................................................................................. 24 ANEXO 2: (C - ARDUINO)....................................................................................................... 27 1. INTRODUÇÃO Este trabalho está envolvido com VANTS do tipo quadricóptero, que consiste em veículo com capacidade de decolagem e aterrissagem verticais constituído de quatro rotores acionados por motores elétricos individuais e independentes. Para que um VANT quadricóptero tenha sua trajetória controlada em malha fechada e de forma autônoma, faz-se necessário que esse veículo embarque um Sistema de Navegação (SN), que consiste em um dispositivo capaz de estimar, em tempo real, sua posição, sua velocidade linear, sua atitude (orientação) e sua velocidade angular. A função de um sistema de controle por realimentação é essencialmente fazer com que medidas/estimativas de variáveis dinâmicas (como atitude, posição e velocidade) rastreiem trajetórias desejadas. Por essa razão, um controle confiável, acurado e robusto requer um SN com as mesmas propriedades qualitativas. A importância de um SN para o funcionamento adequado de VANTs autônomos motiva uma avaliação detalhada de seus componentes e métodos. Em particular, a chamada navegação inercial é a forma tradicional de se realizar navegação por meio da integração das medidas dos sensores inerciais (acelerômetros e girômetros) embarcados no veículo de interesse. A principal vantagem da navegação inercial pura é sua independência em relação a sinais externos e a condições de visibilidade e sua imunidade a interferências intencionais, como o jamming. Graças a essas características, os sensores inerciais são bastante apropriados para operar em ambientes como túneis, cavernas e interiores de prédios.
  • 5. A despeito de sua independência em relação a sinais externos ao sistema, a navegação inercial pura apresenta a significativa desvantagem de produzir estimativas de posição, velocidade e atitude cujos erros divergem sem limites com o tempo. Essa é uma característica bem conhecida, que é explicada, em breves palavras, pelo fato de que junto com acelerações e velocidades angulares, o sistema também integra ao longo do tempo os vieses e derivas dos sensores. De forma a limitar os erros divergentes de sistemas de navegação inerciais puros, invoca-se frequentemente o uso de fusão de sensores para permitir a combinação das medidas inerciais com aquelas providas por outros sensores, como magnetômetros, sensores ultrassônicos, GPS, câmera, entre outros. Os métodos de fusão sensorial mais comuns são aqueles baseados no filtro de Kalman, ferramenta que provê um framework para estimar variáveis dinâmicas (estados) de um sistema a partir de sequências de medidas adquiridas de diversos sensores. A fusão de dados de GPS e sensores inerciais é um tópico importante e já bem estudado. Os esquemas de fusão GPS-INS têm aplicações em diversas áreas, como aviação, guiamento de satélites, aproximação e pouso automáticos de aeronaves, aplicações marítimas e, em especial, em navegação de VANTs. O sucesso desses esquemas se deve principalmente à complementaridade das características típicas dos erros de medição de GPS e de sensores inerciais. A navegação baseada apenas na integração de medidas dos sensores inerciais (navegação inercial pura) é precisa num curto intervalo de tempo, no entanto, resulta em estimativas de posição que se degradam sem limites devido à existência de vieses em acelerômetros e de derivas em girômetros. Com base na estrutura do filtro de Kalman, medidas de sensores inerciais e de GPS podem ser fundidas, segundo uma variedade de esquemas de implementação, permitindo um desempenho de estimação (de posição, velocidade e atitude) superior a ambos os subsistemas individualmente. Infelizmente, a navegação inercial assistida por GPS pode carecer de confiabilidade quando opera em lugares com linhas de visada deficientes em relação aos satélites do sistema GPS. Exemplos de tais lugares são: interiores de prédios, cavernas, minas, cânions urbanos e em florestas (entre árvores, por exemplo). De forma a compensar essas limitações, o uso de câmera digital como auxílio à navegação tem recentemente atraído o interesse de pesquisadores. A fusão INS-Câmera basicamente consiste no uso de câmera(s) digital(is) para medir/rastrear a posição de features numa sequência de imagens e, com base na estrutura do filtro de Kalman, usar tais informações para estimar erros de navegação/erros de sensores e compensá-los nas estimativas de posição, velocidade e atitude. Esses esquemas de fusão parecem ser especialmente adequados para a navegação em ambientes indoor contendo landmarks, que oferecem informações substancialmente ricas para a navegação do veículo. O restante deste trabalho está organizado da seguinte maneira. O Capítulo 2 apresenta um resumo da proposta inicial, a descrição dos trabalhos realizados durante o
  • 6. período 2012/2 e o planejamento para as próximas atividades. O Capítulo 3 define o problema de controle de determinação de atitude e navegação usando sensores inerciais e uma câmera embarcada apontada verticalmente para baixo. O Capítulo 4 apresenta a formulação de um filtro de Kalman que soluciona o problema de determinação de atitude. O Capítulo 5 apresenta alguns resultados de avaliações realizadas por simulações computacionais. Por fim, o Capítulo 6 apresenta as conclusões da etapa parcial a que se refere este relatório. 2. ANDAMENTO E PLANEJAMENTO 2.1. RESUMO DO PLANO INICIAL Este trabalho tem como objetivo desenvolver um sistema de navegação de baixo custo apropriado para voo indoor equipado com, dentre outros sensores, uma câmera, a ser utilizado em um VANT (Veículo Aéreo Não Tripulado) de pequeno porte do tipo quadricóptero (que consiste de um veículo com capacidade de decolagem e aterrissagem verticais constituído de quatro rotores acionados por motores elétricos individuais e independentes), que será projetado, fabricado e posteriormente avaliado experimentalmente. Para alcançar-se tal objetivo, faz-se necessário dotar o sistema de navegação a ser desenvolvido para o VANT de vários sensores que por meio de medidas possibilite o voo autônomo estável e controlado. Esse sistema deve ser equipado com um acelerômetro de 3 eixos para determinação de acelerações lineares, um giroscópio de 3 eixos para determinação de velocidades angulares, um sensor ultrassônico para medição de altitude, e de uma câmera para obtenção de imagens. A Metodologia adotada consiste em inicialmente construir-se um quadricóptero elétrico utilizando componentes de aeromodelismo, e verificar seu funcionamento através de testes rádio controlados. Dado isto, integrar ao quadricóptero a parte física do sistema de navegação a ser desenvolvido, ou seja, uma plataforma em que se encontrem os sensores supracitados. Posteriormente, o desenvolvimento do software do sistema de navegação, o qual consiste basicamente de um filtro de Kalman para fusão dos sensores inerciais, sensor ultrassônico de altitude e a câmera. Este último passo possui implícito todo o estudo a cerca de processos estocásticos, bem como o estudo do filtro de Kalman, e da física do problema, assim como simulação de seu funcionamento anteriormente a sua utilização no VANT propriamente dito.
  • 7. 2.2. RESUMO DAS ATIVIDADES REALIZADAS 1) Construção Inicialmente construiu-se o quadricóptero com peças de aeromodelismo. O que se consiste basicamente do frame em formato de cruz, os 4 motores elétricos do tipo brushless, suas respectivas hélices, e o sistema de alimentação, constituído pelos eletronic speed controllers (ESC’s) cabos de alimentação e da bateria de polímero de Lítio. Além disto, tal quadricóptero possui também um Arduíno Mega como micro controlador utilizado para seu sistema de navegação. O software utilizado para fazer a estabilização de atitude consiste do Aeroquad open-sourse. Esta primeira fase permitiu a familiarização com o funcionamento deste modelo relativamente novo de VANTs, sem que houvesse excessiva preocupação com eventuais danos causados aos seus componentes devido a um mau controle de seu voo, pois não estaria voando de maneira autônoma, mas sim de maneira radio-controlada. 2) Embasamento Teórico Com a finalidade de se adquirir o embasamento matemático necessário para a realização deste trabalho, foram estudados os seguintes tópicos:  Variáveis aleatórias e processos estocásticos. Parte dessa preparação foi realizada através da disciplina de graduação MOQ-13 (Probabilidade e Estatística);  Filtro de Kalman. Foram estudadas diversas formulações do filtro de Kalman: discreta-discreta, contínua-discreta tando para o filtro linear quanto para o filtro de Kalman estendido. As referências utilizadas foram (Gelb, 1974) [1] e (Hwang e Brown, 1997) [2];  Cinemática de atitude. Foram estudadas as diversas representações de atitude bem como as respectivas equações diferenciais que modelam a dinâmica de atitude em função das velocidades angulares do veículo ao longo do tempo. Existem várias possibilidades de parametrização de atitude, dentre elas, as mais recorrentes são: ângulos de Euler, matriz de cossenos diretores (DCM), quaternion de rotação e parâmetros modificados de Rodrigues. A referência adotada foi (Shuster, 1993) [4]. 3) Simulações computacionais Adotou-se o MATLAB como ambiente de simulação. Foram simuladas a cinemática de atitude do veículo bem como as medidas dos sensores, que são uma
  • 8. câmera embarcada com apontamento vertical voltado para baixo e uma tríade de girômetros. Nesse mesmo ambiente, implementou-se também as equações de um filtro de Kalman estendido discreto-discreto para estimação da atitude representada por quaternion de rotação. Foram realizados diversos testes que possibilitaram uma boa sintonia do filtro e comprovaram sua capacidade de convergência e robustez. 4) Familiarização com os sensores utilizados Adotou-se o uso do sensor GY-521 para obtenção das medidas de velocidade angular, e a CMUCam4 como sensor de rastreamento de cores para obtenção dos vetores unitários indicados na figura 3. Ambos os sensores escolhidos atendem ao proposto pelo projeto, sendo sensores de baixo custo, mas que com sistema de navegação desenvolvido fornecem dados bom o suficiente para se fazer a estimação da atitude do quadricóptero com alta precisão. Uma das vantagens de se ter trabalho com o sensor GY-521, é que este também possui um acelerômetro de 3 eixos, sendo estas medidas necessárias em um trabalho posterior em que utilizará o sistema de navegação em movimento. A CMUCam4 consiste em um sensor de visão computacional programável, que pode ser utilizado como rastreador de cor, entre inúmeras outras funções. Ambos os sensores foram utilizados neste projeto em conjunto com o microprocessador Arduino Mega, tendo sido necessário um tempo de estudo de suas bibliotecas, funções, configurações, e utilização de modo a otimizar a obtenção dos dados necessários. Figura 1: (a) Sensor de rastreamento de cores CMUCam4. (b) IMU de 6 graus GY-521.
  • 9. 5) Simulações computacionais com obtenção dos dados em tempo real, e familiarização com comunicação serial entre Arduino e MATLAB Tendo-se o código no MATLAB funcionando de maneira precisa com a simulação, adaptou-se este para que utilizasse os dados provenientes em tempo real dos sensores acoplados ao Arduino Mega. Para tal utilização, foi-se necessário significativo tempo na familiarização com a comunicação serial necessária entre ambos os softwares (Arduino IDE, e MATLAB). Além disto, foi-se necessário escrever o código do Arduíno que obtivesse os dados dos sensores, e os enviassem para o computador através da porta serial. Foram realizados alguns testes, como levantamento das distribuições das medidas dos sensores, que possibilitaram uma excelente sintonia do filtro e uma vez mais comprovaram sua capacidade de convergência e robustez. 6) Tradução do código do Filtro de Kalman para linguagem C. Após atingido o sucesso na simulação com com obtenção de dados em tempo real, passou-se à tradução completa do código do MATLAB para a linguagem C utilizada pelo Arduino, a fim de poder-se testar a viabilidade de utilização do sistema de navegação desenvolvido de maneira totalmente embarcada, não dependendo mais de um computador para nenhum tipo de cálculo. O código completo em linguagem C encontra- se ao término deste relatório no anexo 2. 3. DEFINIÇÃO DO PROBLEMA Com o intuito de modelar o problema de determinação de atitude a partir de medidas vetoriais obtidas pela câmera, considera-se um sistema de eixos cartesianos SB solidário ao corpo do quadricóptero, um sistema de eixos cartesianos SR de referencia, e outro sistema de eixos cartesianos em um referencial inercial (a Terra, por exemplo, assumindo que seu movimento é desprezível). Tais sistemas podem ser visualizados na figura 2. Tanto SB como SR possuem suas origens no centro geométrico do quadricóptero. A câmera utilizada será a CMUCam, que já predispõe de um processamento de imagens e fornece alguns dados, como por exemplo o centroide de regiões de determinada cor. Juntamente com o sensor ultrassônico utilizado (Maxbotix LV-EZ0) obtêm-se as medidas vetoriais que fornecem a direção (do ponto de vista da câmera) de landmarks coloridas dispostas no chão. A câmera encontrara-se fixa ao corpo do quadricóptero, portanto as medidas vetoriais obtidas serão em relação ao sistema de eixos SB. As landmarks estão dispostas no chão de modo a sempre terem-se ao menos duas no campo de visão da câmera. Tais especificações podem ser visualizadas na figura 3.
  • 10. O problema proposto consiste em estimar em tempo real a posição e atitude do quadricóptero como exposto acima. Para estimar-se a atitude, além das medidas vetoriais, utilizam-se também os valores de velocidade angular obtidos pelo girômetro. Além disso, para estimar-se a posição utilizam-se também acelerômetros. Figura 2: Sistemas de eixos cartesianos utilizados para a determinação de atitude. SB, SR e SI correspondem respectivamente aos sistemas de eixos coordenados solidário ao corpo do VANT, de referência e inercial (i.e. no referencial da Terra). Figura 3: Câmera fixa ao quadricóptero, e disposição das landmarks no chão de modo à sempre haver no mínimo duas no campo de visão da câmera a fim de se obter vetores unitários que apontam para as mesmas.
  • 11. 4. FORMULAÇÃO DO FILTRO O método escolhido para resolver o problema definido na Seção 2 consiste num filtro de Kalman estendido para estimação de quatérnio a partir de medidas vetoriais. Para manter a norma do quatérnio estimado próxima de unitária, emprega-se simplesmente uma etapa de normalização Euclidiana das estimativas. Esse filtro será referido como QEKF (quaternion extended Kalman filter). Em seguida, as equações do QEKF são revisadas com base em (SANTOS, 2008). 4.1. Estimação de quatérnio O vetor de estado do estimador de quatérnio de rotação, QEKF, é dado por , onde q1 e são as representações escalar e vetorial, respectivamente, dos componentes real e imaginário de q. Assim, tem-se que a equação de medidas não-linear discreta no tempo dos estimadores de quatérnio de rotação é: ( ) (1) onde, ( ) [ ( ) ( ) ( ) ( ) ( ) ( ) ] : medidas vetoriais feitas no sistema de eixos cartesianos do VANT; : medidas vetoriais em relação ao sistema de referência; : ruído de medição. O modelo de cinemática de atitude para o quatérnio de rotação é dado pela seguinte equação diferencial linear: ̇( ) ( ) ( ) (2) onde, ( ) [ ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ] (3)
  • 12. Em que ( ) ( ) ( ) correspondem respectivamente as velocidades angulares do VANT em relação aos eixos . Integrando (2) de , obtém-se: ( ) (4) Onde ( ) é a matriz de transição de estado. Considerando-se que a velocidade angular ( ) ( ) ( ) ( ) seja constante durante o intervalo de tempo entre amostragens sucessivas das medidas vetoriais, essa matriz é dada por: ( ) (5) onde é computada por (3), mas utilizando em vez de ( ) Substituindo, então, ( ) ̂( ) ( ) na equação anterior: ( ) ( ̂ ) ̂ (6) onde as matrizes ̂ são dadas por (3), porém substituindo ( ) ̂ , respectivamente. Representando o segundo fator do lado direito de (6) pela correspondente série de potências, obtém-se: ( ) ̂ ( ) (7) Considerando-se que sejam ambos pequenos, o truncamento da série em (7) após termos de primeira ordem permite que (4) seja aproximada por: ̂ ̂ (8) Pode-se verificar que: (9) onde, [ ] (10) Sendo assim, utilizando (9) na manipulação do segundo termo do lado direito de (8), finalmente se obtém a seguinte equação de estado discreta no tempo:
  • 13. ̂ ̂ (11) Onde é dado por (10), mas utilizando o quatérnio verdadeiro no instante , no lugar de . Para fins de implementação dos estimadores de quatérnio, a covariância do ruído de estado (segundo termo à direita em (11)) é aproximada por: (12) onde, ̂ ̂ (13) e ̂ é computada por (10), porém utilizando ̂ no lugar de . A exponencial matricial que define a matriz de transição de estado em (5) é aqui computada por: (‖ ‖ ) ‖ ‖ (‖ ‖ ) (14) O quatérnio de rotação apresenta norma unitária e, dessa forma, seus componentes obedecem à restrição . No entanto, a atualização linear do KF, por envolver a operação de soma, não garante que as estimativas de mantenham essa propriedade ao longo da estimação. A forma mais simples de lidar com tal restrição consiste no uso de normalização Euclidiana das estimativas após o estágio de atualização aditiva. Em seguida é apresentado o estimador QEKF, o qual utiliza normalização Euclidiana para garantir que as estimativas tenham normas unitárias. 4.2. QEKF Mediante uso do EKF (Extended Kalman Filter) e tendo-se em vista a equação de estado linear (11) e a equação de medidas não linear (1), obtêm-se os estágios de propagação e de atualização do QEKF. Para garantir que as normas de suas estimativas sejam unitárias, utiliza-se normalização Euclidiana. A estimativa normalizada ̂ ‖ ̂ ‖, apresenta um erro cuja covariância é aproximada no QEKF simplesmente por: (15) O QEKF requer a matriz Jacobiana das medidas,
  • 14. ( ) | ̂ (16) A Tabela 1 apresenta o QEKF. Tabela 1: Estimador de quatérnio de rotação – QEKF (SANTOS, 2008 – pg. 31). Em anexo, ao fim deste relatório encontram-se os códigos do Filtro descrito acima. 4.3. Obtenção dos vetores unitários Após algumas soluções iniciais, em que seriam necessários um sensor a mais a fim de obter-se também uma medida de distância entre a câmera, e o plano em que se encontra a landmark, (neste caso utilizar-se-ia o sensor sonar: Parallax's PING), ou então obter-se a altitude do quadricóptero (para este caso, foi escolhido o sensor altímetro: Sparkfun’s BMP085), e após alguns experimentos com ambos os sensores para determinação da qualidade das medidas fornecidas por estes, abandonou-se ambas as abordagens iniciais, e optou-se por outra cuja necessidade de novo sensor tornou-se desnecessária.
  • 15. Somente com a imagem fornecida pela CMUCam4, é possível determinar-se as coordenadas do vetor unitário que aponta para uma landmark no sistema de eixos do quadricóptero (que consiste no mesmo da câmera). Para tal, faz-se necessário o levantamento de um parâmetro da câmera, denotado aqui por K. K representa a distância entre o plano da imagem vista pela câmera, e a câmera propriamente dita. Porém, o valor de K é dado pelo número de pixels que esta distancia ocuparia (no eixo x ou y) em uma imagem obtida pela câmera, caso esta medida fosse posta em um plano perpendicular ao eixo ótico da câmera afastado exatamente da mesma medida. O valor obtido para K foi de aproximadamente 171, isto significa que para a câmera, em uma imagem visualizada a 1 metro de distância, um objeto com 171 pixels em linha reta (no eixo x ou y da imagem obtida) de dimensão, possui na realidade dimensão de 1 metro. Em uma imagem obtida pela câmera a uma distancia 2 metros de uma parede, 171 pixels desta imagem corresponderiam a um comprimento de 2 metros na parede. E assim por diante. Figura 4: Significado do parâmetro K: Na imagem obtida, K pixels em linha reta correspondem a uma medida no anteparo equivalente à distância entre a câmera e o anteparo. A imagem de trabalho da CMUCam4 consiste em uma matriz de pixels de 120x160, sendo estes numerados de 0 a 119 para o primeiro eixo, e de 0 a 159 para o segundo eixo da imagem. Sendo possível obter esta numeração para os pixels rastreados. Apesar de a CMUCam4 ser, em sua essência, um sensor de cor, por fornecer os valores de RGB de cada pixel de seu campo de visão, é possível utiliza-la para tirar fotos (porém de maneira muito ineficiente e demorada). Sendo assim, foi-se possível realizar experimentos de medições para determinar-se o valor de K com alta precisão.
  • 16. Tendo este parâmetro determinado, por simplicidade supondo-se o centro da imagem vista pela câmera como sendo o pixel com coordenadas ( ), e tendo o eixo ótico da câmera perfeitamente alinhado com o eixo z do sistema de eixos , um vetor que aponta para uma landmark com coordenadas do centroide dadas por ( ) (na imagem fornecida pela CMUCam4, ou seja, x e y são a numeração dos pixels), e com origem na própria câmera, é dado por: ⃗ ( ) (17) Foi-se utilizado o sinal de menos na coordenada z, pois a câmera estará acoplada à parte inferior do quadricóptero, tendo assim sem campo de visão direcionado à parte negativa do semi-eixo z do sistema de eixos . Portanto, sendo a norma do vetor dada por: ‖ ⃗‖ √ (18) Tem-se então que o vetor unitário necessário ao algoritmo desenvolvido é dado por: ⃗⃗ ( ‖ ⃗‖) ⃗ (19) 5. SIMULAÇÕES COMPUTACIONAIS Concentram-se aqui os resultados posteriores as fases de construção e estudos, já que estes são mais significativos como um todo para o trabalho. Inicialmente, a fim de simular os dados de entrada provenientes dos sensores relativos à determinação de atitude, ou seja, girômetros e câmera, plotou-se arbitrariamente funções senoidais bem comportadas para as velocidades angulares (o motivo desta escolha deve-se puramente a tentativa de evitar-se que as velocidades angulares escolhidas impliquem em um movimento muito brusco e distante do que ocorre na realidade com o VANT, fornecendo assim dados mais fidedignos a posterior análise da simulação). A partir destas funções, colhendo-se seus valores em pontos igualmente espaçados de tempo, e adicionando-se um ruído aleatório normalmente distribuído, obtém-se um bom exemplo de valores de medidas provenientes dos giroscópios. Um exemplo deste procedimento pode ser verificado na figura 5.
  • 17. Figura 5: Simulação de velocidades angulares medidas pelos girômetros. Respectivamente em azul, vermelho e verde tem-se: velocidade angular em relação ao eixo x, y e z. Onde x, y e z correspondem a um sistema de eixos ortogonais solidário ao quadricóptero. A partir das funções que geraram as medidas de velocidades angulares, obteve- se qual seria o movimento descrito pelo VANT, ou seja, como os valores dos ângulos que descrevem sua atitude variam com o tempo. Para tal, utilizou-se o método de Runge-Kutta de 4ª ordem, o resultado pode ser visto na figura 6. Figura 6: Atitude parametrizada pelos ângulos de Euler obtida a partir das velocidades angulares escolhidas. Respectivamente em verde, azul e vermelho tem-se 휑, 휃 e 휙. Este último gráfico foi plotado apenas para fim de melhor visualização do movimento descrito pelo quadricóptero. O estudo apresentado aqui trabalha com a parametrização de atitude através de quatérnio de rotação. Sendo assim, segue o correspondente gráfico da variação dos parâmetros do real quatérnio de rotação que descreve o movimento:
  • 18. Figura 7: Variação dos parâmetros do real quatérnio de rotação q=[q0 q1 q2 q3]T. Respectivamente em verde, azul, vermelho e preto tem-se q0, q1, q2 e q3. A partir dos valores do real quatérnio de rotação correspondente ao movimento, determinou-se quais deveriam ser os reais vetores unitários que, a parte de um ruído gaussiano, correspondem as medidas vetoriais a serem obtidas pela câmera que representam as direções de landmarks postas no chão. Para obterem-se tais medidas, rotacionou-se dois vetores conhecidos, supostos serem as medidas iniciais da câmera para as landmarks, utilizando-se os valores do quatérnio do gráfico anterior. Os vetores iniciais escolhidos foram r1=[0, 5/13, -12/13]T e r2=[0, -5/13, -12/13]T (representações em relação a um sistema de eixos fixo ao solo coincidente com o sistema de eixos solidário ao VANT na situação inicial). No intuito de fornecer uma visão mais limpa deste último resultado, na figura 8 é fornecida uma visualização das primeiras 30 medidas dos vetores, ainda não acrescidas do respectivo ruído. Acrescentando-se o devido ruído a este ultimo resultado, obtemos assim dados coerentes que simulam bem velocidades angulares e medidas vetoriais obtidos respectivamente pelos girômetros e pela câmera a partir de um determinado movimento do quadricóptero. Estes dados podem agora ser utilizados como dados de entrada para a implementação do filtro de Kalman que irá estimar o quatérnio de rotação a partir destes dado.
  • 19. Figura 8: Primeiras 30 medidas dos vetores unitários que apontam para as landmarks em relação ao sistema de eixos fixo ao quadricóptero. Nesta imagem, para melhor visualização, está suprimido o ruído acrescido aos vetores, o que corresponde de maneira mais fidedigna às medidas vetoriais obtida pela câmera. Na figura 9 pode-se verificar a estimação obtida para o quatérnio de rotação correspondente ao caso real da figura 7. Percebem-se pouquíssimas diferenças. Na figura 10 é possível verificar-se em detalhe ambos os gráficos superpostos para outro caso. Nota-se que o filtro estima de maneira bastante razoável os parâmetros do quatérnio de rotação, mesmo depois de passado um grande período de tempo, e inúmeras medições já efetuadas. Figura 9: Variação dos parâmetros do quatérnio de rotação estimado pelo filtro de Kalman qe=[q0 q1 q2 q3]T. Respectivamente em verde, azul, vermelho e preto tem-se q0, q1, q2 e q3.
  • 20. Figura 10: Detalhe de comparação entre quatérnio real e quatérnio estimado pelo filtro de Kalman. Em linha continua encontram-se os valores reais, enquanto os pontos correspondem às estimativas obtidas pelo filtro. Figura 11: Índice de ortogonalidade e erro angular em função do tempo. A escala vertical do primeiro gráfico está multiplicada pelo fator .
  • 21. 6. OBTENÇÃO DOS DADOS EM TEMPO REAL POR COMUNIÇÃO SERIAL Concentram-se aqui os resultados posteriores à fase de formulação e simulação do filtro proposto. Inicialmente, pretendia-se reescrever todo o código implementado no MATLAB em linguagem C (o que foi feito posteriormente), e verificar diretamente seu funcionamento final rodando o algoritmo de maneira totalmente embarcada no quadricóptero. Porém, em vista dos inúmeros problemas que poderiam surgir nesta grande passagem do projeto, optou-se por um passo intermediário, que consiste na simulação com obtenção dos dados em tempo real. A rotina implementada anteriormente foi adaptada para utilizar os dados provenientes dos sensores, através de comunicação serial entre o Arduino e o MATLAB, correspondendo assim ao real movimento destes, e não de uma simulação. Houve a necessidade de abordar-se o problema da determinação dos vetores unitários que apontam da câmera para a landmark, explicitada na seção 4.3. Os demais valores que antes eram provenientes da simulação de uma dinâmica do quadricóptero, ou seja, as velocidades angulares, são diretamente lidas através do valor fornecido pelo girômetro, sendo apenas necessário fazer uma correção de unidade. O giroscópio presente no sensor GY-521 possui 4 configurações possíveis de ranges para se trabalhar, sendo a escolhida para este trabalho a que apresenta maior precisão das medidas, porém menor range. Esta decisão foi tomada levando-se em consideração que os testes preliminares seriam executados com movimentos de pequenas e médias amplitudes, pois o campo de visão da câmera escolhida apresenta um campo de visão de cerca de 30º apenas. Além disto, verificou-se experimentalmente que com o menor range, a distribuição das medidas obtidas com o sensor aproxima-se melhor de uma gaussiana, o que melhoraria o desempenho do filtro, dado que esta é uma das premissas de sua formulação. Esta verificação está indicada na figura 12. Figura 12: Dados de velocidade angular em relação ao mesmo eixo obtido com o giromêtro configurado para as duas opções extremas de range. Em (a) e (b), tem-se respectivamente as configurações que fornecem ranges com amplitudes de 2000º/s, e 250º/s. Os dados apresentados
  • 22. na figura encontram-se em rad/s. O pico de (a) encontra-se com cerca de 1600 amostras, e o pico de (b) com cerca de 500 amostras. Com isso, pode-se executar-se novamente a rotina do filtro, e plotar os valores das inovações de todas as componentes de ambos os vetores. Verificou-se que como esperado, estes gráficos possuem média nula, são descorrelacionados. Para cada um dos 6 gráficos, plotou-se também o sigma correspondente (raiz quadrada do respectivo elemento da diagonal principal da matriz de covariância da inovação). Figura 13: Em azul, valores da inovação de cada uma das componentes de ambos os vetores obtidos. E verde, respectivo valor de sigma, proveniente da matriz de covariância da inovação. Sendo de cima para baixo, as coordenadas de x, y e z, sendo os 3 gráficos iniciais correspondentes aos valores do vetor B1 (no código em MATLAB) e os últimos 3, correspondentes aos valores do vetor B2.
  • 23. 7. CONCLUSÕES O projeto obtido significativo progresso, obtendo bom resultados nas simulações, e nas primeiras fases de sua parte prática. Pode-se verificar até o momento que o filtro tem bom desempenho não só em simulações, mas também em na prática, em que o sistema de navegação apesar de ainda não ter sido testado em voo no VANT construído inicialmente, foi testado inúmeras vezes em uma plataforma similar, estimando a atitude da mesma de maneira acurada. Contudo, o teste em voo é sem dúvida uma fase crucial do projeto, e que se espera ser executado em breve a fim de alcançar-se o objetivo pré-estabelecido, isto é, desenvolver um sistema de navegação de baixo custo, porém de excelente qualidade. Ainda assim, a idealização do sistema, e a verificação de sua viabilidade, e performance já foram plenamente confirmadas neste projeto. Como extensão ao trabalho aqui realizado, sugere-se as seguintes atividades:  Alterar o firmware da CMUCam4 de modo a obter dados de maneira mais rápida, e assim não haver-se a necessidade de utilizar mais de uma câmera. No estágio atual em que se encontra o projeto, a alteração dos parâmetros de qual cor deve ser rastreada pela câmera faz com que sua taxa de amostragem caia de 30 fps para 4 fps, os motivos desta perda está relacionado com o modo de implementação das funções utilizadas no código deste sensor. A possibilidade de utilização de uma firmware costumizada já foi esclarecida e confirmada com o fabricante do mesmo; .  Realizar testes experimentais de bancada, tendo uma plataforma com determinação de atitude de modo independente (por exemplo: guimbals instrumentados com encoders), sendo assim, poder-se-ia comparar a atitude estimada pelo sistema de navegação desenvolvido com a fornecida pela plataforma. 8. AGRADECIMENTOS Agradeço ao Prof. Davi Antônio dos Santos por ter cedido seu tempo e paciência ao fornecer auxílio no desenvolvimento deste projeto, e pelo seu sempre constante incentivo. Ao Instituto Tecnológico de Aeronáutica pelo ensino de qualidade, sem o qual este trabalho não teria sido possível, e pelas inúmeras outras oportunidades oferecidas. Agradeço ainda em especial ao CNPq que financiou este projeto através do programa PIBIC. Este incentivo é de suma importância ao desenvolvimento da pesquisa científica no Brasil.
  • 24. 9. BIBLIOGRAFIA 1. GELB, A. Applied Optimal Estimation. Boston: M.I.T. Press, 1974. 2. BROWN, R.G.; HWANG, P.Y.C. Introduction to Random Signals and Applied Kalman Filtering. New York: John Wiley & Sons, 1997. 3. ANDERSON, B.D.O.; MOORE, J.B. Optimal Filtering. New Jersey: Prentice- Hall, 1979. 4. SHUSTER, M. D. A Survey of Attitude Representations. The Journal of the Astronautical Sciences, Vol. 41, No. 4. October-December 1993, pp.439-517. 5. SANTOS, D. A. Estimação de Atitude e Velocidade Angular de Satélites Utilizando Medidas do Campo Geomagnético e da Direção do Sol. Dissertação de Mestrado. Instituto Tecnológico de Aeronáutica, São José dos Campos, 2008. ANEXO 1: CÓDIGOS DO FILTRO DE KALMAN PARA ESTIMAÇÃO DE QUATÉRNIO DE ROTAÇÃO (MATLAB) A) TESTE_GERAL.m clc; clear; % parâmetros de tempo dt = 0.1; %intervalo de tempo entre medidas Tmax=100; %intervalo total de tempo em que são feitas medidas %% covariâncias usadas na simulação do sistema sigma_w = 0.005; %incerteza na medição da velocidades angulares sigma_b=0.01; %incerteza nas medidas das coordenadas dos vetores b1 e b2 Rb = sigma_b^2*eye(6); %covariância do ruído de medidas no sistema Sb Rw = sigma_w^2*eye(3); %covariância do ruído de medidas dos girômetros %% Covariância usadas no filtro R = Rb; Q = 0.005^2*eye(3); %% posições das landmarks r1= [0; 5/13; -12/13]; %representações em Sr das observações vetoriais r2= [0; -5/13; -12/13]; %% Condições iniciais do sistema P(:,:,1)=0.01*eye(4); %covariância do erro de estimação no instante 0 q(:,1) = [1 0 0 0]'; %% Condições iniciais do filtro qe(:,1) = [1 0 0 0]'; for k=1:Tmax/dt+1, %loop único para a simulação e o filtro de Kalman [q(:,k+1),wm(:,k), b1k1, b2k1]=simulacao(q(:,k),r1,r2,Rb,Rw,dt,k); [qe(:,k+1),P(:,:,k+1)] = KalmanFilter(qe(:,k),P(:,:,k),wm(:,k),Q,R,r1,r2,b1k1,b2k1,dt); % Calcula figuras de mérito % Ik - erro angular; Jk - índice de ortogonalidade [Ik(k+1),Jk(k+1)] = figuras_de_merito(q(:,k+1),qe(:,k+1)); end figure; hold on; plot(wm');title('Velocidade angular medida em rad/s');
  • 25. figure; plot(qe','b'); plot(q','r'); figure; plot(Jk); title('Índice de Ortogonalidade'); figure; plot(Ik); title('Erro Angular em graus'); B) simulacao.m function [qk1,wm, b1k1, b2k1] = simulacao(qk,r1,r2,Rb,Rw,dt,i) %% simulação da velocidade angular. wk = [0.1*sin(i*dt) 0.1*cos(i*dt) -0.1*sin(i*dt)*cos(i*dt)]'; %% propagação de atitude [qk1,fi]=propaga_q(qk,wk,dt); qk1 = (1/norm(qk1))*qk1; % atitude representada em DCM D = q2DCM(qk1); %% simulação das medidas wm = wk + sqrtm(Rw)*randn(3,1); % girômetros no instante k b=[D*r1;D*r2]+sqrtm(Rb)*randn(6,1);% medidas vet. no instante k+1 b1k1 = b(1:3); b2k1 = b(4:6); C) KalmanFilter.m function [qk1,Pk1] = KalmanFilter(qk,Pk,wk,Q,R,r1,r2,b1,b2,dt) % Inputs: % qk – estimativa do quaternio no instante k % Pk - convariância do erro estimado correspondente à qk % wk – medida de velocidade angular no instante k % dt – tempo de amostra % Q - covariância do ruído de processamento % R - covariância do ruído das medidas % r1, r2, b1, b2 – medidas vetoriais no instante k+1 % Outputs: % qk1 - quaternio estimado no instante k+1 % Pk1 – covariância do erro de estimação correspondente à qk1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %1a - Propagação do estado estimado [q_,fi] = propaga_q(qk,wk,dt); Csi_k = [-qk(2) -qk(3) -qk(4); qk(1) -qk(4) qk(3); qk(4) qk(1) -qk(2); -qk(3) qk(2) qk(1)]; Gama_k=dt/2*fi*Csi_k; Q_q_k=Gama_k*Q*Gama_k'; P_=fi*Pk*fi'+Q_q_k; %--------------------------------------------------------------------- %1b - Predição das medidas D_q_k= q2DCM(q_); b_estimado=[(D_q_k*r1)' (D_q_k*r2)']'; dDdq1 = [ 2*q_(1) 2*q_(4) -2*q_(3); -2*q_(4) 2*q_(1) 2*q_(2); 2*q_(3) -2*q_(2) 2*q_(1)]; dDdq2 = [ 2*q_(2) 2*q_(3) 2*q_(4); 2*q_(3) -2*q_(2) 2*q_(1); 2*q_(4) -2*q_(1) -2*q_(2)]; dDdq3 = [-2*q_(3) 2*q_(2) -2*q_(1); 2*q_(2) 2*q_(3) 2*q_(4); 2*q_(1) 2*q_(4) -2*q_(3)];
  • 26. dDdq4 = [-2*q_(4) 2*q_(1) 2*q_(2); -2*q_(1) -2*q_(4) 2*q_(3); 2*q_(2) 2*q_(3) 2*q_(4)]; H_1_q = [dDdq1*r1 dDdq2*r1 dDdq3*r1 dDdq4*r1]; H_2_q = [dDdq1*r2 dDdq2*r2 dDdq3*r2 dDdq4*r2]; H_q = [H_1_q; H_2_q]; P_b = H_q*P_*H_q' + R; %--------------------------------------------------------------------- %1c - Covariância cruzada P_b_q = P_*H_q'; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %2a - Ganho K = P_b_q*inv(P_b); %--------------------------------------------------------------------- %2b - Atualização da estimativa qk1 = q_ + K*( [b1' b2']' - b_estimado ); Pk1 = P_ - K*P_b*K'; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %3 - Normalização qk1 = (1/norm(qk1))*qk1; D) Figuras_de_merito.m function [Ik,Jk]=figuras_de_merito(q,qe) De = q2DCM(qe); % DCM estimada D = q2DCM(q); % DCM verdadeira Ik = 180/pi*abs(acos(0.5*(trace(De'*D) - 1))); %erro angular em graus Jk = trace((De'*De-eye(3))*(De'*De-eye(3))');%Índice de ortogonalidade E) propaga_q.m function [q2,fi] = propaga_q(q1,w1,dt) % cálculo da matriz de transição de estado W = 0.5*[0 -w1(1) -w1(2) -w1(3); w1(1) 0 w1(3) -w1(2); w1(2) -w1(3) 0 w1(1); w1(3) w1(2) -w1(1) 0]; n_w = norm(w1); fi=cos(n_w*dt/2)*eye(4)+1/n_w*sin(n_w*dt/2)*W; %matriz de transição de estado q2 = fi*q1; % propagacão do quatérnion F) q2DCM.m function D = q2DCM(q) D11 = 1-2*q(3)^2-2*q(4)^2; D12 = 2*(q(2)*q(3)+q(1)*q(4)); D13 = 2*(q(2)*q(4)-q(1)*q(3)); D21 = 2*(q(2)*q(3)-q(1)*q(4)); D22 = 1-2*q(2)^2-2*q(4)^2; D23 = 2*(q(4)*q(3)+q(1)*q(2)); D31 = 2*(q(2)*q(4)+q(1)*q(3)); D32 = 2*(q(4)*q(3)-q(1)*q(2)); D33 = 1-2*q(2)^2-2*q(3)^2; D = [ D11 D12 D13; D21 D22 D23; D31 D32 D33];
  • 27. ANEXO 2: CÓDIGOS DO FILTRO DE KALMAN PARA ESTIMAÇÃO DE QUATÉRNIO DE ROTAÇÃO (C - ARDUINO) A) arduino_matlab_serial.ino #include <CMUcam4.h> #include <CMUcom4.h> #define R_MIN_1 235 //amarelo #define R_MAX_1 255 #define G_MIN_1 235 #define G_MAX_1 255 #define B_MIN_1 160 #define B_MAX_1 190 #define R_MIN_2 235 //vermelho #define R_MAX_2 255 #define G_MIN_2 160 #define G_MAX_2 210 #define B_MIN_2 140 #define B_MAX_2 200 #define LED_BLINK 5 // 5 Hz #define WAIT_TIME 1000 // 5 seconds #define FILTRO 12 #define K1 683 #define pi 3.1416 #define LED_PIN 13 //----------------------------------------------------------- #include "Wire.h" #include "I2Cdev.h" #include "MPU6050.h" //----------------------------------------------------------- //########################################################### // Variáveis globais bool blinkState = false; CMUcam4 cam1(CMUCOM4_SERIAL1); CMUcam4 cam2(CMUCOM4_SERIAL2); CMUcam4_tracking_data_t data1, data2; MPU6050 accelgyro; int16_t ax, ay, az; int16_t gx, gy, gz; float a_x, a_y, a_z; float g_x, g_y, g_z; unsigned long T1, T2; //###########################################################
  • 28. //########################################################### void setup() { cam1.begin(); cam2.begin(); cam1.LEDOn(LED_BLINK); cam2.LEDOn(LED_BLINK); delay(WAIT_TIME); cam1.autoGainControl(false); cam2.autoGainControl(false); cam1.autoWhiteBalance(false); cam2.autoWhiteBalance(false); cam1.LEDOn(CMUCAM4_LED_ON); cam2.LEDOn(CMUCAM4_LED_ON); //----------------------------------------------------------- Wire.begin(); accelgyro.initialize(); //----------------------------------------------------------- Serial.begin(9600); } //########################################################### void loop(){ cam1.trackColor(R_MIN_1, R_MAX_1, G_MIN_1, G_MAX_1, B_MIN_1, B_MAX_1); cam2.trackColor(R_MIN_2, R_MAX_2, G_MIN_2, G_MAX_2, B_MIN_2, B_MAX_2); delay(WAIT_TIME); cam1.getTypeTDataPacket(&data1); cam2.getTypeTDataPacket(&data2); Serial.println(data1.mx); Serial.println(data1.my); Serial.println(data2.mx); Serial.println(data2.my); for(;;){ accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //medidas feitas juntas cam1.getTypeTDataPacket(&data1); cam2.getTypeTDataPacket(&data2); g_x=gx*pi/(131*180)-0.0244; // conversão para g_y=gy*pi/(131*180)-0.0155; // a unidade correta g_z=gz*pi/(131*180)+0.0069; // e calibração Serial.println(g_y,5); Serial.println(g_x,5); Serial.println(g_z,5); Serial.println(data1.mx); Serial.println(data1.my); Serial.println(data2.mx); Serial.println(data2.my); } }
  • 29. B) KF_C.ino #include <CMUcam4.h> #include <CMUcom4.h> #define R_MIN_1 75 #define R_MAX_1 255 #define G_MIN_1 0 #define G_MAX_1 125 #define B_MIN_1 0 #define B_MAX_1 100 #define R_MIN_2 75 #define R_MAX_2 255 #define G_MIN_2 0 #define G_MAX_2 125 #define B_MIN_2 0 #define B_MAX_2 100 #define LED_BLINK 5 // 5 Hz #define WAIT_TIME 5000 // 5 seconds #define FILTRO 12 #define K1 171 #define pi 3.1416 //----------------------------------------------------------- #include "Wire.h" #include "I2Cdev.h" #include "MPU6050.h" //########################################################### // Variáveis globais CMUcam4 cam1(CMUCOM4_SERIAL1); CMUcam4 cam2(CMUCOM4_SERIAL2); CMUcam4_tracking_data_t data1, data2; MPU6050 accelgyro; int16_t gx, gy, gz; double n_w, c, s, **C, **S, **fi, **q, **wm, dt=0.03, **W, **Csi_k, **Gama_k, **Q_q_k, **Q, **Pk, **D_q_k, **b_e, **b1_e, **b2_e, **r1, **r2, **dDdq1, **dDdq2, **dDdq3, **dDdq4, **H_1_q1, **H_1_q2, **H_1_q3, **H_1_q4, **H_2_q1, **H_2_q2, **H_2_q3, **H_2_q4, **H_q, **P_b, **R, **P_b_q, **K, **P_b_n_inv, **b; //########################################################### // Produto de Escalar por Matriz double** PdeEeM(double e, double** A, int a, int b ) { for(int i=0; i<a; i++) for(int j=0; j<b; j++) A[i][j]=e*A[i][j]; return A; } //###########################################################
  • 30. // Produto de matrizes double** PdeM(double** A, double** B, int a, int b, int c ) { double **P, aux; P=(double **) malloc (a * sizeof(double*)); for(int i=0; i<a; i++) P[i]=(double *) malloc (c * sizeof(double)); for(int i=0; i<a; i++) for(int j=0; j<c; j++){ aux=0; for(int k=0; k<b; k++) aux=aux+A[i][k]*B[k][j]; P[i][j]=aux; } return P; } //############################################################ // Transposta de Matriz double** TdeM(double** A, int a, int b) { double **B; B=(double **) malloc (b * sizeof(double*)); for(int i=0; i<b; i++) B[i]=(double *) malloc (a * sizeof(double)); for(int i=0; i<b; i++) for(int j=0; j<a; j++) B[i][j]=A[j][i]; return B; } //############################################################ // Soma de Matriz double** SdeM(double** A, double** B, int a, int b) { double **C; C=(double **) malloc (a * sizeof(double*)); for(int i=0; i<a; i++) C[i]=(double *) malloc (b * sizeof(double)); for(int i=0; i<a; i++) for(int j=0; j<b; j++) C[i][j]=B[i][j]+A[i][j]; return C; } //############################################################ // Subtração de Matriz double** SUdeM(double** A, double** B, int a, int b) { double **C; C=(double **) malloc (a * sizeof(double*)); for(int i=0; i<a; i++) C[i]=(double *) malloc (b * sizeof(double)); for(int i=0; i<a; i++) for(int j=0; j<b; j++) C[i][j]=A[i][j]-B[i][j]; return C; }
  • 31. //########################################################### void propaga_q (){ W[0][0] = 0; W[0][1] = -wm[0][0]/2; W[0][2] = -wm[1][0]/2; W[0][3] = -wm[2][0]/2; W[1][0] = wm[0][0]/2; W[1][1] = 0; W[1][2] = wm[2][0]/2; W[1][3] = -wm[1][0]/2; W[2][0] = wm[1][0]/2; W[2][1] = -wm[2][0]/2; W[2][2] = 0; W[2][3] = wm[0][0]/2; W[3][0] = wm[2][0]/2; W[3][1] = wm[1][0]/2; W[3][2] = -wm[0][0]/2; W[3][3] = 0; n_w = sqrt(wm[0][0]*wm[0][0] +wm[1][0]*wm[1][0] +wm[2][0]*wm[2][0]); c = cos(n_w*dt/2); s = sin(n_w*dt/2)/n_w; for(int i=0; i<4; i++) for(int j=0; j<4; j++) if(i==j){ S[i][j] = s; C[i][j] = c; } else{ S[i][j] = 0; C[i][j] = 0; } S = PdeM(S, W, 4, 4, 4); fi = SdeM(C, S, 4, 4); //matriz de transição de estado q = PdeM(fi, q, 4, 4, 1); // propagacão do quatérnion } //########################################################### void FCsi_k(){ Csi_k[0][0] = -q[1][0]; Csi_k[0][1] = -q[2][0]; Csi_k[0][2] = -q[3][0]; Csi_k[1][0] = q[0][0]; Csi_k[1][1] = -q[3][0]; Csi_k[1][2] = q[2][0]; Csi_k[2][0] = q[3][0]; Csi_k[2][1] = q[0][0]; Csi_k[2][2] = -q[1][0]; Csi_k[3][0] = -q[2][0]; Csi_k[3][1] = q[1][0]; Csi_k[3][2] = q[0][0]; }
  • 32. //########################################################## void q2DCM() { D_q_k[0][0] = 1-2*(q[2][0]*q[2][0]-q[3][0]*q[3][0]); D_q_k[0][1] = 2*(q[1][0]*q[2][0]+q[0][0]*q[3][0]); D_q_k[0][2] = 2*(q[1][0]*q[3][0]-q[0][0]*q[2][0]); D_q_k[1][0] = 2*(q[1][0]*q[2][0]-q[0][0]*q[3][0]); D_q_k[1][1] = 1-2*(q[1][0]*q[1][0]-q[3][0]*q[3][0]); D_q_k[1][2] = 2*(q[3][0]*q[2][0]+q[0][0]*q[1][0]); D_q_k[2][0] = 2*(q[1][0]*q[3][0]+q[0][0]*q[2][0]); D_q_k[2][1] = 2*(q[3][0]*q[2][0]-q[0][0]*q[1][0]); D_q_k[2][2] = 1-2*(q[1][0]*q[1][0]-q[2][0]*q[2][0]); } //########################################################## void dDdq() { dDdq1[0][0] = 2*q[0][0]; dDdq1[0][1] = 2*q[3][0]; dDdq1[0][2] = -2*q[2][0]; dDdq1[1][0] = -2*q[3][0]; dDdq1[1][1] = 2*q[0][0]; dDdq1[1][2] = 2*q[1][0]; dDdq1[2][0] = 2*q[2][0]; dDdq1[2][1] = -2*q[1][0]; dDdq1[2][2] = 2*q[0][0]; dDdq2[0][0] = 2*q[1][0]; dDdq2[0][1] = 2*q[2][0]; dDdq2[0][2] = 2*q[3][0]; dDdq2[1][0] = 2*q[2][0]; dDdq2[1][1] = -2*q[1][0]; dDdq2[1][2] = 2*q[0][0]; dDdq2[2][0] = 2*q[3][0]; dDdq2[2][1] = -2*q[0][0]; dDdq2[2][2] = -2*q[1][0]; dDdq3[0][0] = -2*q[2][0]; dDdq3[0][1] = 2*q[1][0]; dDdq3[0][2] = -2*q[0][0]; dDdq3[1][0] = 2*q[1][0]; dDdq3[1][1] = 2*q[2][0]; dDdq3[1][2] = 2*q[3][0]; dDdq3[2][0] = 2*q[0][0]; dDdq3[2][1] = 2*q[3][0]; dDdq3[2][2] = -2*q[2][0]; dDdq4[0][0] = -2*q[3][0]; dDdq4[0][1] = 2*q[0][0]; dDdq4[0][2] = 2*q[1][0]; dDdq4[1][0] = -2*q[0][0]; dDdq4[1][1] = -2*q[3][0]; dDdq4[1][2] = 2*q[2][0]; dDdq4[2][0] = 2*q[1][0]; dDdq4[2][1] = 2*q[2][0]; dDdq4[2][2] = 2*q[3][0]; }
  • 33. //########################################################## void FH_q() { H_1_q1 = PdeM(dDdq1, r1, 3, 3, 1); H_1_q2 = PdeM(dDdq2, r1, 3, 3, 1); H_1_q3 = PdeM(dDdq3, r1, 3, 3, 1); H_1_q4 = PdeM(dDdq4, r1, 3, 3, 1); H_2_q1 = PdeM(dDdq1, r2, 3, 3, 1); H_2_q2 = PdeM(dDdq2, r2, 3, 3, 1); H_2_q3 = PdeM(dDdq3, r2, 3, 3, 1); H_2_q4 = PdeM(dDdq4, r2, 3, 3, 1); H_q[0][0] = H_1_q1[0][0]; H_q[0][1] = H_1_q2[0][0]; H_q[0][2] = H_1_q3[0][0]; H_q[0][3] = H_1_q4[0][0]; H_q[1][0] = H_1_q1[1][0]; H_q[1][1] = H_1_q2[1][0]; H_q[1][2] = H_1_q3[1][0]; H_q[1][3] = H_1_q4[1][0]; H_q[2][0] = H_1_q1[2][0]; H_q[2][1] = H_1_q2[2][0]; H_q[2][2] = H_1_q3[2][0]; H_q[2][3] = H_1_q4[2][0]; H_q[3][0] = H_2_q1[0][0]; H_q[3][1] = H_2_q2[0][0]; H_q[3][2] = H_2_q3[0][0]; H_q[3][3] = H_2_q4[0][0]; H_q[4][0] = H_2_q1[1][0]; H_q[4][1] = H_2_q2[1][0]; H_q[4][2] = H_2_q3[1][0]; H_q[4][3] = H_2_q4[1][0]; H_q[5][0] = H_2_q1[2][0]; H_q[5][1] = H_2_q2[2][0]; H_q[5][2] = H_2_q3[2][0]; H_q[5][3] = H_2_q4[2][0]; } //########################################################## //Inversão de Matriz utilizando o método de Gauss-Jordam int inv(double **A, int n) { // A = matriz de entrada e também de saida int pivrow; int k,i,j; int* pivrows; pivrows=(int *) malloc (n * sizeof(int)); float tmp; for (k = 0; k < n; k++) { tmp = 0; for (i = k; i < n; i++) if (abs(A[i][k]) >= tmp) { tmp = abs(A[i][k]); pivrow = i; } if (A[pivrow][k] == 0.0f) return 0; //Inversão falha pois é matriz //singular
  • 34. if (pivrow != k) { for (j = 0; j < n; j++) { tmp = A[k][j]; A[k][j] = A[pivrow][j]; A[pivrow][j] = tmp; } } pivrows[k] = pivrow; tmp = 1.0f/A[k][k]; A[k][k] = 1.0f; for (j = 0; j < n; j++) A[k][j] = A[k][j]*tmp; for (i = 0; i < n; i++) { if (i != k) { tmp = A[i][k]; A[i][k] = 0.0f; for (j = 0; j < n; j++) { A[i][j] = A[i][j] - A[k][j]*tmp; } } } } for (k = n-1; k >= 0; k--) { if (pivrows[k] != k) { for (i = 0; i < n; i++) { tmp = A[i][k]; A[i][k] = A[i][pivrows[k]]; A[i][pivrows[k]] = tmp; } } } return 1; } //########################################################## void setup() { cam1.begin(); cam2.begin(); cam1.LEDOn(LED_BLINK); cam2.LEDOn(LED_BLINK); delay(WAIT_TIME); cam1.autoGainControl(false); cam2.autoGainControl(false); cam1.autoWhiteBalance(false); cam2.autoWhiteBalance(false); cam1.LEDOn(CMUCAM4_LED_ON); cam2.LEDOn(CMUCAM4_LED_ON); //---------------------------------------------------------- Wire.begin(); accelgyro.initialize(); //----------------------------------------------------------
  • 35. C = (double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) C[i]=(double *) malloc (4 * sizeof(double)); S = (double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) S[i]=(double *) malloc (4 * sizeof(double)); fi = (double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) fi[i]=(double *) malloc (4 * sizeof(double)); q=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) q[i]=(double *) malloc (sizeof(double)); wm=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) wm[i]=(double *) malloc (sizeof(double)); W=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) W[i]=(double *) malloc (4 * sizeof(double)); Csi_k=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) Csi_k[i]=(double *) malloc (3 * sizeof(double)); Gama_k=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) Gama_k[i]=(double *) malloc (3 * sizeof(double)); Q_q_k=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) Q_q_k[i]=(double *) malloc (4 * sizeof(double)); Q=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) Q[i]=(double *) malloc (3 * sizeof(double)); Pk=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) Pk[i]=(double *) malloc (4 * sizeof(double)); D_q_k=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) D_q_k[i]=(double *) malloc (3 * sizeof(double)); b_e=(double **) malloc (6 * sizeof(double*)); for(int i=0; i<6; i++) b_e[i]=(double *) malloc (6 * sizeof(double));
  • 36. b1_e=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) b1_e[i]=(double *) malloc (3 * sizeof(double)); b2_e=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) b2_e[i]=(double *) malloc (3 * sizeof(double)); r1=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) r1[i]=(double *) malloc (3 * sizeof(double)); r2=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) r2[i]=(double *) malloc (3 * sizeof(double)); dDdq1=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) dDdq1[i]=(double *) malloc (3 * sizeof(double)); dDdq2=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) dDdq2[i]=(double *) malloc (3 * sizeof(double)); dDdq3=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) dDdq3[i]=(double *) malloc (3 * sizeof(double)); dDdq4=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) dDdq4[i]=(double *) malloc (3 * sizeof(double)); H_1_q1=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) H_1_q1[i]=(double *) malloc (sizeof(double)); H_1_q2=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) H_1_q2[i]=(double *) malloc (sizeof(double)); H_1_q3=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) H_1_q3[i]=(double *) malloc (sizeof(double)); H_1_q4=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) H_1_q4[i]=(double *) malloc (sizeof(double)); H_2_q1=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) H_2_q1[i]=(double *) malloc (sizeof(double));
  • 37. H_2_q2=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) H_2_q2[i]=(double *) malloc (sizeof(double)); H_2_q3=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) H_2_q3[i]=(double *) malloc (sizeof(double)); H_2_q4=(double **) malloc (3 * sizeof(double*)); for(int i=0; i<3; i++) H_2_q4[i]=(double *) malloc (sizeof(double)); H_q=(double **) malloc (6 * sizeof(double*)); for(int i=0; i<6; i++) H_q[i]=(double *) malloc (4 * sizeof(double)); P_b=(double **) malloc (6 * sizeof(double*)); for(int i=0; i<6; i++) P_b[i]=(double *) malloc (6 * sizeof(double)); R=(double **) malloc (6 * sizeof(double*)); for(int i=0; i<6; i++) R[i]=(double *) malloc (6 * sizeof(double)); P_b_q=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) P_b_q[i]=(double *) malloc (6 * sizeof(double)); K=(double **) malloc (4 * sizeof(double*)); for(int i=0; i<4; i++) K[i]=(double *) malloc (6 * sizeof(double)); P_b_n_inv=(double **) malloc (6 * sizeof(double*)); for(int i=0; i<6; i++) P_b_n_inv[i]=(double *)malloc(6*sizeof(double)); b=(double **) malloc (6 * sizeof(double*)); for(int i=0; i<6; i++) b[i]=(double *) malloc (sizeof(double)); for(int i=0; i<3; i++) for(int j=0; j<3; j++) if(i==j) Q[i][j] = 0.000025; else Q[i][j] = 0; for(int i=0; i<4; i++) for(int j=0; j<4; j++) if(i==j) Pk[i][j] = 0.01; else Pk[i][j] = 0;
  • 38. for(int i=0; i<6; i++) for(int j=0; j<6; j++) if(i==j) R[i][j] = 0.0001; else R[i][j] = 0; q[0][0]=1; q[1][0]=0; q[2][0]=0; q[3][0]=0; } //########################################################## void loop() { cam1.trackColor(R_MIN_1, R_MAX_1, G_MIN_1, G_MAX_1, B_MIN_1, B_MAX_1); cam2.trackColor(R_MIN_2, R_MAX_2, G_MIN_2, G_MAX_2, B_MIN_2, B_MAX_2); delay(WAIT_TIME); cam1.getTypeTDataPacket(&data1); cam2.getTypeTDataPacket(&data2); r1[0][0] = sin(atan((data1.mx-80)/K1)); r1[1][0] = sin(atan((data1.my-60)/K1)); r1[2][0] = sqrt(1-r1[0][0]*r1[0][0]-r1[1][0]*r1[1][0]); r2[0][0] = sin(atan((data2.mx-80)/K1)); r2[1][0] = sin(atan((data2.my-60)/K1)); r2[2][0] = sqrt(1-r2[0][0]*r2[0][0]-r2[1][0]*r2[1][0]); for(;;) { accelgyro.getRotation(&gx, &gy, &gz); //medidas feitas juntas cam1.getTypeTDataPacket(&data1); cam2.getTypeTDataPacket(&data2); wm[0][0]=gx*pi/(16.4*180); wm[1][0]=gy*pi/(16.4*180); wm[2][0]=gz*pi/(16.4*180); //---------------------------------------------------------- //1a - Propagação do estado estimado FCsi_k(); propaga_q(); Gama_k = PdeEeM((dt/2),PdeM(fi,Csi_k,4,4,3),4,3); Q_q_k = PdeM(Gama_k,PdeM(Q,TdeM(Gama_k,4,3), 3,3,4),4,3,4); Pk = SdeM(PdeM(PdeM(fi,Pk,4,4,4), TdeM(fi,4,4),4,4,4),Q_q_k,4,4); //---------------------------------------------------------- //1b - Predição das medidas q2DCM(); b1_e = PdeM(D_q_k, r1, 3, 3, 1); b2_e = PdeM(D_q_k, r2, 3, 3, 1);
  • 39. b_e[0][0] = b1_e[0][0]; b_e[1][0] = b1_e[1][0]; b_e[2][0] = b1_e[2][0]; b_e[3][0] = b2_e[0][0]; b_e[4][0] = b2_e[1][0]; b_e[5][0] = b2_e[2][0]; dDdq(); FH_q(); P_b = SdeM(PdeM(PdeM(H_q,Pk,6,4,4), TdeM(H_q,6,4),6,4,6),R,6,6); //---------------------------------------------------------- //1c - Covariância cruzada P_b_q = PdeM(Pk, TdeM(H_q, 6, 4), 4, 4, 6); //---------------------------------------------------------- //2a - Ganho for(int i=0; i<6; i++) for(int k=0; k<6; k++) P_b_n_inv[i][k]=P_b[i][k]; inv(P_b, 6); //retorna 0 em falha, e 1 em sucesso K = PdeM(P_b_q, P_b, 4, 6, 6); //---------------------------------------------------------- //2b - Atualização da estimativa b[0][0] = sin(atan((data1.mx-80)/K1)); b[1][0] = sin(atan((data1.my-60)/K1)); b[2][0] = sqrt(1-b[0][0]*b[0][0]-b[1][0]*b[1][0]); b[3][0] = sin(atan((data2.mx-80)/K1)); b[4][0] = sin(atan((data2.my-60)/K1)); b[5][0] = sqrt(1-b[3][0]*b[3][0]-b[4][0]*b[4][0]); q = SdeM(q,PdeM(K,SUdeM(b,b_e,6,1),4,6,1),4,1); Pk = SUdeM(Pk,PdeM(PdeM(K,P_b_n_inv,4,6,6), TdeM(K,4,6),4,6,4),4,4); //########################################################## //3 - Normalização q = PdeEeM((1/sqrt( q[0][0]*q[0][0] +q[1][0]*q[1][0] +q[2][0]*q[2][0] +q[3][0]*q[3][0])),q,4,1); } }