índiceitem superior

item anteriorpróximo item

 

2.1 - Matrizes

 

Considerando que a simulação e o controle de atitude são equacionados em termos de matrizes e vetores, criou-se um conjunto de estruturas que facilitam a codificação dos programas. No contexto utilizado aqui as matrizes são todas de dimensão 3, ou seja, são matrizes quadradas 3 x 3. Os vetores são igualmente tridimensionais, ou hexa-dimensionais enquanto que quatérnions são quadridimensionais. As estruturas criadas foram: matrix3, vector3, vector6 e quaternion. Utilizou-se o conceito de vetrizes, que combina as propriedades de matrizes com a de vetores. Um vetor é uma estrutura composta por 3 valores reais (precisão dupla, ou double), na forma:

 

 

O vetor de 6 posições é composto por dois vetores tridimensionais:

 

,

 

Uma matriz a é formada por 3 vetores linha, a._1,  a._2 e a._3, e portanto tem a forma:

 

,

 

Finalmente, o quatérnion tem a forma:

 

.

 

Nota-se que a matriz poderia ser definida como sendo um vetor de 9 componentes. A diferença serve para lembrar que o existem produtos de matrizes por vetores, mas não existem produtos de vetores de 6 dimensões por outro de 3 dimensões, por exemplo. Em outras palavras, no produto de uma matriz a por um vetor linha b, deve-se sempre lembrar que, de fato, está a se fazer um produto na forma a bT, onde o sobrescritoT” indica a transposição do vetor. O código para esta multiplicação é simplesmente a*b, sem a necessidade de transpor o vetor.

 

Uma variável matrix3 é composta por 3 vetores linha (denominados _1, _2 e _3) e estes por 3 elementos cada, de tal forma que os nove elementos da matriz podem ser endereçados na seqüência ._1._1, ._1._2, ._1._3, ._2._1, ._2._2, ._2._3, ._3._1, ._3._2, ._3._3. O vetor tridimensional é composto por 3 elementos: ._1, ._2, ._3; o vetor de seis componentes é composto pelos elementos: ._1._1, ._1._2, ._1._3, ._2._1, ._2._2, ._2._3 e, finalmente, o quatérnion é composto por 4 elementos: ._1, ._2, ._3, ._4. Os elementos destas estruturas são todos do tipo double. Para criar variáveis com estas estruturas, usa-se:

 

#include “matrices.h”

            matrix3 mat_rot, mat_rot1, mat_rot2;

            vector3 vec_pos;

            vector6 state_vector;

            quaternion q;

...

 

Os elementos individuais de cada variável podem ser acessados por meio do ponto seguido do nome do elemento, como, por exemplo, mat_rot._21, vec_pos._3 ou q._1. A atribuição de valor para cada um deles pode ser facilmente feita por meio de listas como

 

mat_rot = {0.2, 0, -1, 0.6, 1, -2, 2, 1.5, 3};

vec_pos = {1543.3, 764.0, -2414.8};

 

ou então pelo acesso a cada elemento por meio de seus índices:

 

      vec_pos._1 = mat_rot._1._3;

      vec_pos._2 = mat_rot._2._3;

      vec_pos._3 = mat_rot._3._3;

      q._4 = 1;

 

Foram implementadas (sobrepostas) neste pacote as principais operações matemáticas entre matrizes e vetores, para permitir a representação simbólica destas operações. Assim, um produto de duas matrizes é indicado por:

 

mat_rot = mat_rot1 * mat_rot2;

 

Qualquer composição envolvendo operações de adição, subtração e multiplicação é igualmente válida:

 

mat_rot = (mat_rot1 + mat_rot2) * mat_rot3;

 

As seguintes operações são válidas, e verificadas durante a compilação, isto é, caso seja detectado uma operação não definida previamente, o compilador emite um alerta:

 

·        Produto entre duas matrizes: (matrix3) = (matrix3) * (matrix3)

·        Produto de um escalar por uma matriz:  (matrix3) = (double) * (matrix3)

·        Produto de um inteiro por uma matriz:  (matrix3) = (int) * (matrix3)

