UNIVERSIDAD AUTONOMA METROPOLITANA …148.206.53.84/tesiuami/UAM1472.pdf · Divergencia en el...

81
, UNIVERSIDAD AUTONOMA METROPOLITANA UNIDAD IZTAPALAPA I CARRERA: LIC. EN COMPUTACI~N MATERIA: PROYECTO DE INVESTIGACI~N 11 TÍTULO: " APLICACIONES DEL FILTRO DE KALMAN " ALUMNO: RAúL CRUZ QUIRASCO ASES DR. HÉCTOR PÉREZ MEANA TIMESTRE LECTIVO 97-0 28/11/1997

Transcript of UNIVERSIDAD AUTONOMA METROPOLITANA …148.206.53.84/tesiuami/UAM1472.pdf · Divergencia en el...

, UNIVERSIDAD AUTONOMA METROPOLITANA

UNIDAD IZTAPALAPA I CARRERA:

LIC. EN COMPUTACI~N

MATERIA:

PROYECTO DE INVESTIGACI~N 11

TÍTULO:

" APLICACIONES DEL FILTRO DE KALMAN "

ALUMNO:

RAúL CRUZ QUIRASCO

ASES

DR. HÉCTOR PÉREZ MEANA

TIMESTRE LECTIVO

97-0

28/11/1997

CAPÍTULO l. PRINCIPIOS BÁSICOS.

Principios básicos de filtros adaptivos

Filtros adaptivos

La necesidad de un filtro adaptivo

Formulación del ecualizador adaptivo

Aplicación de un algoritmo recursivo con mínimos cuadrados para un ecualizador adaptivo

El algoritmo fuerte de kalman

Simulación de los resultados

Conclusiones

CAPITULO 11. APLICACIONES DE FILTROS ADAPTIVOS

El combinador lineal de impulso-respuesta-finito.

Ecualización de un canal usando un filtro de kalman para la

transmisión rápida de datos.

CAPITULO 111. DIVERGENCIA

Divergencia en el filtro de kalman

Causas de la divergencia

Control de divergencia

Ejemplo ilustrativo

CAPITULO IV. EL FILTRO ADAPTIVO DE KALMAN Código fuente del filtro adaptivo de kalman

2

3

9

IO

14

16

19

20

24

26

29

29

30

31

35

1

CAPíTULO I

Este trabajo presenta una breve explicación del funcionamiento de los filtros adaptivos. Uno de los principales y más importante de estos filtros es el de Kalman. Gracias a sus investigaciones, los filtros actuales son más precisos en la eliminación de ruido y generación de señales puras.

Para poder explicar de manera precisa y clara los funcionamientos de estos filtros se requiere tener conocimientos de términos matemáticos avanzados, como son el manejos de matrices, manejo de fórmulas Gaussianas, Integrales, y muchos más.

Se muestra de manera esquemática las funciones y desarrollo de estos filtros por medio de algoritmos computacionales, y así poder transferir su proceso de manejo a lenguajes de programación avanzado, como Lenguaje "C", Pascal entre otros.

En el capítulo IV de este documento se anexa el código fuente de un filtro adaptivo de Kalman, este fue creado por el grupo de alumnos que desarrollaron este reporte. El lenguaje usado fue "C" y su compilación se hace por medio de archivos "Include", ya que sólo se tiene un archivo *.c

PRINCIPIOS BASICOS DE FILTROS ADAPTIVOS.

En la estructura básica de un filtro adaptivo mostrada en la figura. La serial de entrada es filtrada para producir una salida la cual típicamente es llevada a otro procesamiento subsecuente. La salida de este filtro es también observada por un circuito el cual valora la calidad de la salida. Esta medida de calidad, o alguna función de esta, es pasada al circuito que la utiliza para modificar los parámetros del filtro y

con esto mejorar la salida. En principio, este ciclo de procesamiento continua operando hasta que los parámetros del filtro son ajustados para que la salida del filtro sea lo mejor posible. También en principio, si las características de la serial de entrada o la calidad de mejoramiento cambian con el tiempo. Entonces este ciclo mejoramiento/ajuste puede reajustar los parámetros del filtro hasta que la nueva salida optima es obtenida.

2

Los bloques funcionales en la figura son bastante generales y pueden ser seleccionados de diferentes formas para resolver problemas prácticos. El filtro, por ejemplo, puede ser implementado de forma analógica o digital y puede tener "un canal de retardo", polo cero o estructura enrejada.

Los parámetros disponibles para ajustar pudieran ser la secuencia de valores impulso- respuesta o funciones más complicadas de las frecuencias de respuesta del filtro . Similarmente, el circuito con el cual se valora la calidad de la salida del filtro puede tomar diferentes formas dependiendo de la aplicación del filtro adaptivo. La forma en la que la valoración de la calidad de salida es convertida en parámetros modificados (ajustados).

Las variaciones en la estructura del filtro, el mecanismo de valoración de calidad y la actualización adaptiva son comúnmente usados para catalogar las características de conducta, y así la aplicabilidad de varios filtros adaptivos.

FILTROS ADAPTIVOS

Los filtros adaptivos tienen una relación estrecha con los ecualizadores. En la practica muchos son de hecho, ecualizadores.

Los filtros adaptivos son utilizados (como ecualizadores), para filtrar ruidos de

banda estrecha y componentes senoidales discretos.

La discusión de filtros adaptivos se hará considerando un filtro general con entradas múltiples. Tal filtro puede también ser usado para nulificar la dirección de aplicaciones de antena y para patrones de emisión. En este caso las entradas pueden llegar de múltiples antenas. En el sentido más convencional para un filtro transversal, las entradas múltiples son simplemente versiones retrasadas de una serial de entrada simple 0.e. las entradas se originan de un cambio de registro).

Comencemos por considerar un diagrama de bloques donde cada entrada X I ,

X2, X3, etc., son originadas de antenas separadas, micrófonos u otro sensor. el término dj es un segmento de la serial deseada. Las seriales de entrada, Xj, contienen la serial deseada más el ruido.

3

En algunas aplicaciones, una muestra de la serial deseada puede no ser habilitada, pero una muestra del ruido puede ser removida.

Podemos utilizar una configuaración donde se tenga la serial más el ruido, n l es el flujo de ruido correlacionado en algún camino con no, y1 es la salida del filtro adaptivo, y Ej es la serial de error minimizada.

Para valores reales de X, sea la serial de entrada el vector:

Wj = W3Q) I w2m

(8.93)

La j-esima senal de salida es

Esta expresión puede ser más consistente si la escribimos en forma de matriz:

y(j> = W'(j>x(j> =X'(j>w(j> (8.95)

Para un caso donde n = 3 tenemos:

4

o bien

y ( j ) = W~(j )x~( j )+W2( j )x2 ( j )+w3( j )x~( j )

Sea la senal deseada de salida d(j). Entonces la serial de error es:

El cuadrado de la senal de error es:

Realizando las multiplicaciones tenemos:

Deseamos encontrar el error cuadrático medio el cual es:

Aplicando el operador de esperanza a la ecuación (8.961, tenemos:

E L 2 (j)]= E[d2(j) - 2 mT (d, X)W(i) + W'(j) (X, X)W(j)] (8.99)

5

Note que los valores de W no son estadísticos y son constantes en la esperanza. Asimismo, definimos

la cual es la correlación cruzada entre las senales de entrada y la respuesta deseada.

Para un proceso de tiempo estacionario, tenemos:

Una expresión similar para cada una de las entradas

Definimos también la matriz de correlación cruzada de las variables de

entrada como:

(8.102)

Puesto que Error[E"cuad"(j)l es una función de segundo orden de la conexión de pesos, podemos visualizarlos como una superficie en forma de tazón (¡.e. Error[E"cuad"(j)l es una función parabólica de conexión de pesos). El proceso

6

adaptivo es entonces la tarea de continuidad observada desde la parte superior del tazón. El método de pendiente descendente usa el vector gradiente para determinar la dirección en la cual se mueve.

Ahora tenemos:

"delta"[E"cuad"(j)l = -2"theta"(d,X) + 2"theta"(x,X) WCj) (8.104)

Derivando esta ecuación, notamos que el primer término, Error[d"cuad"(j)l, es una constante con respecto a W. Hasta entonces la derivada es cero. El segundo término es obtenido multiplicando fuera de la expresión y diferenciando con respecto a W

para cada fila. El último término también puede ser obtenido por la multiplicación de las expresiones y diferenciándolas. Aquí podemos notar que "theta" sub(iK) (j) =

"theta" sub(Ki) (j).

Ahora, para encontrar el vector de peso óptimo, W sub(LMS1, inicializamos el gradiente a cero. Esta condición es satisfecha si:

"theta"(d,X) = "theta"(X,X) W sub(LMS1 (8.105)

Solucionando para W sub(LMS1, tenemos

W SUb(LMS) = "theta"I-Il(X,X) "theta"(d,X) (8.106)

Esta es la ecuación de Weiner Hopf en forma de matriz. El error mínimo cuadrado es obtenido sustituyendo la ecuación (8.106) en la ecuación (8..99):

Error[E"cuad"(j)l sub(MIN) = Error[d"cuad"(j)l - - W[transl Sub(LMS) "theta"(d,X) (8.107)

La ecuación 8.106 puede resolverse directamente después de calcular la correlación de matrices. Usando este método, los coeficientes pueden determinarse rápidamente. Este procedimiento es llamado el algoritmo LMS.

Aquí, adaptamos los coeficientes un paso a la vez usando la ecuación:

7

donde Wcj) = vector de pesos antes de la adaptación WCj + 1) = vector de pesos después de la adaptación

"mu" = constante escalar que controla la razón de convergencia

"grada"[E"-2"(j)I = estimación del vector gradiente con respecto aw

La estimación del gradiente está hecha para asumir que el gradiente del valor de la esperanza es igual al gradiente de su mismo error. Así,

"grada"[E"-2"(j)I "aproximado" "grada"[E"2"(j)l

Diferenciando

"grada"[E"2"(j)l = 2E(j) "grada"[E(j)l (8.110)

El error fue previamente definido (ecuación 8.97) como

Entonces el gradiente es:

"grada"[E(j)l = -X(j) (8.111)

puesto que d(j) no es una función de WCj). Sustituyendo esta en la ecuación (8.110)

"grada"[E"2"(j)l = -2E(j) XCj) (8.1 12)

Finalmente, sustituimos la ecuación 8.112 en la ecuación 8.108

8

EI término ECj)XCj) es simplemente la serial de error multiplicada por cada entrada. Para el ejemplo considerado previamente, tenemos:

Por Io tanto:

W1 Cj + 1) = WlCj) + 2"mu"ECj) XlCj)

W2(j +I) = W2Cj) + 2"mu"ECj) X2Cj)

W3Cj +I) = W3(j) + 2"mU"E(j) X3Cj)

El cual es el algoritmo de Widrow-Hoff.

LA NECESIDAD DE UN FILTRO ADAPTIVO

un filtro adaptivo es definido de manera muy general como un filtro cuyas características pueden ser modificadas para alcanzar algún fin u objetivo y

generalmente es adaptado para llevar a cabo esta modificación automáticamente, sin la necesidad de una sustancial intervención del usuario (mientras no se requiera necesariamente). También usualmente se asume que la escala de tiempo de la modificación es muy lenta comparado con el ancho de banda de la serial que se esta filtrando. Implícitamente con esta suposición es que el disenador de un sistema puede en realidad usar un filtro adaptivo de tiempo invariable, solo si se conoce bastante acerca de la serial de entrada para disenar el filtro. Esta falta de conocimiento puede brotar desde una incertidumbre acerca de las características de la serial cuando el filtro es encendido; o porque las características de la serial de entrada pueden cambiar lentamente durante la operación de "filtración" . A falta de este conocimiento el disenador opta por un filtro "adaptivo" el cual puede "aprender" las características de la serial cuando se activa y que después pueden seguir cambios lentos en esas características.

9

FORMULACI~N DEL ECUALIZADOR ADAPTIVO

Durante el periodo de enseñanza inicial del ecualizador, una sucesión de símbolos d(l), d(2),...,d(n), conocida como el arreglo del algoritmo del ecualizador es transmitida por un canal, dando como resultado una secuencia de salidas ecualizadas y(l), ~(21, .... . ..y(n). En un tiempo n , el ecualizador tiene N entradas almacenadas, esto Io denotamos por el vector

Indicaríamos la dimensionalidad de los vectores y matrices por sus subscripciones. La ausencia de estos indicaría una sola dimensión; por ejemplo; y(n) es un escalar,

x,(n) es un vector de dimensión N, A,(n) es una matriz con N renglones y p

columnas. La transpuesta de la matriz se sobrescribe como T.

EI ecualizador conecta los coeficientes a un tiempo n que son representados

por el vector C, ( n - 1) y con salidas C, (n - l )"xN (n) , que difiere de la salida ideal

d(n) por un error e(n)

Esta fórmula de la salida del ecualizador y su error difiere de distintos tipos de ecualizador. Los más obvios de estos ecualizadores son los lineales transversales con N conectores, por tal motivo {y(n)} es el canal de salida muestra para los símbolos de rotación. La estructura del ecualizador lineal es también relevante a reserva del algoritmo de detección de Viterbi, en tal caso, d(n) en (2) es reemplazado por la combinación lineal de los datos recientes. Una variación de la estructura del ecualizador lineal, son los canales de salida muestra a tiempo p de los símbolos de rotación I/T, el vector se convierte en

10

- -

(n - l )T+-

(n - l )T+-

P

P

(Ver referencia I111).

En caso de una decidir retroalimentar el ecualizador con N , delante y N ,

retroalimentado por las conexiones xN ( n ) esto queda como

donde N = N , + N , , {y(n)} son las muestras del canal de salida y {d(n)} es la decisión

previa de los datos.

una aplicación a esta relación es cuando {d(n-l), ......., d(n-N, I} aparece en (IC),

N , es el último datos que viene de un local, interfiriendo en la transmisión durante

2 caminos de comunicación simultáneamente, 1121.

11

En este y en otras muchas estimaciones y aplicaciones predictivas, las salidas

de los vectores xN (n) son tales que xN (n + 1) son obtenidas de xN (n) para satisfacer

estos componentes, introduciendo el viejo componente p. Por ejemplo para p=2

nuevos elementos y(n), d(n) entra la decisión de retroalimentar el ecualizador a un tiempo n +I, mientras lo permitan los elementos y(n-N,) y d(n-N2 1. Esta propiedad

es crucial en el algoritmo "fuerte" de Kalman .

Para unificar la subsecuente notación, definiremos un vector p-dimensional

$ ( n ) que satisface a nuevos elementos p y un vector p,(n)especificando a p y

eliminando los elementos viejos a un tiempo n + 1; por ejemplo; para un ecualizador

lineal, 6 (n) = y(n) y p, (n ) = y(n - N ) . Para la decisión retroalimentada del

ecualizador,

También definiremos un vector extendido XM(n) , con M=N+p dimensiones,

tal que contiene elementos de <,(n) abriendo un campo de orden sobre los

elementos de x N ( n ) . Por ejemplo en el caso de una retroalimentación del

ecualizador de decisión, con p = 2,

12

I ---

I f

"_"

d(n - I)

Las líneas punteadas denotan la partición de los vectores y las matrices.

En general Sm es la permutación de matrices obvias y e,, el re-arreglo de

10s elementos del Vector extendido X M (n) para desplegar tP (n) , pp (n) , xN ( n ) y

xN (n + I) en una forma de partición simple, es decir

Y

13

APLICACI~N DE UN ALGORITMO RECURSIVO CON MINIMOS

CUADRADOS PARA UN ECUALIZADOR ADAPTIVO.

El problema del ecualizador adaptivo es un clásico problema de mínimos cuadrados recursivos H31, H41. En particular requeriremos del algoritmo del ecualizador adaptivo para generar las conexiones de los coeficientes del vector CN(n) para el

tiempo n tal que minimizamos la acumulación del error cuadrático.

La minimización del vector es la solución de la ecuación de Wiener-Hopf:

donde

\ / 6 > = 0

En la práctica, el parámetro 6 es fijo constante de valor pequeño positivo para

asegurar la no singularidad de la matriz R N N ( n ) . Entonces esto puede ser

demostrado por (41, que en consecuencia CN (n ) puede ser generada recursivamente

de la siguiente manera:

donde

14

La covarianza inversa de la matriz estimada RNN(n)-' mostrada en (10) acelera

grandemente la adaptación del ecualizador, independientemente de las características del canal de dispersión, 141, [51, [61

El vector k , ( n ) puede ser generada por el algoritmo recursivo tal que

produciría N por N de la matriz R,,(n)" sin requerir explícitamente la matriz

inversa. El algoritmo resultante, es el caso especial del algoritmo convencional de Kalman para los ecualizadores adaptivos, reportado por Godard . El parámetro 6

devuelve salida que serían estimadas al final de un mal error cuadrático; el estado del

algoritmo es trascendente y firme y no esta bien sensibilizado para la selección de 6.

Esta complejidad del algoritmo, es proporcional a N2, se usa matrices de arista

de N por N para computar k , (n) . El "Algoritmo fuerte de Kalman" será presentado

matemáticamente equivalente a esto, por la proeza de cambiar la propiedad para computar los vectores k , (n ) recursivamente, sin necesidad de computar o

almacenar alguna matriz de N por N.

En el algoritmo de Kalman (convencional o fuerte) para el ecualizador

adaptivo, todos los vectores previos x,,,(n) y los errores previos em) son acordados

de igual peso en la determinación de conexiones de sus coeficientes estimados. Esta fuente de trabajo para la limitación-duración inicial del arranque de fase. De

cualquier modo el estado fijo de operación usualmente requiere de estos vectores { x , ( k ) } para evitar la siguiente variación en el canal actual y evitar los problemas

asociados con los errores digitales aleatorios. Un criterio conveniente a ejecutar estos requerimientos de caso de estudios, es minimizar exponencialmente el peso del error cuadrático en el tiempo n.

2

C x " " [ d ( k ) - C , ( n ) T x , ( k ) ] k=l

15

donde A es algún número positivo cerrado, pero menor que 1. El inverso de I -h es, aproximadamente hablando, la memoria de el algoritmo. La minimización del vector C, (n) es ahora

donde

Note que (12a) implica

EL ALGORITMO FUERTE DE KALMAN

Los siguientes escalares, vectores y matrices son almacenadas y actualizadas durante cada iteración:

(1) Matrices N por N; A , (n ) y DNP(n) con valores iniciales A,(O) = D,(O) = O,

(2) Matriz N por N; EJn) con valor inicial Epp,(0) = d l ,

( 3 ) Vector con dimension M; k,(n) donde M=N+p (4) Vector con dimension p; sp (n), sP (n)' , rll, (n), y cc, ( n )

(5) Vector con dimension N; mN(n)

Los valores iniciales del vector k , (n ) es

16

y todo x(n) =O para n < =O.

Entonces iniciamos con n =I, k , ( n + 1) este actualizado con el siguiente

algoritmo:

(Multiplicado por la permutación S,, y QM simplificando la cuenta de

permutaciones de los componentes de cada vector). La línea de división de la ecuación (18) indica una permutación.

Partiendo de Q M k , ( n ) tenemos lo siguiente:

17

Una vez actualizada las conexiones del ecualizador con los coeficientes de cada

vector C,(n + 1) entonces tomamos las ecuaciones (2) y (91, usando el vector

K,,, (n + 1 ) .

El conteo del numero de operaciones necesarias para calcular cada salida del

ecualizador y su actualización, pone a cada coeficiente de las conexiones un nuevo

indicativo como para el algoritmo, 7Np + Np2 + 3p2 + 2N + 4/3p3 - p /3 multiplicado

(ecuaciones (21, (9) y (14) hasta la (22)) y 7Np + Np2+p2/2 + An + 4/3p' + 19/6p sumas.

Estos conteos de divisiones como multiplicaciones y elementos Guassianos eliminan la matriz inversa p por p 1151. La correspondencia de convencíonalidad-

implementación del algoritmo de Kalman es de 3N2 +3N multiplicaciones y

2 N 2 + 2 N + 1 sumas. Para un sencillo algoritmo gradiente tenemos que C N ( n ) es

actualizado, acordado por:

CN (n) = C , (n - 1) + ge(n9xN (n) (g una constante)

(23)

2N multiplicaciones y 2~ sumas son necesarias para computar las salidas de ecualizador y actualizar los coeficientes de conexión.

De este modo para el ecualizador lineal (p=1), el número de computaciones por intervalo de símbolo es de:

Kalman fuerte 3N2 + 3N Kalman convencional

12N +S ION +4

2N2+2N+1

Para N grande la complejidad del ecualizador con el algoritmo fuerte de Kalman es aproximadamente 5 veces más rápido que el del gradiente sencillo. La

18

convencionalidad-implementación del algoritmo de Kalman es de aproximadamente N veces menor que el del complejo algoritmo del gradiente simple.

SIMULACION DE LOS RESULTADOS

La figura 1 muestra un esquema de los datos de un sistema de comunicación con un ecualizador lineal cuyas conexiones de coeficientes podrían adaptarse acorde con otros algoritmos, por ejemplo el del fuerte de Kalman o el del algoritmo del

gradiente simple. El programa de simulación estaba dado para el lenguaje BASIC pero se puede usar otros tipos de lenguajes, y ejecutarlo sobre un tiempo-real. 4 niveles de datos pseudo-aleatorios estarán generando y verificando las continuas muestras de impulsos respondidos para 6600 bauds, sistemas de datos de comunicación modulados sobre VSB con 3455 Hz de acarreo de frecuencia, usado sobre un típico canal de teléfono. Los bits de rotación correrían a 13200 bits/s. Adicionando ruido de muestra Gaussianas sumaran al filtro de salida una simulación de señal-ruido en un radio de 31dB. Esta basebanda equivale a la respuesta de impulsos y radios de señal- ruido que estarán mapeados por el algoritmo de adaptación de Kalman 151. La

característica de la frecuencia del canal del teléfono [51, estará anulando los profundos ruidos causados por la baja convergencia del algoritmo gradiente 121.

EI ecualizador lineal tiene N =31 conexiones. Estas salidas estarán substrayendo de referencia lineal la transmisión de datos que corren d(n), a la forma de la señal de error em). La secuencia del error em) {ecn)} y la secuencia de entradas del ecualizador {xcn)} estarán usadas para ajustar las conexiones del ecualizador adaptivamente, y mensurar el error cuadrático durante la adaptación, estarán desplegando como función, los números de cada iteración. Como muestra la figura 2. Note que (e2)>1 inicialmente porque los datos son (+-)1,(+-)3, con igual probabilidad.

EI algoritmo de adaptación del gradiente sencillo esta implementado como en la ecuación (231, donde la constante g, se escoge para rotar la gran convergencia, como de 0.002. El canal de impulsos responde normalmente al tener unidad de energía.

19

El algoritmo fuerte de Kalman estará implementado con a=1. Porque este algoritmo es comenzado con todos los vectores k, A, etc. a cero y con x(n) = O para n < =O, esto se encontrará conveniente para empezar la actualización de k después de leerlo en el corte del primer pulso de datos recibido. Sin embargo para ambos algoritmos, los grandes resultados estarán obteniéndose por el comienzo de la conexión de los coeficientes del ecualizador actualizando antes la principal parte de los primeros pulsos de datos recibidos. “Iteración de Números”, en la figura 2 se enumeran los comienzos de las conexiones de actualización de los coeficientes del

ecualizador.

El error cuadrático estará estimado por cada iteración como el promedio del

peso y su exponencial. La memoria del peso exponencial estará sobre las órdenes de

10 intervalos de símbolos. Para ambos algoritmos adaptivos, el valor inicial de todos los coeficientes conectados serán cero. La convergencia del algoritmo del gradiente simple estará bien bajo porque el canal de frecuencia anulará las respuestas. El

algoritmo de Kalman converge a un valor firme dentro de aproximadamente 80

intervalos. Esta convergencia comporta a este, como sería esperado un similar algoritmo convencial-implementado de kalman/Godard 151.

CONCLUSIONES

El algoritmo del ecualizador adaptivo de Kalman tiene una proporcional complejidad de N, justa en el caso de un algoritmo de gradiente simple, mientras que se tiene un rápida convergencia con el algoritmo de convencionalidad- implementación de Kalman, cuya complejidad es proporcional a N2. El rápido algoritmo es una factor matemáticamente equivalente para el algoritmo convencional de Kalman; el solamente requiere de esto (1) el cambiar la propiedad de entrada de los vectores (satisface en todos los ecualizadores conocidos o cancelaciones de aplicaciones de eco); y (2) que actualice el vector inicial k , ( n ) con

todas la muestra previas x(n) asumidas a cero. El posterior requerimiento garantiza una condición de comienzo simple, con el argumento de inducción usado en el rápido algoritmo de derivación.

20

Para un ecualizador lineal, el algoritmo rápido de Kalman requiere un número de operaciones por iteración solo aproximadamente 5 veces que para el algoritmo de gradiente simple. Acordando la cantidad de números por operación tabulado anteriormente, una correspondencia del algoritmo convencional-implementación de Kalman requeriría aproximadamente 45 veces tal como muchas operaciones haría el

algoritmo del gradiente.

21

Adición Gaussiana Muestra de ruido

4-Nive1 de datos d(n) , M u m Ecualizador Lineal , ~

(impulsos) (31 conexiones) i A

Algoritmo Adaptivo .........; Error e(n)

A

.............................................. .......................................

Fig. 1 Simulación de un sistema de transmisión de datos

E R R O R

C U A D R

1

0.1

C O

O..Ol

Error de mínimos ............................................ .......................... 20 40 60 : 80 10 12 14

NUMERO DE ITERACIONES o O O

Fig. 2 Convergencia del error cuadrático, todos los ecualizadores inicializados a cero

22

23

CAPITULO II

EL COMBINADOR LINEAL DE IMPULSO-RESPUESTA-FINITO.

Analizaremos un filtro con una estructura de impulso-respuesta finita en tiempo y

discreta (FIR) , basado en una línea de retardo y un conjunto de N coeficientes de ganancia ajustables Wo hasta WN-1 . La salida del filtro Y(x) es simplemente la suma de las entradas retardadas y escaladas dada por

por conveniencia Y(x) también puede ser escrita como los puntos (o interiores) producto de 2 vectores : i. e.

donde

W = [Wl,W2, ........, W(N-1) 1 t y

X(k) = [X(k),X(k-l) ,...., X(k-N + 111 t

El filtro mostrado en la figura también usa una forma simple de valoración de calidad de la senal filtrada. La salida del filtro Y(k) es comparada a una forma de onda deseada d(k), y alguna diferencia entre las dos constituye un error y por lo tanto una

24

degradación de la calidad. La forma de onda d(k) es en algunas veces llamada la serial deseada, la referencia, o la forma de onda plantilla.

El objetivo de seleccionar los coeficientes del filtro adaptivo es para forzar a ser Y(k)

igual a d(k) exactamente.

Uno pudiera cuestionar porque no simplemente pasamos d(k) en vez de Y(k), ya que es la sena1 deseada a la salida del filtro. Por ahora citaremos dos circunstancias donde la transmisión de d(k) en vez de Y(k) no es posible.

En ciertas aplicaciones d(k) esta solo disponible durante una fase de entrenamiento en conjunción con una secuencia de valores de entrada predeterminada . En tales casos la adaptación es cesada durante el procesamiento de la actual secuencia de entrada X , para cada d(k) no esta disponible (es imposible).

En otras aplicaciones d(k) es "medible" solo después de que calculamos Y(k). En otras palabras, nuestra evaluación de calidad es derivada de una "perfecta" retrospectiva.

Alguna diferencia entre d(k) y Y(k) resulta en una Serial de error e(k) (distinta de cero), la cual intentamos usar en los parámetros de las reglas de adaptación del filtro. Como hemos notado, el objetivo del ajuste es buscar un conjunto de coeficientes, un vector W; el cual reduce e(k), o alguna función de e(k) al valor más pequeno posible, cuando esta parametrización es alcanzada (y mantenida), es decir el filtro toma convergencia a el conjunto optimo d coeficientes representado por el vector Ws.

Nótese que si d(k) = xt(k)WS, entonces W = W$ implica que e(k) = O para todo k.

Nuestras reglas de ajuste de parámetros son terminadas de adaptar si, cuando la solución optima previa W$ cambia a un nuevo valor. Cada algoritmo adaptivo es necesariamente recursivo; como nuevas entradas son procesadas y su calidad es evaluada, el filtro es actualizado, si es necesario.

25

ECUALIZACI~N DE UN CANAL USANDO UN FILTRO DE

KALMAN PARA LA TRANSMISI~N RÁPIDA DE DATOS.

A continuación se muestra cómo el filtro de Kalman puede aplicarse en el problema de establecer la ganancia de ecualizadores transversales para minimizar la distorsión cuadrática (mean-square). En presencia de ruido y sin conocimiento previo del canal, el algoritmo del filtro conduce a una convergencia más rápida que otros métodos, su velocidad de convergencia depende solamente del número de recursos. Se dan resultados teóricos y se usa una simulación por computadora para corroborar la

teoría y comparar el algoritmo con el método clásico.

Los sistemas de transmisión de datos generalmente usan canales de comunicación de voz de banda. Estos se caracterizan por un ancho de banda relativamente estrecho. (de 300 a 3000 Hz), una alta razón de ruido en la señal (aproximadamente de 20 a 39 dB), y una amplitud y distorsión de fase que varían lentamente con el tiempo. La alta velocidad de transmisión de datos requiere entonces ecualización. Muchos módems receptores usados en la actualidad, están equipados con un filtro para maximizar razón de señal/ruido y un ecualizador para minimizar la interferencia entre símbolos debida a una distorsión. Los ecualizadores generalmente son del tipo de filtro transversal, con ganancias dedicadas a minimizar algunos errores de criterio. Un proceso automático de ecualización requiere un período inicial de entrenamiento durante el cual el ecualizador reduce el error. En la “ecualización preestablecida”, pulsos aislados son transmitidos previamente a la transmisión de

datos, y las ganancias establecidas derivadas se mantienen constantes durante la transmisión de datos. Periódicamente, debe practicarse un corto lapso de entrenamiento para mantener actualizadas las ganancias.

Una segunda clase de proceso de ecualización es conocido como “ecualización adaptiva”. Aquí el ecualizador establecido es derivado de la señal recibida. Durante el período de entrenamiento, el ecualizador continuamente busca minimizar la desviación estándar de la muestra de su señal de salida de una referencia ideal generada internamente en sincronía en el receptor. Cuando la distorsión residual es lo suficientemente pequeña, los datos actuales pueden transmitirse. El ecualizador es entonces cambiado en el “modo dirigido de decisión”, usando como referencia una señal reconstruida obtenida poniendo en el “umbral” la señal de salida del

26

ecualizador. La ecualización adaptiva tiene muchas ventajas sobre la ecualización preestablecida, estando entre ellas la capacidad de adaptación a los cambios en las características del canal durante la transmisión.

Claramente, hay un retraso en la transmisión de datos proporcional a la longitud del período de entrenamiento, y es deseable un decremento en este retardo. Muchos algoritmos de ajuste han sido descritos en los libros, generalmente haciendo énfasis en la velocidad de convergencia. El bien conocido algoritmo de los mínimos cuadrados de Gersho, muestra que la velocidad de convergencia es determinada por los valores máximo y mínimo del espectro de poder de la señal sin ecualizar . Resultados similares para algoritmos más sofisticados se han reportado por Chang y

Kobayashi.

Aquí, un nuevo algoritmo, basado en la teoría de filtrado de Kalman, es propuesto para obtener una rápida convergencia en la ganancias de ecualizadores transversales para su óptima configuración. Un filtro de Kalman ha sido aplicado previamente al canal de ecualización por Lawrence y Kaufman, pero en una forma enteramente diferente, comenzando por el hecho de que en su estudio el ecualizador es reemplazado por el filtro.

Mostraremos que la convergencia de mínimos cuadrados se obtiene, bajo condiciones de ruido, dentro de un número de iteraciones determinado solamente por el número de utilizaciones, sin previa información sobre el canal. Después de revisar los fundamentos de la teoría de Kalman, mostramos cómo aplicar ése filtrado en la ecualización y en la derivación de una expresión para la velocidad de convergencia. Finalmente, se usarán simulaciones por computadora para comprobar la validez de la teoría y para comparar el algoritmo propuesto con el método descendente. Se hace una comparación además con algunos otros sofisticados algoritmos.

27

28

CAPíTULO Ill

DIVERGENCIA EN EL FILTRO DE KALMAN

Bajo ciertas condiciones, la órbita estimada por un filtro de Kalman tiene errores mucho más grandes que los predichos por la teoría. Este fenómeno es llamado divergencia, y proporciona la operación insatisfactoria del filtro de Kalman .

La ejecución del filtro de Kalman bajo las condiciones actuales de operación puede degradarse seriamente en relación de la ejecución teórica indicada por el estado de la matriz de covarianza. El filtro de Kalman teóricamente produce una estimación cuya precisión va incrementándose con cada observación adicional que es procesada. La magnitud de los errores de estimación medida por el determinante de

la matriz de covarianza del error de estimación es una función monótona decreciente del número de observaciones. Sin embargo, se ha observado que bajo las condiciones actuales de operación, los niveles de error en el filtro de kalman son significativamente más altos que los predichos teóricamente. Los errores pueden, de hecho, incrementarse continuamente aunque se estén procesando datos adicionales. La posibilidad de dicha inestabilidad o comportamiento divergente fue sugerida primero por Kalman. Más tarde fue notada por Pines y Knoll y otros en aplicación del filtro de Kalman a la navegación espacial y la determinación de órbitas.

CAUSAS DE LA DIVERGENCIA

una causa de la divergencia del filtro es la discrepancia entre el modelo matemático usado para derivar las ecuaciones del filtro y las actuales condiciones bajo las cuales el filtro debe operar. Ejemplos de tales discrepancias son el descuido de los términos en el potencial gravitacional o un conocimiento inexacto de las constante en el potencial. Otro origen de la divergencia son los errores en el coeficiente balístico o en el modelo de densidad de aire usado en el cálculo de la aceleración de arrastre. Tales errores se asumen como errores parciales. Ya que ellos afectan las ecuaciones dinámicas de movimiento, y para diferenciarlos de las observaciones parciales, estos errores se denominan parciales dinámicos.

29

La figura 1 muestra la divergencia causada por un error del 25 % en la aceleración de

arrastre. Un origen diferente de divergencia son los errores "round-off" inherentes en la implementación de las ecuaciones del filtro en una computadora digital de palabras de longitud finita. La figura 2 muestra el efecto de los errores computacionales inducidos por una singular precisión aritmética (IBM 7090) en el filtro de Kalman.

Una manifestación de los errores causados por la máquina ocurre en el cálculo del estado de la matriz de covarianza. Después de que el filtro de Kalman ha estado operando por algún tiempo, ésta matriz deja de ser definida positiva y simétrica. Los coeficientes relevantes del filtro calculados usando ésta matriz son entonces erróneos y, consecuentemente, la órbita estimada es incorrecta. J. E. Potter y R.

Battin derivaron una variación del filtro de Kalman en la cual la matriz de covarianza permanece al menos simétrica no-negativa. Esta técnica elimina algunos, pero no todos los efectos de los errores computacionales y al mismo tiempo el filtro requiere un algoritmo más complejo. En filtros de procesamiento por lotes, los errores "round-off" en el filtro se vuelven evidentemente serios como errores computacionales en la operación de la matriz de inversión.

Varias aproximaciones han sido sugeridas para prevenir la divergencia del filtro. Una aproximación sostiene que la divergencia ocurre cuando el filtro asigna un peso demasiado pequeno al último dato medido. Así el dato actual hace sólo una pequena corrección en la estimación, de hecho muy pequena, ésos errores crecen actualmente por la interacción natural de los errores de posición y velocidad. Un "arreglo" obvio es incrementar más o menos arbitrariamente el peso del dato actual. Tal arreglo implica incrementar la matriz de covarianza de estado mientras mantenemos constante el período de órbita incierto. La frecuencia y cantidad del incremento debe determinarse empíricamente, y puede emplearse tanto en filtros recursivos como en los no recursivos.

Schmidt y Pines han sugerido modificaciones analíticas a las ecuaciones del filtro para representar parciales dinámicas sin incrementar el número de estados a ser estimados por el filtro. Además, Pines ha desarrollado una máquina simple para modificación del ruido basada en modelo asumido de los errores causados por

30

“round-off’’ en la computadora digital. Otras técnicas, tales como el borrado del filtro para guardar los elementos de la diagonal de la matriz de covarianza de estado en un “umbral” específico, fueron investigados por Holick.

Ditto experimentó la divergencia en el corrector diferencial no-recursivo Gemini- Bayes, donde los problemas numéricos aparecen en la inversión de matrices no condicionadas, así como en el incumplimiento de parciales dinámicas. La ocurrencia de la divergencia en un filtro no recursivo no es sorprendente en vista de la equivalencia del filtro de Kalman y la mínima varianza no recursiva del filtro. Las modificaciones del filtro empleada por Ditto son similares a las de Schmidt y Pines.

EJEMPLO ILUSTRATIVO.

Para proporcionar al lector una comprensión intuitiva del problema de la

divergencia, daremos un simple ejemplo analítico, donde el filtro de Kalman estima cómo diverge una trayectoria de la verdadera cuando el número de observaciones se incrementa. Éste fenómeno es ocasionado en este caso por la omisión de una de

las componentes de estado del vector que describe el sistema. Esta situación ocurre generalmente in la práctica, ya sea deliberadamente para disminuir la complejidad de la representación del sistema, o bien de forma inadvertida porque se desconoce la existencia de ciertos estados. El ejemplo considerado aquí es la estimación de la

altitud X de un vehículo de datos de altura. Un filtro de Kalman se diseña primeramente suponiendo que X es constante, ¡.e., el vehículo se encuentra ascendiendo (o cayendo) con una aceleración constante. Una pequeña modificación del filtro de Kalman muestra entonces la eliminación de ésta divergencia.

Para diseñar el filtro de Kalman, asumimos que las medidas de altitud tienden a cero es independiente de los errores aleatorios de ruido n(k) que poseen una desviación estándar común u. En resumen, los errores por ruido se asumen acotados, JnNl <=B.

El filtro de Kalman estimado de la altitud está dado por:

31

+) = -1 + W ( k ) [ Y O - Y,(k)l W ( k ) = P(k -)l[P(k -)+ 0 2 1

P(k -) = P(k - 1 +) X ( k -) = X ( k - 1 +) P(k+) = P(k-) - P(k-)[P(k-) + 0 ']"P(k- ) y ( k ) = X ( k ) + n(k)

Y,(k) = m - )

Donde O = desviación estándar del P(O-)= varianza de la altura estimada a pri

error por ruido de la altura or¡; y los símbolos - y + que aparec

n (kl, Ben en

las ecuaciones precedentes, denotan los estimados inmediatamente al previo e inmediatamente subsecuentes a una observación.

Supongamos ahora que el vehículo, en vez de permanecer a una altitud constante, está ascendiendo con una aceleración constante y su trayectoria está descrita por:

Supongamos también que las medidas de altitud son tomadas una vez por segundo. Un fácil cálculo conduce para el filtro de Kalman, a la altitud observada después de N

observaciones:

VN 1 X ( N + ) = X ( 0 ) + ~ + ______ C n ( k )

2 N+1,=,

Substrayéndolo de la trayectoria real:

X(N) = X(0) + VN

encontramos que para el error U(N)

VN 1 N

2 N + l , = , & ( N ) = X ( N ) - X ( N + ) = - + ~- C n ( k )

y como los errores de ruido están acotados,

32

Por lo tanto, la desviación del filtro de Kalman estimada de la trayectoria verdadera, se incrementa decrementando N.

33

PÍTULO

34

CAPITULO IV

EJEMPLO ILUSTRATIVO.

/ * DECLARACION DE VARIABLES GLOBALES Y PROTOTIPOS DEL PROGRAMA KALMAN * /

# include # include # include # include # include # include # include # include # include

<graphics.h> <dos. h> cstdio. h> <conio. h> <bios. h> <stdlib.h> <time . h> <mouse. h> <portada.h>

#define tam 14 #define muestras 14 #define N 14 #define M 100 #define NumElem 14 #define NumBlock 100 #define NumIter 60 #define NumLoop-Corr 20 #define Num AR 5 #define PI 3.141592

/ * orden del predictor * /

/ * VARIABLES GLOBALES * /

double HK [ tam] , XK [ tam] , A [ tam] ; double Q[tam] [tam] ,Q1 [tam] [tam] ; double sena1 Y [muestras] ; double senal-D[muestras]; double Y2,Y3T D, error; / * salida del filtro * / double arr [250] ; int opc = 1, uso; char cadfileout [50] ; / * almacena el archivo datos * / char cadfileinA[50]; / * almacena el archivo de A * / char cadfileinX[50]; / * almacena el archivo de X * / char cadfileinD[50]; / * almacena el archivo de D * / char USO='O'; / * O si es Predictor o char AA='O'; / * O si es aleatorio y * / char XX='O'; * /

/ * O si es aleatorio y

donde se guardaran los

donde se leeran los datos

donde se leeran los datos

donde se leeran los datos

1 si es Estimador * / 1 si se toma de archivo A

1 si se toma de archiuvo X

char DD='l'; / * 1 si se toma de archiuvo D * / char NUMA[5],NUMX[5],NUMD[5]; / * almacenan el numero de muestras * /

35

char A1='O1,D1='O';

/ * PROTOTIPOS DE FUNCIONES * /

void inicializa(void); void KALMAN (void) ; void vector XK(doub1e nvoval); void vector-A(void); void proyecto (void) ; void fuera (void) ; void correr (void) ;

void void void void void void void void

inicial (void) ; lim vert (void) ; lim-horiz(void); muestra rat (void) ; esconde-rat (void) ; reporta-edo (int *x, int *yI int *edo) ; ini graf (void) ; flecha(int x, int y, int clr) ;

void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void

menu (void) ; mensa j e-mouse (int x , int y) ; mensa j e-tecla (void) ; detecta opc(int x, int y); checa-opcion (void) ; mueve-opcion (int k) ; limpia barra (void) ; limpia-flechas(void); func (int xi , int yi , int xf, int yf) ; haz opcion (void) ; mensaje tecla func2 (void) ; checa-o&ion-func2 (int x, int y) ; uso comun mouse (int x, int y, int xi , int yi , int x€, int yf) ; rangomouse (int x, int y, int xi , int yi , int xf, int yf) ; mueve-opcion-uso(int k); limpia barra uso (void) ; comunlTint xTint y,char *cadl,char *cad2); comun2 (int x, int y, char *cadl, char *cada) ; flecha2 (int x, int y, int color) ; guarda imagen(int x1,int y1,int x2,int y2,void **imagen); boton (int x, int y, char *cadena, int clr) ; boton press(int x,int y,char *cadena,int clr); botonIcirc (int x, int y) ; fondo (void) ; esq-sup-izq (int x, int y) ; esq-sup der (int x, int y) ; esq-infIizq(int x, int y); esq inf-der (int x, int y) ; lineas (void) ; cuadro2 (void) ; cuadro3 (void) ; barrido (int xi, int yi , int xf , int yf, int color) ; mensa j e (void) ; ventana - menu(int xi, int yi, int xf, int yf) ;

void void void void void void void void void void void void void void void void void void void void

barra(int x, int y, int anch, int alt) ; barra1 (int x, int y, int anch, int alt, int clr) ; barra2 (int x, int y, int anch, int alt) ; titulo (void) ; cuad men (void) ; logotipo (int x, int y, int colorl, int co1or2) ; fondo azul (void) ; submenus (int x, int y, int x1 , int yl) ; captura archivo(void); void captura archivo2(void); enbarraT(int x, int y, int anch, int alt, int fondo) ; captura (int x, int y, int tope, int clr, char *cadena) ; caja(int x, int y, int taml); advertencia(char *cadl,char *cad2); captura muestras(void); void captura aleatorios(void); salida (void) ; void integrantes (void) y inicializa cadenas(void); rango-mousg-horizontal(int x,int y); salida-entrada (void) ; hacer instalacion (void) ; restablece(v0id);

void inicializa - cadenas() / * inicializa las cadenas de salida * /

strcpy(cadfileout, " " ) ; / * numero de muestras a tomar para * / strcpy(cadfileinA, " " ) ; / * cada uno de los par metros * / strcpy(cadfileinX, " ' I ) ; strcpy(cadfileinD, " " ) ; strcpy (NUMA, " " ) ; strcpy (NUMX, ' ' ' I ) ; strcpy (NUMD, ' " I) ; 11

I / * las rutas de los archivos y el * /

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / * FUNCIONES GRAFICAS PARA EL AMBIENTE * /

# include <kalman.h>

char entro='O'; char entrouso;

char NUMTEMP[S]; / * guardamos en el, el numero temp. de muestras * /

void menu ( ) { int edo, if x, y;

/ * in¡-graf ( ) ; * / fondo ( ) ; fondo-azul ( ) ;

/ * cuadros de menu * / barra(10,29,100,418); / * cuadro del menu de opciones * / barra(15,34,90,408) ;

/ * botones de opciones * /

37

boton (40,130, ''USO", 9) ; boton (40,170, "A", 7) ; boton (40,210, "X", 7) ; boton(40,250, "Dl', 7) ; boton(40,290, r 'Runl' , 7) ; boton(40,330, "Clr", 7) ; boton (40,370, "Exit", 7) ;

cuad men ( ) ; mensaje ( ) ; / * mensaje de opcion * / titulo ( ) ;

logotipo (562,431,15, O) ; muestra - rat ( ) ;

while (1) { edo=0 ; i=O ; reporta edo (&x, &y, 6redo) ; mensaje-mouse (x, y) ;

if (bioskey (1) ) { if(edo==l-lI bioskey(l)){ / * si se hizo un click izq o un enter * /

i=bios key ( O ) ; if (i!=7181) {

mueve-opcion (i ) ; mensaje tecla ( ) ; checa - opcion ( ) ;

i i if (edo==l)

{ detecta-opc (x, y) ; if (opc ! = O) checa-opcion (

1

if ((i == 7181 1 I edo==l)) {

switch (opc) { case 1: entrouso=

Kalman") ;

1

boton press ( setcoior (7 ) ;

O'; 40,

/ * si es un click * /

uso=l ; 130, "USO" , YELLOW) ;

outtextxy(35,457,"Forma en que se usar el algoritmo de

edo=0 ; func (130,100,250,170) ; boton (40,130, "Uso", 9) ; break;

case 2: entrouso='O'; uso=l; if (Dl=='O') { boton press (40,170, "A", YELLOW) ; setcoior (7 ) ; outtextxy(35,457,"Numeros aleatorios"); Al='l'; func (130,135,250,205) ; boton(40,170, "A", 9) ; boton press (40,250, "D", 7) ; 1 else

-

i sound(1800); delay(100);

38

/ *

/ *

sound(2000); delay(100); nosound ( ) ;

1 break;

boton press (40,210, "X", YELLOW) ; setcoior (7) ; outtextxy(35,457, "Pesos de la entrada") ; func (130,170,250,240) ; boton (40,210, "X", 9) ; break;

if (A1=='0') { entrouso='O'; uso=l; boton press (40,250, "D", YELLOW) ; setcoior (7) ;

case 3: entrouso='O'; uso=l;

case 4:

outtextxy(35,457, "Numeros de func (130,205,250,275) ; * / Dl=' 1 ; boton press (40,170, "A", 7) ; boton740,250, "D", 9) ;

}else i sound(2100) ; delay sound(2900) ; delay nosound ( ) ;

1

break;

boton press (40,290, r'Run", YEL set color (7 ) ; outtextxy(35,457, "Inicia los correr ( ) ;

case 5: esconde rat ( ) ; L

correlacitn") ;

100) ; 100) ;

OW) ;

calculos de Kalman") ; . . .

inicializa cadenas(); / * inicializa las cadenas * / muestra rat( ) ; boton(45,290, "Run", 9) ; break;

boton press (40,330, r'Clrr', YELLOW) ; barrido (357,70,595,175,5) ; restablece ( ) ; boton (40,330, "Clr", 9) ; muestra-rat ( ) ; break;

boton press (40,370, "Exit",RED) ; integrantes ( ) ; * / salida-entrada ( ) ; boton (40,370, "Exit", 9) ; break;

integrantes ( ) ; muestra-rat ( ) ; break;

case 6: esconde rat ( ) ;

case 7: entrouso='O';

case 8: esconde-rat();

1 } ;

1 / * endif * / } / * enddo * /

39

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MENU GENERAL

. . . . . . . . . . . . . . . . . . . . . . . . . / * muestra los mensajes en la barra de estado, de cada una de las opciones*/ / * cuando estos son tocados con el cursor del mouse * / . . . . . . . . . . . . . . . . . . . . . . . . . void mensajemouse (int x, int y) {

i€(x >=40 & & X <=70 ) { if(y >= 120 & & y <= 140 & & entro!='l'){ limpia barra ( ) ; setcolor (15) ; outtextxy(35,457,"Forma en que se usar el algoritmo de

entro='l'; Kalman") ;

}else if(y >= 160 & & y <= 180 & & entro!='2')i

limpia barra ( ) ; setcolor (15) ; outtextxy (35,457 , "Numeros aleatorios") ; entro='2';

}else if(y >= 200 & & y <= 220 & & entro!='3'){

limpia barra ( ) ; setcolor (15) ; outtextxy(35,457,"Pesos de la entrada"); entro='3';

1 else if(y >= 240 & & y <= 260 & & entro!='4'){ limpia barra ( ) ; setcolor (15) ; outtextxy(35,457, "Numeros de correlacicn") ; entro='4';

if(y >= 280 & & y <= 300 & & entro!='5'){ }else

limpia barra ( ) ; setcolor(15); outtextxy (35,457, "Inicia l o s calculos de Kalman") ; entro='5';

}else if(y >= 320 & & y <= 340 & & entro!='6'){

limpia barra ( ) ; setcolor(15); outtextxy(35,457,"Restablece valores al

entr0='6'; } else

determinado") ;

if(y >= 360 & & y <= 380 & & entro!='7'){ limpia barra ( ) ; setcolor (15) ;

40

outtextxy (35,457 , "Salir del programa") ; entro='7';

1 }/*else limpia - barra();*/

. . . . . . . . . . . . . . . . . . . . . . . . . / * muestra los mensajes en la barra de estado, de cada una de las opciones*/ / * cuando se mueve con las flechas del cursor * / . . . . . . . . . . . . . . . . . . . . . . . . . void mensa j e-tecla ( ) [

limpia barra ( ) ; setcolor(15); switch (opc) { case 1:

outtextxy(35,457,"Forma en que se usar el algoritmo de Kalman" ) ;

break;

outtextxy (35,457 , "Numeros aleatorios") ; break;

outtextxy(35,457, "Pesos de la entrada") ; break;

outtextxy(35,457, "Numeros de correlacitn") ; break;

outtextxy(35,457,"Inicia los calculos de Kalman"); break;

outtextxy(35,457,"Restablece valores al determinado"); break;

case 2:

case 3:

case 4:

case 5:

case 6:

case 7: outtextxy (35 , 457 , "Salir del programa") ;

/ * outtextxy(35,457,"Lista de colaboradores en el programa") ; * /

break;

. . . . . . . . . . . . . . . . . . . . . . / * checa el rango del mouse cuando se pulsa el boton izquierdo * / . . . . . . . . . . . . . . . . . . . . . void detecta opc(int x,int y)[

if (x >=7 && x <=28 ) { if(y >= 5 & & y <= 27) opc = 7;

1 else if(x>=603 & & x<=622 & & y>=5 & & y<=27)

else OPC =8;

if (x >=40 & & x <=70 i if(y >= 120 & & y <= 140) OPC = 1; else

if(y >= 160 & & y <= 180) opc = 2; else

41

}else opc=O;

. . . . . . . . . . . . . . . . . . . . . . . / * cambia las opciones del menu cuando estos son movidos con las flechas * / / * del cursor * / / * * * * * * * * * * * * x * * * * * * * /

void mueve-opcion (int k) {

switch ( k ) { case 18432 : opc--;

if(opc==2 & & Dl=='l') if(opc==4 & & Al=='l') break;

if(opc==2 & & Dl=='l') if (opc==4 & & Al=='l') break;

if (opc==2 & & Dl=='l') if(opc==4 & & Al=='l') break;

if(opc==2 & & Dl=='l') if (opc==4 & & Al=='l') break:

1 if (opc < 1) opc=7; if(opc > 7) opc=l;

case 20480 : opc++;

case 19200 : opc--;

case 19712 : opc++;

opt"; OPC" ;

opct+; opctt;

opc"; OPC" ;

opct+; opc++;

. . . . . . . . . . . . . . . . . . . . . . . / * refresca la opcion que fu, pulsada con el mouse, limpiando las flechas * / / * indicadoras y marcando la que esta activa * / . . . . . . . . . . . . . . . . . . . . . . . void checa option() {

switch (opc) { case 1: esconde-rat();

limpia-f lechas ( ) ; flecha (40,130,9) ; muestra-rat ( ) ; break;

if (D1=='0') { limpia-flechas ( ) ;

case 2: esconde-rato;

42

flecha(40,170,9) ; i muestra-rat ( ) ; break;

limpia flechas ( ) ; flecha~40,210,9) ; muestra-rat ( ) ; break;

if (A~=='G" ) { limpia flechas ( ) ; flecha740,250, 9) ;

1 muestra-rat ( ) ; break;

limpia-flechasO; flecha(40,290,9) ; muestra-rat ( ) ; break;

limpia-flechas ( ) ; flecha (40,330, 9) ; muestra-rat ( 1 ; break;

limpia flechas ( ) ; flecha(40,370, RED) ; muestra-rat ( ) ; break:

case 3: esconde rat ( ) ;

case 4: esconde rat ( ) ;

case 5: esconde rat ( ) ;

case 6: esconde rat ( ) ;

case 7: esconde rat ( ) ;

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / * * cambia el color de las flecha de seleccicn * / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . void flecha(int x, int y, int clr) I

esconde-rat ( ) ; setcolor(DARKGRAY); line (xt35 y-3 , x+39, yt4 ) ; line (x+35, y-3, xt42, y-3) ; line (xt39, y+4 , xt42, y-3) ; setfillstyle (SOLID-FILL, clr) ; floodfill (x+39, y, 8) ; setcolor (WHITE) ; line (x+39, y+4, x+42, y-3) ; muestra-rat ( ) ;

1

void limpia barra ( ) { setcolor (7) ;

outtextxy outtextxy outtextxy out t extxy outtextxy outtextxy

/ * limpia barra de estado * /

35,457, "Numeros aleatorios") ; 35,457, "Pesos de la entrada") ; 35,457, "Numeros de correlacitn") ; 35,457, "Inicia l o s calculos de Kalman") ; 35,457, "Salir del programa") ; 35,457,"Forma en que se usar el algoritmo de

Kalman") ;

43

outtextxy(35,457,"Restablece valores al determinado"); / * outtextxy(35,457,"Lista de colaboradores en el programa");*/ 1

void limpia - flechas ( ) { / * limpia las flecha de indicacion * / flecha(40,130,7) ; if(Dl=='O') flecha (40,170,7) ; flecha (40,210,7) ; if (Al=='O') flecha(40,250, 7) ;

1

flecha (40,290,7) ; flecha (40,330,7) ; flecha(40,370, 7) ;

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . . . . S u B M E N u S

void func (int xi, int yi, int xf, int yf) { int edo=0 , x, y, tecla=O; void "dibujol;

esconde rat ( ) ; guarda imagen (xi-10, yi-lO,xf+25, yftl0, Ldibujol) ; submenus (xi, yi , xf , yf ) ; muestra-rat ( ) ;

while(edo!=2 & & tecla ! = 283) { edo=0 ; tecla=O; reporta edo (&x, &y, &edo) ; uso - comün mouse (x, y, xi, yi,xf+20,yf+5) ;

if(edo==l I 1 bioskey(l)){ / * si se hizo un click izq o un enter

-

* / if (bioskey (1) ) { tecla=bioskey(O); if (tecla!=7181) {

mueve-opcion-uso(tec1a); mensaje tecla-func2 ( ) ; checa - opcion - func2(xi+20,yi+15);

1 1 if (edo==l ) / * si es un click * / I

rango mouse (x, yI xi, yi, xf+20, yf+5) ; if(us0 ! = O ) checa - opcion func2 (xi+20, yi+15) ; -

I

44

if (tecla == 7181 I I edo==l ) haz - opcion ( ) ;

1 } / * enddo * /

esconde-rat ( ) ; putimage (xi-10, yi-10, dibujol, O) ; free (dibujol) ; muestra-rat ( ) ; limpia barra uso ( ) ;

1 - -

void haz option() { * /

- / * realiza la funcion de cada una de las opciones

switch (opc) { case 1: switch (uso) {

case 1: setcolor (5) ; outtextxy(357,70, "E S t i m a d o r"); setcolor (14) ; outtextxy(357,70,"P r e d i c t o y"); USO=' o ;

/ * captura archivo ( ) ; * / break;

case 2: setcolor (5) ; outtextxy(357,70,"P r e d i c t o r"); setcolor (14) ; outtextxy(357,70,"E S t i m a d o y " ) ;

USO=' 1 ' ; break;

-

/ * captura archivo ( ) ; * / -

1 ; break;

case 2: switch (uso) {

case 1: setcolor (5) ;

o u t t e x t x y ( 3 5 7 , l o o , " 0 ~ 6 6 0 0 ~ ~ ~ 6 0 0 6 ~ 6 0 0 0 6 ~ 6 ~ ~ ~ ~ ~ 6 ~ ~ ~ ~ ) ; setcolor (14 ) ; OUttextXy(357,100, "Leyendo disco") ; captura-archivo2 ( ) ; & q & q = ' O I ;

break; case 2: setcolor (5) ;

outtext~y(357,~00,'~6~0600~000600006~0~~0~~6~06~~~~); setcolor (14) ; outtextxy(357,100,"Aleatorio"); captura-aleatorios0; A A = ' 1 7 . break;

1 ; break;

case 3: switch (uso) {

case 1: setcolor (5) ;

outtextxy(357,130,"66~~~~~0600006~06~~~0~~0~~00011); setcolor (14) ;

45

outtextxy(357,130, "Leyendo disco") ; captura - archivo2 ( ) ; XX='O'; break;

case 2: setcolor (5) ;

o u ~ ~ e x ~ x y ( 3 5 7 , ~ 3 ~ , " - - - - - - ~ - - - ~ - - - - - - - uuuuuuuuuuuuuuuuuu60~066666ú~~~); setcolor (14) ; outtextxy (357,130, "Aleatorio") ; captura - aleatorios(); XX='l'; break;

1 ; break;

/ * case 4: switch (uso) {

case 1: setcolor (5) ;

outtextxy(357,160,'Ú~66~~6~~66~6ú6~6ú~~6~~~060úú11); setcolor (14 ) ; outtextxy(357,160, "Leyendo disco") ; captura archivo2 ( ) ; DD=' O' ; break;

-

case 2: setcolor (5) ;

outtextxy(357,160,'16~66~6ÚÚ06~66666~~6~6~ú~6~ú~6~1); setcolor (14) ; outtextxy(357,160, "Aleatorio") ; captura-aleatorios0; DD='1' ; break;

1 ; break; * /

I 1

void mensaje tecla_func2(){ / * muestra el mensaje de funcionamiento * / limpiabarra-uso ( ) ; / * de cada una de las opciones * /

switch (opc) { setcolor (15) ;

case 1: switch (uso) {

case 1: outtextxy(35,457,"El programa se usar en modo de

break;

outtextxy(35,457,"El programa se usar en modo de

break;

Predictor") ;

case 2:

Estimador") ;

I ; break;

default: switch (uso) {

case 1: outtextxy(35,457, "Los datos se leeran de disco") ; break;

case 2:

46

outtextxy(35,457,"Los datos se generar n

break; aleatoriamente") ;

I ; break;

void checa opcion func2(int x,int y) { / * de acuerdo a la opcion en que se dio click se muestra su mensaje * /

switch (opc) { case 1:

switch (uso) { case 1: esconde rat ( ) ; comunl (x, y, "Predict~r", "Estimador") ; outtextxy(35,457,"El programa se usar en modo de

Predictor") ;

Estimador") ;

muestra - rat ( ) ; break; case 2: esconde rat ( ) ; comun2 (x, y+30, "Es~imador", "Predictor") ; outtextxy(35,457,"El programa se usar en modo de

muestra rat ( ) ; break;

-

} ; break;

default: switch (uso) {

case 1: esconde-rat ( ) ; comunl (x, y, "Leer disco", "Aleatorio") ; outtextxy(35,457 , "Los datos se leeran de disco") ; muestra - rat ( ) ; break; case 2 : esconde-rat ( ) ; comun2 (x, y+30, "ALeatorio", "Leer disco") ; outtextxy(35,457,"Los datos se generar n

muestra rat ( ) ; break;

aleatoriamente") ; -

1 ; break;

1 I

void uso comunmouse(int x, int y,int xi,int yi,int xf,int yf){ / * checa-las areas en el que se encuentra el puntero del mouse * / / * y pone el mensaje correspondiente a cada una de las areas dentro de l a * / / * barra de estado * /

if(x>xi & & x<xf & & y>yi & & y<yf) { if(y>yi & & y<yi+35 & & entrouso ! = I l l ) { limpia-barra-uso ( ) ;

entrouso='l'; esconde-rat ( ) ; switch (opc) {

case 1: comunl (xi+20, yi+15, "Predictor", "Estimador") ;

47

modo de Predictor") ; outtextxy(35,45l,"E1 programa se usar en

disco", "Aleatorio") ;

disco") ;

break; default: comunl (xi+20, yi+15, "Leer

outtextxy(35,45l,"Los datos se leeran de

break; 1 muestra-rat ( ) ;

1 if(y>yi+35 & & y<yf & & entrouso ! = '2'){ limpia - barra-uso();

entrouso='2'; esconde-rat ( ) ; switch (opc) {

case 1: comun2 (xi+20, yi+45, "Estimador", "Predictor") ;

modo de Estimador") ; outtextxy(35,457,"El programa se usar en

break; default: comun2 (xi+20, yi+45, "Aleatorio", "Leer

disco") ;

aleatoriamente") ; outtextxy(35,45Il"Los datos se generar n

break; 1 muestra-rat ( ) ;

void rango mouse (int x, int y, int xi, int yi , int xf , int yf) { / * indica en que area nos encontramos cuando pasamos el puntero del mouse * / / * y se halla hecho click, en ese momento cancelamos la entrada nuevamente * /

if(x>xi & & x<xf & & y>yi & & y<yf) { if(y>yi & & y<yi+35) uso=l; else if(y>yi+35 & & y<yf) us0=2;

else uso=0; }else uso=0;

void mueve opcion-uso(int k){ / * checa 1s tecla que se pulso y avanza o retorcede en el cuadro de menu * /

switch (k) { case 18432 : uso--;

case 20480 : uso++;

case 19712 : uso++;

case 19200 : uso--;

break;

break;

break;

break;

48

if (uso < 1) uso=2; if ( u s o > 2) uso=l;

1

void limpia barra-uso(){ / * limpia barra de estado * / setcolor (7) ; o~ttextxy(35~457,"Presione el boton derecho del mouse para salir C

outtextxy(35,457,"El programa se usar en modo de Estimador"); outtextxy(35,457,I7E1 programa se usar en modo de Predictor"); outtextxy(35,457,"Los datos se generar n aleatoriamente"); outtextxy(35,457,"Los datos se leeran de disco");

[ESC] ' I ) ;

void comunl (int x, int y, char *cadl, char *cad2) { / * dibuja la simulacion de un boton selecionado con el cambio de color en las * / / * flechas de seleccion * /

setcolor (BLACK) ; outtextxy(x, y+30, cad2) ;

flecha2 (x+95, y, 15) ; setfillstyle(S0LID FILL,7); / * rellena de gris la no opcion*/ floodfill (x+97, y+35,7) ;

setcolor (WHITE) ; setfillstyle(S0LID FILL,WHITE); outtextxy (x, y, cadli; flecha2 (x+95, y, 15) ; floodfill(x+97,y+5,WHITE); / * dentro del triangulo*/

1

void flecha2 (int x, int y, int color) { / * limpia las flechas para una nueva seleccion * /

setcolor (color) ; line (x, y+4 , x+4 , y) ; line (x, y+4 , x+4 , y+8) ; line (x+4, y, x+4 , y+8) ;

1

void comun2 (int x, int y, char *cadl, char *cad2) { / * lo mismo que comunl, pero en funcion inversa * /

setcolor (BLACK) ; outtextxy(x, y-30, cad2) ;

flecha2 (x+95, y, 15) ; setfillstyle(S0LID FILL,7); / * rellena de gris la no opcion*/ floodfill (x+97, ~ - 2 5 ~ 7 ) ;

setcolor(WH1TE); setfillstyle(S0LID FILL,WHITE); outtextxy(x, y, cadly; flecha2 (x+95, y, 15) ; floodfill(x+97,y+5,WHITE); / * dentro del triangulo*/

1

49

void submenus (int x, int y, int xl, int yl) { / * de acuerdo a la opcion hecha en el menu principal se muestra su submenu * /

ventana-menu (x, y, x1 , yl) ; setcolor (BLACK) ;

switch (opc) { case 1: outtextxy (x+20, y+15, "Predictor") ;

outtextxy(x+20, y+45, "Estimador") ; break;

outtextxy(x+20, y+45, "Aleatorio") ; break;

default: outtextxy(x+20, yt15, "Leer disco") ;

I setcolor(L1GHTBLUE); line (x+20, y+25,x1-20, yl-45) ; line (x+20, y+55, x1-20, yl-15) ; setfillstyle (SOLID FILL, BLUE) ; setcolor (15) ; outtextxy(35,457,"Presione el boton derecho del mouse para salir C

-

[ESC] " ) ; 1

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . FUNCIONES DE CAPTURA PARA ARCHIVOS

/ * * * * * * * * * * * * * * * * * * funcion que pinta la caja de captura . . . . . . . . . . . . . . . . . . . .

void caja(int x, int y, int taml) {

int tamax;

tamax=(taml*8)+5; / * tamano del caja con la holgura * /

/ * * * * * * * * * * * * * cuadro exterior de la caja , de color blanco

/ * tam es el numero de caracteres * /

* * * * * * * * * * * * * * * / setcolor (15) ; line(x-15,y-lO,x+tamax+8,y-l0); line (x-15, y-10, x-15, y+25) ; line(~-15,y+25,x+tamax+8,y+25); line (x+tamax+8, y-10, x+tamax+8, y+25) ;

/ * * * * * * * * * * * * * * efecto hundido de l a caja de captura * * * * * * * * * * * * /

setcolor (WHITE) ; line (x-5, y+15, x+tamax, y+15) ;

50

line (x+tamax, y, x+tamax, y+15) ; setcolor (O) ;

line (x-5, y, xttamax, y) ; line (x-5, y, x-5, y+15) ;

1

void captura(int x,int y,int topelint clr,char "cadena) { int i=O , z=O , k=O , band=l, pos=O, malo=l ; char cad[2] , cad1 [lo01 ; char tecla=O;

caja(x,y, tope) ; / * se pinta la caja de captura * /

setcolor (clr) ; cad[l]='\xO';

setcolor(c1r); / * marca de inicio de captura (cursor) * / line (x+ (lO*i), y+12, x+ (lO*i) +lo, y+l2) ;

/ * mientras no presione <ENTER> * /

while (tecla ! = 13) {

malo=l;

while (malo) { / * mientra tecla no valida * / tecla = getch() ; if (tecla == '\xO' )

tecla=getch ( ) ; else malo = O;

if (((tecla == 8) & & i > O) ) / * si backspace y hay letras * /

i 1";

cad [ O] =cadena [ i] ; cadena [ i] = \x0 ; if (i < (tope-1)) / * borra caracter hacia la izquierda * /

{ / * si no hay recorrido * / setcolor (LIGHTGRAY) ; outtextxy(x+(8*i) ,y+4,cad); line (x+ (8*i) +lo, y+12, x+ (8*i) +20, y+12) ; setcolor (clr) ; line(x+(8*i),y+l2,x+(8*i)+lO,y+lZ);

1

if (i < (tope-1)) { / * si no esta lleno el cuadro de captura" /

if ((tecla >= 48 & & tecla <= 57) 1 1 (tecla >= 97 & & tecla <= 122) I 1 (tecla >= 65 & & tecla <= 90))

t cadena [i] =tecla; / * si letra o numero * /

51

cad [ O] =tecla; outtextxy(x+(8*i),yt4,cad); / * pinta tecla presionada * / setcolor (LIGHTGRAY) ; / * avanza el cursor * / line(x+(8*i),y+l2,~+(8*i)+8,y+12); it+; setcolor (clr) ; line(x+(8*i),ytl2,xt(8*i)+8,ytl2); 1

if ((tecla == 46 I I tecla == 58 1 1 tecla == 92) & & i >= 1 ) i cadena[i]=tecla; / * si ' \ I , l . o : * / cad [ O] =tecla; outtextxy(x+(8*i),y+4,cad); / * pinta tecla presionada * / setcolor (LIGHTGRAY) ; / * y avanza el cursor * / line(x+(8*i),y+l2,xt(8*i)+8,y+l2); i++; setcolor (clr) ; line(x+(8*i),y+l2,~+(8*i)t8,y+12);

1 } / * si tam <= tope*/ else

I / * si cuadro lleno * / / * hacemos efecto de barrido * / if ((tecla >= 48 & & tecla <= 57) 1 I (tecla >= 97

& & tecla <= 122) I I (tecla >= 65 & & tecla <= 90)) I cadena [ i] =tecla; cadena [ i+l] = ' \x0 ; / * si letra o numero * / cad [ O] =tecla;

line(xt(8*(pos-l)),y+12,xt(8*(pos-l))t8,y+l2);*/ i+t; /*setcolor (clr) ; line (x+ (8* (pos-1) ) , y+12, X+ (8* (pos-1) ) +8, yt12) ;

/ * setcolor (LIGHTGRAY) ;

1 if ((tecla == 46 1 I tecla == 58 I I tecla == 92)

* /

& & i >= 1 ) I cadena[i]=tecla; / * si ' \ I , ' . I o ' : I * /

cad [ O] =tecla; setcolor (LIGHTGRAY) ; line(x+(8*(pos-l)),y+12,~+(8*(pos-l))t8,y+l2); i++; setcolor (clr) ; line (x+ (8* (pos-1) ) , y+12, x+ (8* (pos-1) ) +8, y+12) ;

cadena[i+l]='\xO';

1

if (band) { band=O; / * si primera vez de barrido * / pos = 1;

1 else{ / * si hay mas barrido * / setcolor (LIGHTGRAY) ; outtextxy(x,y+4, cadl) ; setcolor (clr) ;

52

* / caja(x,y, tope); / * se pinta la caja de captura

setcolor (clr) ; / * pinta cursor * / ~ine(x+(8*(pos-l)!,y+12,~+(8*(p0~-1))+8,~+12);

/ * copia subcadena a mostrar * /

z=o ;

i for(k=(i-(tope-1) ) ;k <= i; k+t )

cadl [ z] =cadena [ k] ; z++;

1 cad1 [tope] = I \x0 ;

/ * muestra subcadena * / outtextxy (x, y+4, cadl) ;

/ * sonido cuando barre una caracter a la izquierda * / / * sound (1000) ;

delay (200) ; nosound ( ) ; * / }

1 cadena [i] = I\xO'; / * fin de cadena * /

void captura-archivo ( ) { char final [ 301 , cadenal [ 501 ; char band='F'; struct ffblk a; char unidad [ 31 , dir [ 641 , nombrea [ 91 , ext [ 51 ;

esconde-rat ( ) ; enbarra2 (300,250,300,100,7) ; setcolor (O) ; outtextxy(320,270r"Nombre del archivo donde se guar-"); outtext~y(320~280,"dar n l o s calculos hechos por el I r ) ;

outte~txy(320~290," programa : ' I ) ;

while (band=='F') { setcolor (7) ; / * borramos lo anterior escrito * / outtextxy(34Or314,'66666~666666~6~66666666''); outtextxy(340,315, 'I r t ) ; captura (340,310,25, O, cadenal) ;

/ * - splitpath(cadenal,unidad,dir,nombrea,ext);*/

if (strcmp(cadena1,cadfileout) !=O) { / * checamos que no sea enter y que se escriba el nombre del

advertencia ( "Favor de introducir el disco", "en la unidad

if (strcmp(cadenal,"")==O & & strcmp(cadfileout,"") !=O)

archivo * /

correspondiente") ;

band='V' ; / * oprimio enter con opcion * /

53

else if (strcmp (nombrea, " " ) ! =O j

* /

intente con otro") ;

if (findfirst (cadenal, &a, O)==O) / * vemos si existe el file

advertencia ("El nombre del archivo ya se", "encuentra,

else { strcpy(cadfileout,cadenal); / * nueva ruta y file * / band= V ;

1 else advertencia ( 'I Falta nombre del archivo", I r I r ) ;

}else if (strcmp (cadfileout, " " ) ==O) advertencia ("Favor de introducir la ruta", 'I y el nombre

del archivo") ; else {

advertencia ( "Favor de introducir el disco", "en la unidad correspondiente");

band='Vi' ; I

1

barrido (300,250,600,350,l) ; setcolor (5) ; outtextxy(357,85, final) ;

setcolor (14 ) ; strcpy (final, " " ) ; strncpy(final,cadfileout,29); outtextxy(357,85, final) ; muestra-rat ( ) ;

1

void captura archivo2(){ / * usamos una cadena temporal (cadtemp) para guardar el contenido * / / * de las variables globales cadfilein-, para que estas no cambien * /

char unidad [ 31 , dir [ 641 , nombrea [ 91 , ext [ 51 ; char cadenal [5O], final E301 , cadtemp[50] ; char band='F'; struct ffblk a;

strcpy (cadenal, ' r r f ) ; strcpy(fina1,1'6666666666666666666666666666611);

esconde rat ( ) ; enbarra2(350,250,250,85,7) ; / * muestra el cuadro de dialogo

setcolor (O) ; outtextxy(370,270, "Nombre del archivo donde se") ; outtextxy(370,280, tomar n los datos: " ) ;

switch (opc) { / * inicializa la cadena temporal * /

* /

case 2: strcpy(cadtemp,cadfileinA); break; case 3: strcpy(cadtemp,cadfileinX); break; case 4: strcpy(cadtemp,cadfileinD); break;

1

while (band=='F') { setcolor (7) ; / * limpia la zona de escritura * / outtextxy (380,304, "66686666666666606660066") ;

54

outtextxy(380,305, IT ) ; captura (380,300,25, O, cadenal) ;

/ * - splitpath (cadenal, unidad,dir, nombrea, ext) ; * /

if (strcmp (cadenal, cadtemp) ! =O) { / * checamos que no sea enter y que se escriba el nombre del

advertencia ( "Favor de introducir el disco", "en la unidad

if (strcmp (cadenal, "")==O & & strcmp(cadfileinA, " " ) !=O)

else if (strcmp(nombrea, " " ) !=O)

archivo * /

correspondiente") ;

band='V' ; / * oprimio enter con opcion * /

if (findfirst (cadenal, &a, O) !=O) / * vemos si existe el file * /

intente otra vez") ; advertencia ("El nombre del archivo no se", "encuentra,

else { strcpy(cadtemp,cadenal); / * nueva ruta y file * / band='V' ;

1 else advertencia ( " Falta nombre del archivo", 1 ' 7 1 ) ;

}else if (strcmp(cadtemp, "")==O) advertencia("Favor de introducir la ruta"," y el nombre

del archivo") ; else {

advertencia ( "Favor de introducir el disco", "en la unidad correspondiente");

band= V : 1

I

captura muestras(); / * muestra la captura del numero de muestras * /

-

switch(opc){ / * guardamos en las variables globales 10 nuevo * / case 2: strcpy(cadfileinA,cadtemp);

case 3: strcpy(cadfileinX,cadtemp);

case 4: strcpy(cadfileinD,cadtemp);

StrCpy (NUMA, NUMTEMP) ; break;

StrCpy (NUMX, NUMTEMP) ; break;

StrCpy (NUMD, NUMTEMP) ; break; 1

barrido(350,250,600,375,1); / * cierra el dialogo * / switch (opc) { / * aparece los nuevos requerimientos * /

case 2: setcolor (5) ; outtextxy(357,100,final); outtextxy(357,115, final); setcolor (14 ) ; strcpy(fina1, r r r l ) ; strncpy(fina1, cadfileinA, 29) ; outtextxy(357,100,final); outtextxy(357,115,NUMA); break;

setcolor (5) ; outtextxy(357,13O,final); outtextxy(357,145, final) ; setcolor (14) ; strcpy(fina1, " " ) ; strncpy(fina1, cadfileinx, 29) ;

case 3:

55

outtextxy(357,13OIfinal); outtextxy (357 I 145 I NUMX) ; break;

setcolor (5) ; outtextxy(357,160,final); outtextxy(357,175,final); setcolor (14) ; strcpy (final I " I 1 ) ; strncpy(final,cadfileinD, 29) ; outtextxy(357,160,final); outtextxy (357 I 17 5 I NUMD) ; break;

case 4:

1 muestra-rat ( ) ;

void capturamuestras(){ char band='F'; register int k;

enbarra2 (350,337,250,31,7) ; setcolor (O) ; outtextxy(360,348, "Numero de muestras:");

while (band==' F' ) { setcolor (7) ; / * limpiamos el area de captura * / outtextxy(549,351, "6666") ; outtextxy(549,352,"- I t ) ;

captura(549,347,4,OINUMTEMP) ; k=atoi (NUMTEMP) ; if (k!=O) band='V';

1 1

void captura-aleatorios0 {

capturamuestras ( 1 ; barrido (350,337,600,375,1) ; switch (opc) {

case 2: setcolor (5) ; outtextxy(357,115,final); setcolor (14) ; strcpy (NUMA, NUMTEMP) ; outtextxy(357,115,NUMA); break;

setcolor (5) ; outtextxy(357,145,final); setcolor (14) ; strcpy(NUMX, NUMTEMP) ; outtextxy (357 I 145 I NUMX) ; break;

setcolor (5) ; outtextxy(357,175,final) ; setcolor (14) ;

case 3:

case 4:

56

strcpy (NUMD, NUMTEMP) ; o~ttextxy(357~175,NUMD) ; break;

void advertencia(char *cadl,char *cad2){ void *parte;

sound (2000) ; delay (200) ; nosound ( ) ; guarda - imagen (190,190,470,290, &parte) ;

setcolor (12) ; rectangle (200,200,450,260) ; setfillstyle (SOLID FILL, 4) ; floodfill (300,240,¡2) ;

setcolor (8) ; rectangle (210,261,452,270) ; setfillstyle (SOLID FILL, O) ; floodfill (300,265,8) ; rectangle (451,210,460,270) ; setfillstyle (SOLID FILL, 0) ; floodfill (454,265,8) ;

setcolor (10) ; outtextxy(218,210, cadl) ; outtextxy(218,220,cad2); setcolor (15) ;

/ * zona de escritura * /

/ * sombras * /

/ * mensaje * /

outtextxy(247,240, "Pulse cualquier tecla") ; getch ( ) ; putimage (190,19O,parte, 0) ; free (parte) ;

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . . . FUNCIONES P A M LA SALIDA

void salida entrada0 { / * funcion principal del cuadro de salida * / int edo=O, tecla=O, x, y; void *pa;

uso=l; sound(2000) ; delay(200); nosound(); esconde-rat ( ) ; guarda imagen(240,190,460, 290, &pa) ; enbarra2 (250,200,200, 80,7) ; setcolor (0) ; outtextxy(278,218,"Desea salir ahora?"); barra (270,240,72,20) ; barra(358,240,72,20); setcolor (15) ;

57

outtextxy(279,247, "Aceptar") ; setcolor (8 ) ; outtextxy(364,247, "Cancelar") ; muestra-rat ( ) ;

while(edo!=2 & & tecla ! = 283) { edo=O; tecla=O; reporta-edo (&x, &yI &edo) ;

if(edo==l I I bioskey(l)){ / * si se hizo un click izq o un enter * /

if (bioskey (1) ) tecla=bioskey (O) ; if (tecla!=7181) { mueve opcion-uso(tec1a);

if(tecla==19200 1 1 tecla==18432){ setcolor (8 ) ; outtextxy (364 , 247 , "Cancelar") ; setcolor (15) ; outtextxy(279,247, "Aceptar");

setcolor (8) ; outtextxy(279,247, "Aceptar") ; setcolor (15) ; outtextxy (364 , 247 , "Cancelar") ; 1

}else if(tecla==l9712 I I tecla==20480){

1

rango-mouse horizontal(x,y); if ( edo==l ) / * si es un click * /

if ((tecla == 1181 1 1 edo==l))

case 1: switch (uso) {

free (pa) ; cortina ( ) ; closegraph ( ) ; restorecrtmode ( ) ; exit (1) ; break;

case 2: edo=2; break;

1

} / * enddo * / esconde-rat ( ) ; putimage(240,190,pa, O) ; free (pa) ; muestra-rat ( ) ;

1

void rango mouse-horizontal(int x,int y ) { / * indica en que area nos encontramos cuando pasamos el puntero del mouse * / / * y se halla hecho click, en ese momento cancelamos la entrada nuevamente * /

if(x>270 & & x<342 & & y>240 & & y<260)

else if(x>358 & & x<430 & & y>240 & & y<260) uso=l;

us0=2 ; else uso=O;

58

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * / . . . . . . . . . . . . . . . . . . . . . . . . . . PANTALLA PARA LOS INTEGRANTES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

void integrantes ( ) {

enbarra2 (200,215,300,200,2) ; setcolor (15) ; outtextxy(215,235,"UNIVERSIDAD AUTONOMA METROPOLITANA"); outtextxy(215,245, 'I I Z TAPALAPA" ) ; setcolor (O) ; outtextxy(246,280, "Profesor asesor de proyecto") ; outtextxy(247,280, "Profesor asesor de proyecto") ; outtextxy(255,290, "Doctor H,ctor P,rez Meana") ; outtextxy(300,315, "Programadores") ; outtextxy (301,315, "Programadores") ; outtextxy (260,355, "Lic. Cruz Quirazco Raul") ; outtextxy(215,335,"Lic. Lozano Becerril Ricardo C,sar"); outtextxy(243,345, "Lic. Maldonado Muaoz Rogelio") ; outtextxy (250,325, "Lic. S nchez Arroyo Adriana") ; setcolor (15) ; outtextxy(263,390, "Pulse cualquier tecla") ; getch ( ) ; barrido (200,215,600,415,l) ;

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . DECORADOS DE PANTALLA Y AMBIENTE

void guarda imagen (int xl, int yl, int x2 , int y2, void **imagen) { unsigned int size;

size = imagesize (xl, yl, x2, y2) ; *imagen = malloc(size);

if ("imagen ! = NULL)

else { getimage (xl, yl, x2, y2, *imagen) ;

setcolor (4) ; sound(1000); delay(100); nosound(); outtextxy(35,457,"No hay suficiente memoria. Pulse una tecla."); getch ( ) ; exit (1) ; 1

59

void boton(int x, int y, char *cadena, int clr) / * boton normal * / I void *dibujo;

esconde rat ( ) ; guarda ~magen(30,40,93,70, &dibujo) ; putimage (x-10, y-10, dibujo, O) ; free (dibujo) ; setcolor ( W H I T E ) ; arc (x, y, 90,230,lO) ; line (x, y-10, x+40, y-10) ; setcolor (DARKGRAY) ; arc(x+40, y, 270,90,10) ; arc(x+41, y, 270, 90,lO) ; arc(x, y, 230,270,lO) ; line (x, y+10, x+40, y+lO) ;

/ * flecha*/ line (x+35, y-3, x+39, y+4) ; line (x+35, y-3, x+42, y-3) ; line (x+39, y+4, x+42, y-3) ; setfillstyle ( S O L I D - F I L L , clr) ; floodfill (x+39, y, 8) ; setcolor ( W H I T E ) ;

/*flecha*/ line (x+39, yt4, x+42, y - 3 ) ; arc (x+40,y, 50,90,10) ; setcolor (O) ; outtextxy(x, y-3, cadena) ; muestra-rat ( ) ;

1

void boton - press(int x,int y,char *cadena,int clr){ / * boton presionado * /

esconde-rat ( ) ; setcolor (LIGHTGRAY) ;

/ * flecha*/ line(x+35,y-3,~+39,y+4); line (x+35, y-3,x+42, y-3) ; line (x+39, y+4 , x+42 , y-3) ; setcolor (DARKGRAY) ; arc(x, y, 90,270,lO) ; line (x, y-10, x+40, y-10) ; arc (xt40, y, 270, 90,lO) ; arc(x+41, y, 270,90,10) ; line (x, yt10, x+40, y+lO) ; setfillstyle ( S O L I D F I L L , L I G H T G R A Y ) ; floodfill (x, y, DARKGRAY) ;

/ * flecha*/ line (x+35, y-3, x+39, y+4) ; line (xt35, y-3,x+42,y-3) ; line (x+39, y+4,x+42, y-3) ; setfillstyle (SOLID - F I L L , clr) ; floodfill (x+39, y, 8) ; setcoior ( L I G H T G W Y ) ; arc (x, y, 90,270,10) ;

60

line (x, y-10, x+40, y-10) ; arc(x+40, y, 270,90,10) ; arc (x+41, y, 270,90,10) ; line (x, y+10, x+40, y+10) ; setcolor (WHITE) ; line (x-1, y+10, x+40, y+10) ; arc (x+42, y, 270,70,10) ; setcolor(DARKGRAY); arc (x+2, y, 90,270,lO) ; line (xt2, y-10, x+45, y-10) ; arc (x+42, y, 60,90,10) ; setcolor (WHITE) ;

arc (x+2, y, 230,270,lO) ;

/ * setcolor (DARKGRAY) ; line (x-1, y+8, x+40, y+8) ; arc (x+42, y, 270,70,8) ; arc (x+2, y, 90,270,8) ; line(x+2,y-8,~+45,y-8);*/

setcolor ( 8 ) ; outtextxy(x+2,y-3,cadena); muestra rat ( ) ; -

}

void boton circ(int x,int y){ setcolor(DARKGRAY); circle (x, y, 10) ; arc(x+l, y, 270, 90,lO) ; line (x-2 , y-3 , x-2 , y+4 ) ; line (x-2, y-3, x+3, y+l) ; setcolor (WHITE) ;

/ * circulo * / line(x-2,y+4,x+3,y+l); arc(x, y, 90,180, 9) ;

1

void fondo() { setfillstyle (SOLID FILL, 7) ; floodfill (10,10,7)7

void esq-sup-izq(int x, int y){ setcolor (15) ; line (x, y, x+10, y) ; line (x, y, x, y+lO) ; setcolor (DARKGRAY) ; line (x, y+10, xt3, y+10) ; line (x+lO, y, x+10, y+3) ; line (x+lO, yt3, x+3, y+3) ; line (x+3, y+3, x+3, y+10) ;

I

void esq-sup-der (int x, int y) {

line (x, y, x-10, y) ; line (x, y, x, y+lO) ; setcolor (DARKGRAY) ;

setcolor(WH1TE);

61

llne line line line

1

(x-1Oryrx-1Ory+3); (x, ytlO, x-3, y+10) ; (x-3,y+3,x-lO,y+3); (x-3, y+3, x-3, y+10) ;

void esq inf izq(int x, int y) i setcolor (WHITE) ; line (x, y, x, y-10) ; line (x, y, x+lO, y) ; setcolor (DARKGRAY) ; line (x, y-10, x+3, y-10) ; line (x+10, y,x+lO,y-3) ; line (x+3, y-3,x+3,y-10) ; line (x+lO, y-3, x+3, y-3) ;

1

void esq-inf der(int x,int y){ setcolor (WHITE) ; line (x, y, x, y-10) ;

line (x, y, x-10, y) ; setcolor(DARKGRAY); line (x-10, y, x-10, y-3) ; line (x, y-10, x-3, y-10) ; line (x-3, y-3, x-10, y-3) ; line (x-3, y-3, x-3, y-10) ;

1

void lineas ( ) { setcolor (15) ; line (20,459, 620,459) ; line (629,450,629,71) ; line (20,21, 620,21) ; line (11,71,11,450) ;

setcolor (O) ; line (20,22,620,22) ; line (12,51,12,430) ; line (20,438,620,438) ; line (628,430,628,51) ;

void cuadro2 ( ) { setcolor (15) ; outtextxy(480,410, "Abortar <ESC>") ;

setcolor (15) ; / * cuadro de la pantalla * / line (305,75,595,75) ; line (305,75,305,395) ;

line (305,395,595,395) ; line (595,395,595,75) ;

/ * cuadro de la pantalla * /

62

void barrido (int xi, int yi, int xf, int yf, int color) { register int i, j, w, z;

w= ( (yf-yi) /2) +yi; z=yf+yi+4;

for(j=yi; j<=wt4; j++) for(i=xi; i<=xf+4; i++){ / * el 4 es la agregacion para la * /

putpixel (i, j , color) ; / * sombra * / putpixel (i, z- j , color) ;

void cuadro3 ( ) { / * cuadro para el RUN * / setcolor (O) ;

line (450,80,590,80) ; line (450,80,450,390) ; line (450,390,590,390) ; line (590,390,590,80) ; setfillstyle (SOLID FILL, 3) ; floodfill (480,81,07;

/ * cuadro interno de pantalla negra * /

1

void mensaje ( ) { setfillstyle (SOLID - FILL,LIGHTBLUE) ; setcolor (15) ; line (30,80,90,80) ; line (90,80,90,100) ; line (90,100,30,100) ; line (30,80,30,100) ; floodfill (41,81,15) ; setcolor (10) ; outtextxy(35,88, "OPCION") ;

void ventana menu (int xi, int yi, int xf, int yf) { setcolor(WH1TE); arc (xi+lO, yi+lO, 90,180,lO) ; arc (xi+lO, yf-l0,180,270,10) ; line (xi, yi+lO, xi, yf-10) ; line (xi+lO, yi, xf+13, yi) ; arc (xf+lO, yf-l0,270,360,10) ; arc (xf+lO, yi+lO, 360,70,10) ; line(xi+8,yf,xftlO,yf); line(xf+20,yi+10,xf+20,yf-l0); setfillstyle(SOL1D FILL,7); floodfill(xi+lO,yiT10,15); setcolor (DARKGRAY) ; arc (xf+lO, yf-l0,270,360,10) ; arc (xf+lO, yi+lO, 360,70,10) ; line(xit8,yf,xf+lO,yf); line (xf+20, yi+lO, xf+20, yf-10) ; setcolor (11) ; / * sombra * / arc (xf+ll, yf-9,270,360,10) ;

63

line (xi+8, yf+l,xf+lO, yf+l) ; line (xf+21, yi+lO, xf+21, yf-10) ; arc(xf+l2, yf-8,270,360,lO) ; line (xi+9, yf+2,xf+10ryf+2) ; line (xf+22, yi+ll, xf+22, yf-10) ;

1

void barra(int x,int y,int anch,int alt){ setcolor (8) ;

line (x, y, x+anch, y) ;

line (x+l, y+alt,x+anch, y+alt) ; line(x+anch,y+l,x+anch,y+alt); setfillstyle(SOL1D F I L L , 7) ; floodfill (x+5,y+5,8) ;

line (x, y, x, y+alt) ;

setcolor(WH1TE); line (x, y, x+anch, y) ; line (x, y, x, y+alt) ; setcolor (O) ; line (x, y+alt+l, x+anch+l, y+alt+l) ; line (x+anch+l, y, x+anch+l, ytalt+l) ;

1

void enbarra2(int x,int y,int anch,int alt,int fondo) {

line (x, y, xtanch, y) ;

line (x+l, y+alt, x+anch, y+alt) ; line(x+anch,y+l,x+anch,y+alt); setfillstyle (SOLID F I L L , fondo) ; floodfill (x+5, y+5,8) ;

setcolor (8) ;

line (x, y, x, y+alt) ;

setcolor (WHITE) ; line (x, y, x+anch, y) ; line (x, y, x, y+alt) ; setcolor ( 4 ) ; / * marco color rojo * / line (x+5 , y+5 , x+anch-5 , y+5) ; line (x+5 , y+5 , x+5 , y+alt-5) ; line(x+5,y+alt-5,x+anch-5,y+alt-5); line(x+anch-5,y+5,x+anch-

setcolor (O) ; line (x, y+alt+l, x+anch+l, y+alt+l) ; line (x+anch+l, y,x+anch+l, y+alt+l) ; setcolor (11) ; / * sombra color cyan claro * / line(x+2,y+alt+2,x+anch+2,y+alt+2); line(x+anch+2,y+2,x+anch+2,y+alt+2); line(x+2,y+alt+3,x+anch+2,y+alt+3); line(x+anch+3,y+2,x+anch+3~y+alt+2);

5, y+alt-5) ;

i

/ * barra hundida con color * / void barra1 (int x, int y, int anch, int alt, int clr) {

setcolor(c1r); / * inicialmente era blanco para el fondo * / line (x, y, x+anch, y) ; line (x, y, x, y+alt) ; line (x, y+alt , x+anch, y+alt) ; line (x+anch, y,x+anch, y+alt) ; setfillstyle (SOLID F I L L , clr) ; floodfill (x+l, y+1,6) ;

64

/ * setcolor(DARKGRAY); line (x , y, x+anch , y) ; line (x, y, x, y+alt) ; * /

i

void barra2 (int x, int y, int anch, int alt) { setcolor (WHITE) ; line (x, y+alt, x+anch, y+alt) ; line (x+anch, y, x+anch, y+alt) ; setcolor (O) ;

line (x, y, x, y+alt) ; line (x, y, x+anch, y) ;

I

void titulo ( ) { barra (10 , 5 , 24 , 22) ; barra2 (16,15,12,3) ; / * barrita de cierre de pantalla * / barra(36,5,565,22) ; barra(603,5,19,22) ; / * boton de ? * / barra1 (40,8,556,16,6) ; barra(618,30, 4,390) ;

settextstyle (1, O, 1) ; setcolor (O) ; outtextxy(l97,4,"F i 1 t r o d e K a 1 m a n"); outtextxy(610,4, " ? " ) ; setcolor (15) ; outtextxy(l99,4 , "F i 1 t r o d e K a 1 m a n") ; settextstyle (O, O, O) ;

barra(553,422,69,50); / * barra para el logo * /

1

void cuadmen ( ) { setcolor (8 ) ; line (10,472,500,472) ; line (500,472,500,449) ; line (501,473,501, 451) ;

line (10,473,501,473) ; line(l2,474,502,474);

line (502,474,502,451) ;

setcolor (15) ; line(lO,450,499, 450) ; line (10,472,10,450) ; settextstyle (1 , O, 1) ; setcolor (0) ;

outtextxY(l20f425I"PPPPPPPPPPPPPPP~PPPPP~P~~PPPPPPPPPPPPPPPPPPPPPPPPPPPPP PPPPPPP" ) ;

outtextxy(508,443, "UAM"); outtextxy(509,443, "UAM"); outtextxy(506,455, "PPPPPP ' I ) ; setcolor (2) ; settextstyle (2, O, 0) ; outtextxy(559,456, "Iztapalapa") ; outtextxy(558,456, "Iztapalapa") ; setcolor (8 ) ; outtextxy(560,456, "Iztapalapa") ; settextstyle (O , 0 , 0) ;

1

65

void fondo-azul ( ) { register int a;

setcolor (O) ; rectangle (121,45,609,430) ; setfillstyle (SOLID FILL, 1) ; floodfill (200,200,0) ;

setcolor (15) ; line (120,431,610,431) ; line(610,44,610,431) ; / * lineas de marco

line (120,430,610,430) ; line (609,44,609,431) ; / * fondo azul * / del * /

setcolor (12) ; / * fondo magenta * / rectangle(130,60,600,190); / * marco del fondo magenta * / setfillstyle (SOLID FILL, 5) ; floodfill (140,100,¡2) ; a=140; setcolor (3) ; outtextxy(a, 70, "Programa usado como: " ) ; outtextxy(a, 85, "Destino del archivo final:") ; outtextxy (a, 100, "Toma de los datos A: ' I ) ; outtextxy(a, 115, "Numero de muestras a tomar: ' I ) ; outtextxy(a, 130, "Toma de los datos X:") ; outtextxy(a, 145,"N€mero de muestras a tomar:"); outtextxy(a, 160, "Toma de los datos D:") ; outtextxy(a, 175, "N€mero de muestras a tomar:") ; restablece ( ) ;

1

void restablece ( ) { register int a;

a=357; setcolor(l4); outtextxy(a, 70,"P r e d i c t o r"); outtextxy(a, 100, "Aleatorio") ; outtextxy(a, 115, "25") ; outtextxy(a, 130, "Aleatorio") ; outtextxy(a, 145, "25") ; outtextxy(a, 160, "Lectura de disco") ; outtextxy(a, 175, "25") ;

boton(40,170,"A1~,7); boton (40,250, "D", 7) ; sound(2200); delay(100); sound (2500) ; delay (100) ;

Al=' 0 ; DI= 10 1 ;

nosound ( ) ;

void ini graf ( ) { int control, modo; control = VGA; modo = VGAHI; initgraph (&control, &modo, '"') ;

1

66

# include <globales.h>

int q; / * contiene la tecla pulsada para la interrupcion * / char aborta='€'; / * bandera de abortar los c lculos * /

. . . . . . . . . . . . . . . . . . . . . . SIMBQLOGIA . . . . . . . . . . . . . . . . . . . . . . . . . . . / * Q=Q(n); Ql=Q(n-l); XK=X(n); XKT=X(n)Transpuesta; HK=W(n) * / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

void inicializa(void) I

register int i,j;

f o r (i=O; i<tam; i++) { XK[i]=O.O; HK[i]=O.O; senal-Y [ i ] =O. O ; sena1 D [ i] =O. O; A[i]=Z.O;

1 for (i=O; i<tam; it+) for(j=O; j<tam; j++) t if (i==j) { Q[i] [j]=lOO.O; Ql[i] [j]=lOO.O;

Q[i] [j]=O.O; Ql[i] [j]=O.O;

} else {

1 1

1

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * / . . . . . . . . . . . . . . . . . . . . . . . . Filtro de KALMAN * * * * * * * * * x * * * * * * * * * * * * * * * * / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

void KALMAN (void)

register int i,j; double suma,result,lambda=0.999; double S [tam] , KG [tam] ; /*KG = a la ganancia de Kalman * /

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * /

67

for (i=O; i<N; i++) f o r (j=O; j < N ; j++) Q1 [il [jl=Q[il [I1 ;

/ * toma de la vieja Q * * * * * * * /

Y2=0. o ;

for (i=O; i<N; i++) Y2=Y2+ (HK[i] *XK[i] ) ;

error= Y3 - Y2;

. . . . . . . . . . . . . . . . . . . . (X(n)trans*Q(n-l)*X(n))tlambda * * * * * * * * * * * x * * * * * * * * * * * /

for (i=O; i<N; i++) { suma=O . O; for ( j = O ; j<N; j++)

S [i] =suma; suma=suma+(XK[j]*Ql[j] [il);

1 suma=O. O ; for (i=O; i<N; i++)

result=sumatlambda; suma=suma+ (XK[i] *S [i] ) ;

for(i=O; i<N; it+) i suma=O . O ; for ( j = O ; j<N; j++)

KG [i] =suma/result; suma=suma+(Ql[il [jl*XK[jl);

/ * Q(n-l)X(n) * /

/ * * * * * * * * * * * * * * * * * * Adaptacien de vector de coeficientes x * * * * * * * * * * * * * * * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . W(*)=W(n-l)+K(n)*error

for(i=O; i<N; i++) HK[i]= HK[i]+(KG[i]*error);

. . . . . . . . . . . . . . . . . . . . Calculo del vector Q(n)

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / * * * * * * * * * * * * * * * * Q(n)=[Q(n-1) -K(n)X(n) transQ(n-1) ] /lambda * * * * * * * * * * * * * * * * * /

for(i=O; i<N; i++) f o r ( j = O ; j < N ; j++) Q[i] [j]=(Ql[i] [jl-(KG[il*S[jl)) /lambda;

68

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . Calculo del Vector XK

* * * * /

void vector XK(doub1e nvoval) { register int i;

for (i=O; i<NumElem; i++) / * recorremos * / XK[NumElem-i] = XK[NumElem-i-11 ;

XK [O] =nvoval; / * generamos numero aleatorio*/

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

. . . . . . . . . . . . . . . . . . . . . . . . . . Calculo del vector A

void vector - A(void) {

A[O]= 7.785205408500e-02; A[ 11 = 3.965393194820e-01; A[2] = 7.291320908460e-01; A [ 3 ] = 4.697822874050e-01; A[4]=-1.439060039290e-01; A[5]=-2.240361849940e-01; A[6]= 7.130921926700e-02; A[7]= 8.061260915100e-02; A [ 8 ] = - 3 . 8 0 2 9 9 3 6 9 3 5 0 0 e - O 2 ; A [ 9 ] = - 1 . 6 5 7 4 5 4 1 6 3 1 0 0 e - 0 2 ; A[10]=1.255099855600e-O2; A[11]=4.295779730000e-O4; A[12]=-1.80164070400Oe-O3; A[13]=3.537138000000e-O4; / * El resto del Vector A no varia * /

1

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Calculamos el error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

/*Error ( ) t

69

register int i; D=O. O;

for(i=O; i<N; i++) D=D+ (A[i] *XK[i] ) ; error=D-Y; i * /

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Principal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * /

void proyecto (void) { double xl=0,x2=OIpot sig,pot-err,pot-noise,mse; long stime; int seed, i, j , k;

-

inicializa ( ) ; vector - A ( ) ;

time (&stime) ; seed=stime%lOO; srand (seed) ;

f o r (i=O; i<NumBlock; i++) I

pot sig=O.O; potIerr=0.0; pot noise=0.0; forTj=O; j<NumIter; j++) t

/ * se generan numero aleatorios * /

xl=(double)rand()/(double)RAND MAX-0.5; / * x nuevo * / x 2 = ( d o u b l e ) r a n d ( ) / ( d o u b l e ) R A N D - " 0 . 5 ; / * ruido nuevo*/ -

vector - XK(x1) ;

D=O. O; f o r (k=O; k<NumElem; k + + ) D=D+ (A[k] *XK[k] ) ;

Y3 = D + x2; KALMAN ( ) ;

pot-err+=(D-Y2) * (D-Y2) ; pot-sig+= (D*D) ; pot-noise+= (Y3-D) * (Y3-D) ;

if ( j = = O ) {

70

setcolor (O) ; delay (5) ; outtextxy(400,457, l r o l r ) ;

outtextxy(408,457, l v o v v ) ;

delay (2 ) ; outtextxy(416,457, ; delay(2) ; outtextxy(424,457, ; delay (2) ; outtextxy (432 I 457, l ' k l v ) ; delay (2) ; outtextxy(440,457, l ' + l ' ) ;

delay(2); outtextxy(448,457,'vkv1); delay (2) ; outtextxy(456,457, v l k v l ) ; delay (2) ; outtextxy(464,457, v v z l v ) ; delay (2) ; outtextxy(472,457,vv2"); delay(2) ; outtextxy(480,457, l l z ' l ) ;

outtextxy(488,457, v l z l ' ) ;

delay (2) ;

delay(2);

if (bioskey(1) ) I q=bioskey (O) ; if (q==283) goto el;

I

mse=pot-err/pot-sig; /*snr=pot - sig/pot - noise;*/ arr [ i] =mse ; setcolor (15) ; delay (5) ; outtextxy(400,457, " o ' 1 ) ;

outtextxy(408, 457,1'0"); delay(2); outtextxy(416,457, v v o ' l ) ; delay (2) ; outtextxy(424,457, ""') ; delay(2) ; outtextxy(432,457, " k v l ) ; delay (2) ; outtextxy(440,457,"krv) ; delay(2); outtextxy(448,457, l l + ' v ) ; delay (2) ; outtextxy (456,457 I " k T v ) ; delay(2); outtextxy(464, 457,'12v1); delay(2) ; outtextxy(472,457, I v Z v 1 ) ; delay (2) ; outtextxy(480,457, l v * l v ) ;

delay(2);

delay (2) ;

71

/ * outtextxy(488,457, 1'21') ;

delay (50) ; * / printf ( 'I %d %If \n", i,mse) ;

if (bioskey(1) ) I q=bios key ( O ) ; if (q==283) goto el;

1 i el : fuera ( ) ; 1 / * €in del principal * /

void fuera ( ) { if (q==283) { setcolor (7) ; outtextxy(40,457,"Realizando c lculos de Kalman"); outtextxy(500,457,"!Trabajando-"); outtextxy(400,457,"oooo++++2222rr "" ) ; aborta='t';} 1

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * * / / * * * * * Muestra en pantalla el error cuadr tico del filtro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * * * * * /

void correr() { int i, k, ini, z, v, band=0;

double cuadr; char *cad=" ", *cadi=" *

/ * cuadro2(); borde de la pantalla * / / * cuadro3(); relleno negro de la pantalla * / settextstyle (DEFAULT FONT, HORIZ DIR, 1) ; setcolor (14 ) ; outtextxy(370,350, "Espere un momento.. . . . ' I ) ; setcolor (15) ;

/ * outtextxy(40,457, "Realizando c lculos de Kalman") ; outtextxy(500,457,"!Trabajando-");*/ proyecto ( ) ;

- -

if (aborta=='t') { aborta='f'; goto e2; }

setcolor (1) ; outtextxy(370,350,"Espere un momento.. . . . I 1 ) ;

setcolor (7) ; outtextxy(40,457,"Realizando c lculos de Kalman"); outtextxy(400,457,"oooott++2222"); ""

outtextxy(500,457, "!Trabajando-") ; setcolor (14 ) ; outtextxy (450,90, "Error Cuadratico") ; setcolor (15) ; outtextxy(40,457,"Muestra del contenido final del archivo");

for (v=0; v<= 150; v++) i putpixel (300-v, 230, WHITE) ;

72

putpixel (3OO+v, 230, WHITE ) ; delay(l0);

1

for (v=O; v<= 80; v++) I putpixel (150,23O+v, WHITE) ; putpixel (450,23O+v, WHITE ) ; delay (10) ;

1

for (v=O; v<= 150; v++)

putpixel (15O+v, 310,WHITE) ; putpixel (45O-v, 310, WHITE ) ; delay (10) ;

1

setfillstyle (SOLID FILL, DARKGRAY) ; floodfi11(300,250,~HITE); band=l;

for (k=O; k<=50; k++ ) I setcolor(L1GHTGREEN); ini=k; z=1;

for (i=ini; i<= (ini+2) ; i++ ) I

Z + + ;

cuadr = arr [i] *arr [i] ; gcvt (k+z, 5, cadl) ; outtextxy(170,250+(z*lO),cadl); gcvt (arr [ i] ,5, cad) ; gcvt ( cuadr, 5, cadl ) ; outtextxy(350,250+ (z*lO), cadl) ; outtextxy (230,250+ (z*lO), cad) ;

/ * cuadr= arr[(ini+20)-z]*arr[(ini+20)-~]; gcvt (arr [ (ini+20) -z] ,5, cad) ; gcvt (cuadr, 5, cadl) ; outtextxy(470,320- (z*lO), cad) ;

outtextxy(460,320-(z*lO),cadl);

if (bioskey(1)) { q=bios key ( O ) ; if (q==283) goto e2;

1 * /

1 delay (100) ;

if(k == 80 ) { setcolor (7) ;

outtextxy(40,457,"Muestra del contenido final del archivo"); setcolor (15) ; outtextxy (450,350, "Presione una tecla") ;

73

/ * outtextxy(40,457,"-Proceso terminado! . . . . , los resultados estan listos en el archivo");*/

getch ( ) ; setcolor (7) ;

/ * outtextxy(40,457,"-Proceso terminado! . . . . , los resultados estan listos en el archivo");*/

setcolor (3) ; outtextxy (450,350, "Presione una tecla") ; outtextxy(450,90, "Error Cuadratico") ;

1

setcolor (DARKGRAY) ;

for (i=ini; i<= (ini+2) ; i++ ) z=1;

i

Z++; gcvt (k+z,5,cadl);

outtextxy(170,250+(z*lO),cadl); cuadr = arr [i] *arr [ i] ; gcvt (arr [i] ,5, cad) ; gcvt (cuadr, 5, cadl) ; outtextxy (350,250+ (z*lO), cadl) ; outtextxy (230,250+ (z*lO), cad) ;

/ * cuadr= arr[(ini+20)-z]*arr[(ini+20)-~]; gcvt (arr [ (ini+20) -z] ,5, cad) ; gcvt (cuadr, 5, cadl) ;

outtextxy(470,320-(z*lO),cad); outtextxy(460,320-(z*lO),cadl);*/

I if (bioskey (1) ) {

q=bios key ( O ) ; if (q==283) goto e2;

I

I for (v=O; v<= 150; v++)

t putpixel (3OO-v, 230, WHITE) ; putpixel (3OO+v, 230, WHITE ) ; delay (10) ;

}

e2: aborta=' f ;

if (band) {

setfillstyle (SOLID FILL,BLUE) ; floodfill (300,250,WHITE) ;

for (v=O; v<= 150; v++) t putpixel (~OO-V, 230, BLUE) ; putpixel (3OO+v, 230, BLUE ) ; delay (10) ;

1

for (v=0; v<= 80; v++)

i putpixel (150,23O+v, BLUE) ; putpixel (450,23O+v, BLUE ) ; delay(l0);

1

for (v=O; v<= 150; v+t) I putpixel (15O+v, 310, BLUE) ; putpixel (45O-v, 310, BLUE ) ; delay (10) ;

1

} / * fin de if (band) * / setcolor (7) ; outtextxy(40,457,"Muestra del contenido final del archivo");

/*restablecer();*/

75

# include <graficos.h > # include "direct.h"

void mainO{

clrscro; /*hacer instalacion0; ini graf0; poi-tadao; closegrapho; /* cierra los graficos para que se restablescan los */ ¡ni grafO; inicializa cadenaso; menuo; 1

-

void hacer instalaciono { struct ffblk fp; register int fin;

-

if(findfirst("c:\\KALMAN",&fp,FA-DIREC)! =O) {

I* printf("lnstalacion terminada.......");*/ 1

1

system("a:\instalar.bat");

inicialo;

76

[I I

[21

131

141

[51

161

[71

[81

191

[I 01

[Ill

[I 21

11 31

[I 41

w. Lucky, “Automatic Equalization for Digital Communication”, Bell Sys. Tech, J.,

April, 1995, pp 547-588

Cersho, “Adaptive Ecualization of Highly Dispersive Channels for Data

Transmission”, Bell Sys. Tech J., January, 1969, pp. 55-70

Widrow and M. E. HOff, Jr., “Adaptive switching Circuits”, IRE Wescon Conv. Rec., pt. 4, August, 1960, pp 96-104

D. Godard, “Channel Equalization usin a Kalman Filter for Fast Data

Transmission“, IBM J. Research and Development, May, 1974, pp 267-273

R. D. Gitlin and F. R. Magee, Jr., “Self-Orthogonalizing Adaptive Equalization Algorithms”, IEEE Trans. Communications, July 1997, pp. 666-672

R. w. Chang, “A New Equalizer for Fast Sart-Up Digital Communication”, Bell Sys

Tech. J., July-August, 1971, pp 1969-2014.

Morf, L. Ljung and T. Kailath, “Fast Algorithms for RecuSiVe Identification”, Proc. IEEE Conf. On Decision and Control Clearwater Beach, Florida, December, 1976

Morf and L. Ljung, “Fast Algorithms for Recursive Identifiaction”, IEEE

International Symposium on Information Theory, June, 1976, Ronneby, Sweden. Levinson, “the Wiener RMS (Root Mean Square) Error Criterion in Filter Desing and Presiction”, J. Math. Phys., 1974, Vol. 25, pp. 261-278

Ljung, M. Morf, and D. D. Falconer, “Fast Calculation of Gain Matrices for Recursive Estimation Shemes”, International J. Control, Juanary, 1978. Macchi and L. Guidoux, “Un Nouvel Égaliseur: L’ Égaliseur á Double Échantillonage”, Ann. Telecommum., Sept-Oct. 1975, pp. 331-338. D. Falconer, K. H. Mueller and S. B. Weinstein, “Echo Cancellation Techniques for Full-Duplex Data Transmission on Two-wire Lines”. Proc. Nat. Telecomm. Conf., Dallas, December 1976, pp 877-883

Soderstrom, L. Ljung and I. Gustavsson, “A Cmparative study of Recursive Identification Methods”, Report 7427, 1974, Dept. Of Automatic Control, Lund Institute of Technology, Lund, Sweden. J. Astrom and P. Eykhoff, ”System Identification- A Survey”, Automatica, vol. 7,

pp 123-162, (1971)

I . Steinberg, Computational Matrix Algebra, McGraw-Hill, 1974.

77

[I51 Identification Methods”, Report 7427, 1974, Dept. O f Automatic Control, Lund Institute of Technology, Lund, Sweden.

1161 J. Astrom and P. Eykhoff, “System Identification- A Survey”, Autornatica, Vol. 7, pp 123-162, (1971)

7%