·        Produto de uma matriz por um escalar: (matrix3) = (matrix3) * (double)

·        Produto de uma matriz por um inteiro: (matrix3) = (matrix3) * (int)

·        Divisão de uma matriz por um escalar: (matrix3) = (matrix3) / (double)

·        Divisão de uma matriz por um inteiro: (matrix3) = (matrix3) / (int)

·        Soma de matrizes: (matrix3) = (matrix3) + (matrix3)

·        Diferença entre matrizes: (matrix3) = (matrix3) - (matrix3)

·        Produto escalar entre vetores: (double) = (vector3) * (vector3)

·        Produto de uma matriz por um vetor: (vector3) = (matrix3) * (vector3)

·        Soma de vetores: (vector3) = (vector3) + (vector3)

·        Diferença entre vetores: (vector3) = (vector3) - (vector3)

·        Produto vetorial: (vector3) = (vector3) ^ (vector3)

·        Produto de um escalar por um vetor: (vector3) = (double) * (vector3)

·        Produto de um inteiro por um vetor: (vector3) = (int) * (vector3)

·        Produto de um vetor por um escalar: (vector3) = (vector3) * (double)

·        Produto de um vetor por um inteiro: (vector3) = (vector3) * (int)

·        Divisão de um vetor por um escalar: (vector3) = (vector3) / (double)

·        Divisão de um vetor por um inteiro: (vector3) = (vector3) / (int)

·        Produto de uma matriz por um vector6: (vector6) = (matrix3) * (vector6)

·        Soma de vetores duplos: (vector6) = (vector6) + (vector6)

·        Diferença entre vetores duplos: (vector6) = (vector6) - (vector6)

·        Produto de um escalar por um vetor6: (vector6) = (double) * (vector6)

·        Produto de um inteiro por um vetor duplo: (vector6) = (int) * (vector6)

·        Produto de um vetor6 por um escalar: (vector6) = (vector6) * (double)

·        Produto de um vetor duplo por um inteiro: (vector6) = (vector6) * (int)

·        Divisão de um vetor duplo por um escalar: (vector6) = (vector6) / (double)

·        Divisão de um vetor duplo por um inteiro: (vector6) = (vector6) / (int)

·        Produto entre escalar e quatérnion (quaternion) = (double) * (quaternion)

·        Produto entre inteiro e quatérnion (quaternion) = (int) * (quaternion)

·        Produto entre quatérnion e escalar (quaternion) = (quaternion) * (double)

·        Produto entre quatérnion e inteiro (quaternion) = (quaternion) * (int)

·        Divisão entre quatérnion e escalar (quaternion) = (quaternion) / (double)

·        Divisão entre quatérnion e inteiro (quaternion) = (quaternion) / (int)

·        Produto entre quatérnions (quaternion) = (quaternion) * (quaternion)

 

O produto escalar entre vetores é indicado pelo sinal usual do produto “*”, enquanto que o produto vetorial é indicado pelo circunflexo “^”. Veja que o resultado pode diferir em virtude da ordem com que as operações são realizadas, como no caso:

 

(matrix3) = (matrix3) * ((vector3) * (vector3))

(double) = (matrix3) * (vector3) * (vector3)

 

Em virtude da sobreposição de operações e dos símbolos de operações, não se pode garantir a ordem com que elas são realizadas numa linha. Notou-se que pelo menos no produto vetorial a ordem de precedência do produto não é obedecida, isto é, num cálculo como este:

 

dwdt = a_ang ^ w_vel - wheel_torque;

 

a subtração tem precedência sobre o produto! Portanto, adverte-se manter um controle sobre a ordem das operações, para evitar maiores problemas na depuração, e sinalizar por meio de parêntesis a ordem correta:

 

dwdt = (a_ang ^ w_vel) - wheel_torque;

 

O produto de uma matriz por um vetor de 6 componentes é realizado multiplicando-se a matriz pelos dois vetores que compõem o vetor6.

 

O produto de quatérnions, por sua vez, permite efetuar a rotação de uma atitude dado o quatérnion que relaciona ambas. Maiores detalhes podem ser encontrados no Apêndice D de Wertz (Wertz, 1978). A estrutura quatérnion admite que os três primeiros valores (q._1, q._2 e q._3) constituem o vetor nas direções i, j e k, respectivamente, enquanto que a quarta componente (q._4) armazena o valor escalar:

 

           

 

As definições e protótipos para estas variáveis encontram-se no cabeçalho matrices.h. Um programa que utilize estas estruturas deverá ser unido (link) ao arquivo matrices.lib, que contém os operadores definidos em matrices.c. As matrizes são criadas pela estrutura matrix3, os vetores pela estrutura vector3 e os quatérnions pela estrutura quaternion. O seguinte programa foi utilizado para testar as operações entre matrizes e vetores:

 

#include <stdio.h>

#include "matrices.h"

void main ()

{

      double a = 2;

            matrix3 mat1 = {9, 8, 7, 6, 5, 4, 3, 2, 1};

      matrix3 mat2 = {-1, 4, 2, -5, -3, 0, 3, 2, 4};

      matrix3 mat3 = {5, -2, 4, -1, -3, 0, 2, 9, 1};

      vector3 vec1 = {1, 2, 3}, vec2 = {-4, -3, 2}, vec3;

 

//    mat3 = 2 * mat1 * mat3 * mat2 ;// produto de matrizes

//    mat3 = mat1 * mat3 * 2 * mat2 ;// produto de escalar por matriz

//    mat3 = mat1 * mat3 * mat2 * 2 ;// produto de matriz por escalar

//    mat3 = mat1 + mat3 + mat2 ;  // soma de matrizes

//    mat3 = mat1 + mat3 - mat2 ;  // soma e subtração de matrizes

//    mat3 = (mat1 + mat3) * mat2 ; // soma e produto

 

//    mat3 = vec1 * vec2 * mat2 ;  // produto escalar

//    mat3 = mat2 * (vec1 * vec2) ; // produto escalar

//    a = mat2 * vec1 * vec2;      // produto de matriz por vetor

//    vec3 = vec1 + vec2;          // soma de vetores

//    vec3 = vec1 - vec2;          // diferença de vetores

//    vec3 = vec1 ^ vec2;          // produto vetorial

//    vec3 = vec2 ^ vec1;          // produto vetorial

//    vec3 = a * vec1;             // produto de escalar por vetor

//    vec3 = vec1 * a;             // produto de escalar por vetor

 

      printf(" Matriz \n");

      printf(" %10.4f  %10.4f  %10.4f \n", mat3._11, mat3._12, mat3._13);

      printf(" %10.4f  %10.4f  %10.4f \n", mat3._21, mat3._22, mat3._23);

      printf(" %10.4f  %10.4f  %10.4f \n", mat3._31, mat3._32, mat3._33);

      printf(" Vetor \n");

      printf(" %10.4f  %10.4f  %10.4f \n", vec3._1, vec3._2, vec3._3);

      printf(" Escalar \n");

      printf(" %10.4f  \n", a);

 

      return;

}

 

Adicionalmente, foram acrescentadas funções que visam oferecer outros recursos na manipulação de matrizes. Entre elas encontram-se funções para inverter ou transpor uma matriz, normalizar um vetor ou um quatérnion, funções de atribuição de valores,  etc. Estas funções são descritas a seguir:

 

·         quaternion conjugate (quaternion quat);

·         matrix3 identity (double escal);

·         matrix3 inverse (matrix3 matin);

·         double modulus (vector3 vecin);

·         matrix3 skew_simetric (vector3 win);

·         matrix3 transpose (matrix3 mat);

·         quaternion unity_quaternion (quaternion quat);

·         vector3 unity_vector (vector3 vecin);

·         vector3 vec3_def (double vx, double vy, double vz);

·         vector6 vec6_def (double vx, double vy, double vz, double wx, double wy, double wz);

·         quaternion quat_def (double q1, double q2, double q3, double q4);

·         matrix3 mat3_def (double a11, double a12, double a13, double a21, double a22, double a23, double a31, double a32, double a33);