Learning">
Nothing Special   »   [go: up one dir, main page]

Equilibrando Pendulo Invertido - Eric Joel Barragan Gonzalez

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 73

Tabla de Contenido

Presentación
Intención de la Serie:
Lo que Abarca este Libro:
Requerimientos para Seguir el Libro:
Como Seguir este Libro:
El Siguiente Libro:
Temas de los Libros de la Serie:

1. Antecedentes
2. Limitantes
3. Utilidad
4. Problema Inicial
5. Objetivos
6. Explicación del Algoritmo Paso a Paso
6.1 Librerías
6.1.1 Código
6.2 Parámetros Iniciales y Variables
6.2.1 Código
6.3 Definición de Elementos a Dibujar
6.3.1 Código
6.4 Definición de Móvil
6.4.1 Código
6.5 Perceptrón de Control
6.5.1 Código
6.6 Definición de Ventana
6.6.1 Código
6.7 Creación de Elementos
6.7.1 Código
6.8 Dibujado en Ventana
6.8.1 Código
6.9 Actualización y Control Manual
6.9.1 Código
6.10 Arranque del Programa
6.10.1 Código
6.11 Programa Completo
6.11.1 Código Completo en Python 2
7. Tiempos de Trabajo del Perceptrón
8. Variables a Ingresar al Perceptrón
9. Definición del Cálculo del Error
10. Función de Activación o Transferencia
11. Entrenamiento y Controles
12. Comparando con y sin Función de Activación
13. Entrenamiento con Respuesta Inmediata
14. Ventajas del Aprendizaje Permanente
15. Configuración en Espejo
16. Modelado Matemático del Simulador

Retroalimentación
Serie Tutorial:

Programando Redes Neuronales Artificiales Paso a Paso con Python

3: Equilibrando Péndulo Invertido con Perceptrón


(Analizado y Explicado con Sentido Práctico)

Código en Python para :

- Equilibrar el Péndulo Invertido con un Perceptrón: 379 líneas

por: Eric Joel Barragán González


Intención de la Serie:

Con la presente Serie de Libros, pretendo compartir mi experiencia trabajando con las Redes Neuronales Artificiales
(RNA), la que adquirí al buscar su aplicación en mis proyectos y encontrarme con abundante y buen material teórico,
con fórmulas matemáticas, pero poco práctico, muy laboriosos de aplicar, o simplemente ejemplos incompletos que
solo mostraban resultados y no implementación; sin contar las horas para entenderlo antes de aplicarlo. Por lo que con
esta Serie de Libros pretendo cubrir la parte práctica con ejemplos probados, y con cada Libro, puedas experimentar
con tu propio código y comenzar a adaptarlos a tus proyectos, ya sea un robot o una aplicación para toma de decisiones.

Así que me enfoco en guiar al lector que quiere experimentar con el fascinante mundo de las Redes Neuronales
Artificiales codificándolo por si mismo, y que tiene dificultades para hacerlo, lo cual pretendo facilitar con al menos un
ejemplo completo por Libro.

Aprende haciendo. Con la Serie comienza copiando, y con tu propia experiencia, aprenderás a:

1. Evaluar las necesidades y recursos de tu Proyecto.

2. Seleccionar que tipo de RNA emplear en tu proyecto.

3. Diseñar tu propia topología de RNA.

4. Parametrizar la topología y facilitar su mejora dinámicamente, con menos recodificación.

5. Configurar tu RNA de acuerdo a tus necesidades.

6. Distinguir cuales son las partes que consumen más tiempo de cómputo, para producir una topología y código
finales de desempeño eficiente, con consumo de memoria controlada

Compartiéndote comentarios de mi experiencia, que te ayuden a asimilar tu experiencia con mayor facilidad. El mundo
de las RNA está en pañales, y lo que se sabe se ha aprendido a prueba y error, apoyándose un poco en teoría
matemática, pero sobre todo en inspiración biológica, de las redes neuronales de los cerebros estudiados; así que si
quieres aprender, creo yo, debes estar dispuesto a arriesgarte a equivocarte y tal vez hasta logres descubrir algo que
nadie más ha encontrado y aportes también a este campo.

Con cada Libro cubriré por lo menos un ejemplo completo, funcional y probado, explicando paso a paso el algoritmo,
mostrando su codificación en lenguaje Python, pues no solo es fácil de aprender y entender, además es muy utilizado, y
por su claridad, ayuda a que entiendas mejor los algoritmos, por si lo quieres escribir en otro lenguaje; por otro lado se
está desarrollando una serie paralela en lenguaje C que es muy utilizado en proyectos de electrónica y PC, genera
ejecutables eficientes, que en RNA de gran escala, o proyectos de recursos reducidos, es importante.

La Serie se centra en ejemplos que te ayudarán a entender como funcionan las RNA, aunque también incluiré Libros en
especial que te ayuden a desarrollar algoritmos para solucionar problemas específicos en la Robótica y en el Manejo de
Información, como lo son Visión por Computadora, Equilibrio y Desplazamiento, Navegación, Manipulación de
Objetos, Interpretación del Habla, Reconocimiento de Escritura, Interpretación de Sonares, Clasificaciones y Selección,
Ajuste de Parámetros, Monitoréo de Procesos, Optimización, Análisis de Tendencias y Predicciones.

Además te recomiendo ejercicios en los que te guío, para que en tus primeros experimentos sepas que cambiarle y
donde esperar afecte, y pronto puedas refinar tu conocimiento por tu propia mano y experiencia.

No necesariamente los ejemplos serán como los de los autores de cada momento de las historia de las redes neuronales,
pues no es el objetivo de la Serie. Pero inspirado en estos y bajo los mismos principios, haremos un recorrido de
ejemplo en ejemplo para que puedas conocer las aportaciones principales y las incorpores a tu conocimiento y
experiencia, y al terminar de recorrer esta Serie seas capaz de diseñar tus propias RNA, incorporar con mayor facilidad
nuevo conocimiento y hasta realizar tus propias aportaciones en tus proyectos.
Se paciente, pues pasar mis notas y experiencias a ejemplos que sean interesantes, con ejercicios guiados y explicados,
me toma tiempo y algunos libros pueden demorar más en publicarse por la complejidad y el tiempo que toma probar los
ejercicios; procuraré sacar cada libro lo más pronto posible, pero procurando ser claro, mantenerlo sencillo e
incorporando al mismo tiempo los elementos que te ayuden a darte cuenta de los aspectos más relevantes de cada
algoritmo que trabajamos, y buscando siempre el sentido práctico.

Tabla de Contenido
Lo que Abarca este Libro:

En este libro les mostraré la integración al algoritmo del Perceptrón de una función matemática, la que se aplica a la
salida del cálculo del Perceptrón, es llamada "Función de Activación" o "Función de Transferencia", veremos como
afecta el comportamiento del Perceptrón y reflexionaremos sobre en que casos puede ser mejor usarla y en cuales no es
necesaria e incluso mejor, para lo que la compararemos contra su comportamiento sin ella.

Lo haremos con un ejemplo muy visual y práctico, en el que el trabajo del Perceptrón será equilibrar un Péndulo
Invertido montado sobre un Carro. Que es una solución muy interesante y aplicable incluso a problemas de la Industria.
Y lo haremos con un algoritmo de un Perceptrón de una sola Neurona, puro, pues no nos apoyaremos con fórmulas,
como muchas veces se hace, que prácticamente entregan el valor y se le deja al Perceptrón solamente la tarea de ajustar
este valor a partir de la alimentación de este valor y de algunos otros parámetros de que se disponen. Nosotros
dejaremos todo el trabajo al Perceptrón para cumplir la tarea, lo que resultará al final en que con mucho menos
cómputo pueda resolverlo.

Tabla de Contenido
Requerimientos para Seguir el Libro:

1. Saber Programar en el Lenguaje de Tu Elección, de Preferencia Python.

2. Con el Lenguaje Elegido, una Máquina con Entorno de Desarrollo Listo.

3. De el Lenguaje Elegido, Librerías de Funciones Matemáticas.

4. De el Lenguaje Elegido, Librerías de Animación Geométrica: como pyglet, o pygame para Python.

5. Nociones de Física Mecánica Dinámica.

6. Nociones de Plano de Coordenadas.

7. Nociones de Trigonometría.

8. Estar Dispuesto a Experimentar.

Aunque el conocimiento no es trivial, en cuanto a física es suficiente con lo que aprendes en la escuela, por lo regular
antes de la universidad, incluso si no lo recuerdas o no lo has visto, puedes apoyarte en internet, para darte una idea,
pues no requieres dominarlo, en el peor de los casos puedes limitarte a copiar las fórmulas y las gráficas te permitirán
entenderlo y tal vez solo te hagan falta algunos conceptos; y en cuanto a las librerías que se requieren de Python, en una
búsqueda en internet encontrarás tutoriales que te ayudarán a dejar listo tu equipo para trabajar. Ahora que si ocupas
otro lenguaje de programación puede ser un poco más difícil encontrar las librerías, e incluso en algunos lenguajes no
existirán y tendrás que hacer las funciones tu mismo. Por lo anterior, yo te recomiendo uses Python, es un lenguaje muy
adecuado para el aprendizaje, en especial por todas la librerías que se han desarrollado para él, además de su claridad.

Tabla de Contenido
Como Seguir éste Libro:

El Libro lo he pensado para seguir de principio a fin, de manera que vayas incorporando conocimiento, y en los
algoritmos, elementos, yendo de lo más sencillo a lo más complicado, para entender mejor que es lo que está pasando,
y de cada elemento incorporado una explicación, y después ejercicios con reflexiones, que te permitan acortar tu curva
de aprendizaje-experiencia, y practiquemos el analizar con un sentido práctico, en lugar de configurar simplemente a
prueba y error, o de depender solo de las fórmulas matemáticas, que aunque muy útiles pues complementan nuestro
conocimiento y nos dan otro punto de vista, si nos descuidamos, nos pueden estar limitando a un solo punto de vista, y
nos estaríamos perdiendo de la increíble capacidad de nuestro cerebro para entender las cosas y verlas más allá. Sin
embargo los nombres de los Puntos que te presento son descriptivos, como para que distingas si es algo que no
requieres leer y continúes con el punto siguiente.

En particular en Este Libro pongo el grueso de la Teoría después de la codificación, de manera que cuando llegues a
ella ya tengas funcionando el Simulador y hallas podido hacer algunas pruebas. Y, cuando trabajemos con la teoría la
vayas incorporando a tu conocimiento junto con pruebas y reflexiones que te propondré, claro más las tuyas.

Cuando leas en un dispositivo de pantalla pequeña, te sugiero que por lo menos cuando veas el código, pongas la
pantalla en horizontal, para que con mayor ancho, quepan las líneas completas y no pasen al siguiente renglón en lo
posible.

Tabla de Contenido
El Siguiente Libro:

Para el siguiente libro comenzaremos a trabajar con un Perceptrón con varias Neuronas, en el que el trabajo que le
daremos será el aprender a reconocer caracteres, que será un paso más para seguir avanzando en integrar nuevas
capacidades al Perceptrón, para que nuestros algoritmos de Perceptrón puedan resolver tareas más complejas.

Tabla de Contenido
Temas de los Libros de la Serie:

1. Perceptrón Simple con y sin Sesgo(bias) con Función Lineal

2. Perceptrón Simple con Umbral Implícito y Función Lineal

3. Perceptrón Simple con Umbral Implícito y Función No Lineal

4. Perceptrón Monocapa con Función Sigmoide

5. Perceptrón Bicapa con Retropropagación(Backpropagation) y Función Sigmoide

6. Perceptrón Tricapa con Retropropagación(Backpropagation) y Función Sigmoide

7. Perceptrón Tricapa con Retropropagación(Backpropagation) y Función Alternas de Sigmoide

8. Perceptrón Multicapa con Ramificaciones

9. Perceptrón Multicapa con Ramificaciones Traslapadas

10. Perceptrón Multicapa con Convolución

11. Perceptrón con Aprendizaje por Refuerzo para Activar Robots

12. Perceptrón con Memoria Asociativa para Clasificación de Imágenes

13. Perceptrón para Reconocimiento de Caracteres

14. Perceptrón para Reconocimiento de Voz

15. Perceptrón para Reconocimiento de Imágenes

16. Perceptrón Evolutivo para Acelerar Aprendizaje

Tabla de Contenido
1. Antecedentes

En cuanto a la Función de Activación obedece a una inspiración biológica, pues al estudiar las neuronas se ha
encontrado que la energía que entrega no es lineal, además de que no siempre el resultado es activa o inactiva, sino que
pueden entregar una magnitud, como lo comenzamos a trabajar en el Libro Anterior y lo haremos en Este Libro. Se han
aplicado y probado una considerable cantidad de funciones, algunas tan especificamente desarrolladas para casos en
particular, que para otros casos resultan inadecuadas. Clasificarlas no es tarea fácil, pues por así decirlo, con sus
particularidades, casi podemos aplicar cualquier función, y el Perceptrón tiende a adaptarse, tomando en cuenta que no
necesariamente será para mejorar su desempeño. Nosotros comenzaremos a ver las funciones por las más usadas y por
ser las que se pueden generalizar a más situaciones.
El Péndulo Invertido

El equilibrar el Péndulo Invertido ha sido tradicionalmente un banco de pruebas de sistemas de control automático
debido a su nivel de dificultad y requerimiento de respuesta inmediato, similar a los requerimientos de varios sistemas
de interés, como controlar cohetes y sistemas de navegación, por una parte, mientras por otra es directamente útil como
equilibrar grúas y robots industriales. Del Péndulo se desprenden varios problemas a resolver:

Equilibrarlo ya sea cuando ya esta en equilibrio y mantenerlo, o cuando esta cercano a esta posición y el control
debe de ponerlo en posición y mantenerlo, que es el trabajo que le daremos a nuestro Perceptrón.
Partiendo de cualquier posición del Perceptrón, lo lleve a estar colgando ya estático, sin ningún balanceo.
Partiendo de cualquier posición lo lleve a la vertical y lo mantenga.
Partiendo de cualquier posición lo lleve a una determinada ubicación del carro con el Péndulo arriba y lo
mantenga.
Partiendo de cualquier posición lo lleve a una determinada ubicación del carro con el Péndulo abajo y sin
balanceo.
Con limitantes de recorrido del Carro pueda subir o bajar el Péndulo.

En este libro solo resolveremos el primer problema, pero ya que este ejercicio es tan bueno y rico en material lo
seguiremos usando en otros libro, pues mientras vamos incorporando capacidades a nuestros Perceptrones, esto nos
permitirá ir resolviendo también problemas más complejos.

Es usual que en la solución de este problema al Perceptrón le den un papel secundario, solo para ajustar el valor final
que es arrojado por el algoritmo principal, que consiste en fórmulas físicas que al calcularse prácticamente nos
arrojarán el valor necesario, el que ajustará el Perceptrón tomando en cuanta ajustes que han resultado en el pasado para
mejorar el resultado, que es como se utilizan los filtros Kalman, y después el resultado es traducido en impulso del
motor que equilibrará el Péndulo. Sinembargo nosotros no nos apoyaremos con otro algoritmo y le dejaremos
completamente el trabajo del equilibrio al Perceptrón, y las fórmulas solo las ocuparemos para el Simulador. Y te
enseñaré como configurarlo para que aprenda a hacerlo en solo 1,000 ciclos, y soporte variaciones en la Masa del
Péndulo.

Tabla de Contenido
2. Limitantes

La Función de Activación requiere tiempo de cómputo adicional, y no solo en el tiempo de entrenamiento,


también en el tiempo en que ya está trabajando el Perceptrón sin supervisión, cuando se trabaja Modo Pasivo.
Puede retardar el aprendizaje si no se manejas adecuadamente.

Tabla de Contenido
3. Utilidad

Contiene las oscilaciones fuera de control, previniendo comiencen a saltar de un lado a otro de los valores de
convergencia de los Pesos.
Permiten controlar los rangos de los valores en las que los ajustes serán mayores, acelerando el aprendizaje-
respuesta, mientras que lo puede reducir en otros, como lo puede ser cuando estos valores estén cerca de los
óptimos, proporcionando un ajuste más fino.

Del Controlador del Péndulo Invertido su utilidad permite entre otras ser base para:

Equilibrar robots de dos ruedas o incluso una.


Equilibrar robots con piernas, incluso con una pierna, para caminar correr o saltar.
Balancear bajo control cargas de las grúas.
Que Robots manejen elementos sin perder el equilibrio, con movimientos eficientes en tiempo y energía.
Controlar el empuje de un cohete espacial.
Mantener la dirección de la navegación de una nave, facilitando al piloto su manejo.

Tabla de Contenido
4. Problema Inicial

El problema es similar a cuando un niño juega a equilibrar una escoba de cabeza en la palma de su mano, este abarca
tres dimensiones, en nuestro caso el Péndulo Invertido se simplifica para una primera aproximación a dos dimensiones.

El problema radica en la dificultad para controlar la vertical del Péndulo ya que es un sistema inherentemente inestable,
mostrando un nivel de complejidad por un lado comparable a otros problemas, y por otro lado en si es un problema que
se presenta en situaciones reales que es deseable controlar tanto el movimiento como el equilibrio.

Tabla de Contenido
5. Objetivos

Simular un Péndulo Invertido sobre un Carro.


Equilibrar el Péndulo Invertido sobre el Carro simulado.
Levantarlo desde 60° de la vertical, hasta la vertical.
Controlarlo con un Perceptrón de una sola Neurona sin Función de Activación.
Controlarlo con un Perceptrón de una sola Neurona con Función de Activación Sigmoide.
Comparar y reflexionar sobre ventajas y desventajas de la Función de Salida Sigmoide.

Tabla de Contenido
6. Explicación del Algoritmo Paso a Paso

La forma en la que organizo el código es la siguiente:

1. Librerías
2. Parametros Iniciales y Variables
3. Definición de Elementos a Dibujar
4. Definición de Móvil
5. Perceptrón de Control
6. Definición de la Ventana
7. Creación de Elementos
8. Dibujado en Ventana
9. Actualización y Control Manual
10. Arranque de Programa

De cada Proceso explico su funcionamiento esencial, enseguida listo en un recuadro la parte del código
correspondiente, implementado en Python. Además cada paso complementado con notas de su funcionamiento.

Más detalles del funcionamiento, explicación y ejercicios, se cubrirán en Puntos siguientes. Ya que puedes estar
leyendo éste Libro en un dispositivo de pantalla pequeña, el Código en Python lo pongo en Tablas para diferenciarlo.
Cuando lo escribas en tu código, recuerda que el intérprete de Python toma en cuenta que esté en la misma línea el
código y que la indentación sea igual a la del grupo de líneas a las que pertenece, que es como agrupa Python.

Para la explicación yo me he acomodado con Pyglet para realizar la animación del Péndulo, sin embargo MyGame esta
muy difundido y podría ser tu elección, solo tendrás que sustituir lo relacionado, lo cual te será fácil identificar, pues
además de que esta agrupado, contienen la palabra gl o pyglet, o bien te lo indico.

Tabla de Contenido
6.1 Librerías

# coding=utf-8 : nos permitirá hacer comentarios con caracteres de el español.

random : nos permitirá generar los valores pseudoaleatorios de los Pesos Iniciales.

pyglet : y sus import nos permitirá crear ventanas, dibujarlas e interactuar en este caso con el teclado.

math : nos permitirá usar los elementos matemáticos que le acompañan.

Tabla de Contenido
6.1.1 Código

# coding=utf-8
import random
import pyglet
from pyglet.gl import *
from pyglet.window import key
from math import sin, cos, pi, e, fabs

Tabla de Contenido
6.2 Parametros Iniciales y Variables

Los siguientes son los parámetros que nos permitirán configurar el funcionamiento tanto de la simulación como del
entrenamiento y funcionamiento del Perceptrón.

Encendido : Con valores de (1 ó 0) pone en funcionamiento el Perceptrón, para que cuando no está entrenando puedas
probar lo que ha aprendido, o bien entrenar la vertical para aumentar la eficiencia en este punto.

Fracción : Se refiere a la fracción de tiempo de un segundo, configura tanto los Fotogramas por Segundo (FPS) como
la fracción de tiempo para el cálculo del simulador.

Ciclos : Es para el control de entrenamiento del Perceptrón, similar a los Libros Anteriores.

Estado : También binario, con (1) pondrá en entrenamiento al Perceptrón, y con (0) interrumpirá el entrenamiento.

Activo : Activa el Aprendizaje del Perceptrón, por lo que también guarda los valores de Pesos nuevos en el Archivo
indicado.

Sigmoide : Pone con (1) al Perceptrón la Función de Activación a su respuesta, afectando: resultado, error, evaluación
y aprendizaje. Es punto central en este libro, veras lo impactante que puede ser en el Perceptrón.

Apr : Es el Valor de Aprendizaje, que como en los Libros Anteriores es la magnitud de la aproximación de cada
aprendizaje que se calcula.

t_ini : Representa tanto la parte positiva como la negativa, del rango de ángulos que puede el Perceptrón en el
entrenamiento tomar en cada ciclo, el que se calculará pseudoaleatoriamente. Trabaja en Radianes con valores
positivos.

v_ini : Representa tanto le parte positiva como la negativa, del rango de velocidad que puede el Perceptrón en el
entrenamiento tomar en cada ciclo, el que se calculará pseudoaleatoriamente. Trabaja en Metros por Segundo con
valores positivos.

Archivo : Es el Nombre del Archivo en donde se guardará el aprendizaje del Perceptrón. El que tomará al arrancar el
programa si existe, si no, lo creará.

Las Variables que se inicializan, son con las que presentará en pantalla la información que nos permitirá tener una idea
de en que va trabajando el Perceptrón y su Estado. Lo que se podrá modificar con el Teclado con los Controles que
veremos más adelante.

Error : Es la variable donde se guardará el último Error de Desempeño del Perceptrón para presentarlo en Pantalla.

Fuerza : Es la última magnitud de Fuerza que se ha aplicado al Carro en busca de regresar a la vertical. Se muestra en
Pantalla.

Itr : El el número de ciclo de Aprendizaje en el que está trabajando el Perceptrón. Se muestra en Pantalla.

Ang : Es el ángulo en el que queda el Péndulo, después de aplicar la Fuerza calculada por el Perceptrón. Se muestra en
Pantalla.

Tabla de Contenido
6.2.1 Código

Encendido = 0
Fraccion = 60.0
Ciclos = 1000
Estado = 0
Activo = 0
Sigmoide = 1
Apr = 0.001
t_ini = 1.0
v_ini = 0.1
Archivo = 'Pesos.pes'

Error = 0
Fuerza = 0
Itr = 0
Ang = 0

Tabla de Contenido
6.3 Definición de Elementos a Dibujar

Para representar gráficamente la simulación utilizaremos un Círculo para el Péndulo, una Línea para la Barra y un
Rectángulo para el Carro. Que están formados por 3 partes: la inicialización de las variables, su actualización, con una
conversión de sistema de coordenadas y su dibujado, en este caso con Pyglet. Ya que en Pyglet no hay círculos
predefinidos, lo representaré con 24 puntos, los que se calculan a partir de su posición y la multiplicación de su
dimensión por un factor que corresponde a su ángulo correspondiente en incrementos de 15 grados. Como veras en
Pyglet se inicia indicando el tipo dibujo, se introducen las coordenadas de los puntos que lo forman y se termina el
dibujo. Ya que no requieren rotar ni el círculo ni el rectángulo, una vez definida su dimensión solo se trabajará con su
posición; mientras que para el caso de la linea una parte estará ligada a la posición del Carro y la Otra a la Masa del
Péndulo.

Por otro lado se define la Etiqueta, la que permitirá mostrar en pantalla la información del estado del Perceptrón y de
las variables de control de la simulación. Su forma de trabajar es similar, se inicializa, configurando la etiqueta, se
actualizan sus variables, y se dibuja. Aquí la diferencia con respecto a las figuras, es que estas solo se dibujan una vez
por actualización, mientras que la etiqueta se pintará una vez para cada dato, en cada actualización.

Tabla de Contenido
6.3.1 Código

class Circulo:
def __init__(self, (x, y, d)=(0, 0, 0)):
self.x, self.y, self.d = x, y, d
def dibujar(self):
x = self.x*100
y = self.y*100
d = self.d*100
gl.glColor3f(*(0,0,0))
gl.glBegin(gl.GL_POLYGON)
gl.glVertex3f(x + 0.09659*d, y + 0.02588*d, 0)
gl.glVertex3f(x + 0.08660*d, y + 0.05000*d, 0)
gl.glVertex3f(x + 0.07071*d, y + 0.07071*d, 0)
gl.glVertex3f(x + 0.05000*d, y + 0.08660*d, 0)
gl.glVertex3f(x + 0.02588*d, y + 0.09659*d, 0)
gl.glVertex3f(x + 0.00000*d, y + 0.10000*d, 0)
gl.glVertex3f(x + -0.02588*d, y + 0.09659*d, 0)
gl.glVertex3f(x + -0.05000*d, y + 0.08660*d, 0)
gl.glVertex3f(x + -0.07071*d, y + 0.07071*d, 0)
gl.glVertex3f(x + -0.08660*d, y + 0.05000*d, 0)
gl.glVertex3f(x + -0.09659*d, y + 0.02588*d, 0)
gl.glVertex3f(x + -0.10000*d, y + 0.00000*d, 0)
gl.glVertex3f(x + -0.09659*d, y + -0.02588*d, 0)
gl.glVertex3f(x + -0.08660*d, y + -0.05000*d, 0)
gl.glVertex3f(x + -0.07071*d, y + -0.07071*d, 0)
gl.glVertex3f(x + -0.05000*d, y + -0.08660*d, 0)
gl.glVertex3f(x + -0.02588*d, y + -0.09659*d, 0)
gl.glVertex3f(x + 0.00000*d, y + -0.10000*d, 0)
gl.glVertex3f(x + 0.02588*d, y + -0.09659*d, 0)
gl.glVertex3f(x + 0.05000*d, y + -0.08660*d, 0)
gl.glVertex3f(x + 0.07071*d, y + -0.07071*d, 0)
gl.glVertex3f(x + 0.08660*d, y + -0.05000*d, 0)
gl.glVertex3f(x + 0.09659*d, y + -0.02588*d, 0)
gl.glVertex3f(x + 0.10000*d, y + -0.00000*d, 0)
gl.glEnd()

class Cuadrado:
def __init__(self, (x, y, d)=(0, 0, 0)):
self.x, self.y, self.d = x, y, d
def dibujar(self):
x = self.x*100
y = self.y*100
d = self.d*100
gl.glColor3f(*(0,1,0))
gl.glBegin(gl.GL_QUADS)
gl.glVertex3f(x + 0.25*d, y + 0.0, 0)
gl.glVertex3f(x +-0.25*d, y + 0.0, 0)
gl.glVertex3f(x +-0.25*d, y + -0.3*d, 0)
gl.glVertex3f(x + 0.25*d, y + -0.3*d, 0)
gl.glEnd()

class Linea:
def __init__(self, (x1, y1, x2, y2)=(0, 0, 0, 0)):
self.x1, self.y1, self.x2, self.y2 = x1, y1, x2, y2
def dibujar(self):
x1 = self.x1*100
y1 = self.y1*100
x2 = self.x2*100
y2 = self.y2*100
gl.glColor3f(*(0,0,0))
gl.glBegin(gl.GL_LINES)
gl.glVertex3f(x2, y2, 0)
gl.glVertex3f(x1, y1, 0)
gl.glEnd()
class Etiqueta:
def __init__(self):
self.e = pyglet.text.Label( ''
, font_size=20
, x=0, y=0
, color=(0,0,0,255)
, anchor_x='left'
, anchor_y='center')
def dibujar(self, x, y, t):
self.e.x = x
self.e.y = y
self.e.text = t
self.e.draw()

Tabla de Contenido
6.4 Definición de Móvil

Llamo Móvil a la definición del Objeto con el que se realiza la Simulación en la parte abstracta, que se complementará
con el conjunto formado por el Carro, la Barra y la Bola del Péndulo. Se define en cuatro partes: la inicialización de sus
variables para el cálculo de su simulación, la actualización de las variables para su graficación, el cálculo de la
simulación y el cambio de la fuerza de empuje, que es como se interactúa con la simulación, ya sea por Control Manual
o por el Control del Perceptrón.

Inicialización

Para el Carro

self.M = Masa
self.D = Dimensión
self.b = Fricción
self.X = Posición
self.V = Velocidad
self.A = Aceleración
self.F = Fuerza

Para el Péndulo

self.m = masa
self.d = dimensión
self.l = longitud
self.t = ángulo
self.v = velocidad
self.a = aceleración
self.It = ángulo inicial
self.Iv = velocidad inicial

Para Otros

self.G = Gravedad
self.FT = Fracción de Tiempo
self.Entrenamiento = Estado de Entrenamiento
self.Activo = Aprendiendo

Actualizar

Pasa los nuevos valores de las variables del Móvil, a las figuras geométricas para que se muestre en pantalla la
simulación.

Calcular

Se pasan los valores a variables locales para facilitar su manejo en la fórmula, se considera la dirección de la velocidad
para el signo de la fricción, se precalculan el Seno y el Coseno del ángulo, y se aplican las fórmulas que en el último
capítulo explicaré, las que se ocupan para calcular las aceleraciones del Carro y del Péndulo; con estos resultados se
actualizan los valores de las variables afectadas, del Carro y del Péndulo, según corresponda; después de esto para que
no se salga de pantalla, cada vez que va a quedar fuera se envía al otro lado para que continúe visible, y por ultimo se
mantiene el ángulo en el rango de (-pí a pi). Y en cuanto al empuje se toma el valor para su cálculo y se introduce en
los de el Móvil.
Empuje

Y en cuanto al Empuje es la forma para ingresar en el Simulador el Dato con el que se interactúa con él, ya sea a traves
del Control Manual, o del Control por el Perceptrón. Solo es una variable del Móvil, pero por su relevancia la separé de
las demás.

Tabla de Contenido
6.4.1 Código

class Movil():
def __init__(self):
# Propiedades de Carro
self.M = 1.0
self.D = pow(self.M, 0.33333333)
self.b = 0.05
self.X = 0.0
self.V = 0.0
self.A = 0.0
self.F = 0.0
# Propiedades de Pendulo
self.m = 1.0
self.d = pow(self.m, 0.33333333)
self.l = 1.0
self.t = 0.0
self.v = 0.0
self.a = 0.0
self.It = 0.0
self.Iv = 0.0
# Otros
self.G = 9.8
self.FT = Fraccion
self.Entrenamiento = Estado
self.Activo = Activo
def Actualizar(self):
X = self.X
t = self.t + pi
l = self.l
x = X + sin(t) * l
y = cos(t) * l
M = self.M
m = self.m
D = self.D
d = self.d
circulo.x = x
circulo.y = -y
circulo.d = d
cuadrado.x = X
cuadrado.d = D
linea.x2 = x
linea.y2 = -y
linea.x1 = X
def Calcular(self):
FT = self.FT
F = self.F
G = self.G
M = self.M
X = self.X
V = self.V
b = self.b
m = self.m
l = self.l
v = self.v
t = self.t
if V > 0:
B = b
elif V 0:
B = -b
else:
B = 0
S = sin(t)
C = cos(t)
A = (F - S * C * G * m + S * m * v**2 * l - B *
M * G - B * C * C * G * m + B * C * m * v**2 *
l) / (M + S * S * m + B * C * S * m)
a = S * G - C * A

self.a = a
self.A = A
self.V += A / (2*FT)
self.v += a / (2*FT)
self.X -= V / (1*FT)
self.t += v / (1*FT)
if self.X > 4: self.X = -4
if self.X -4: self.X = 4
if self.t > pi: self.t -= 2*pi
if self.t -pi: self.t += 2*pi
self.F = 0
def Empujar(self, F):
self.F = F

Tabla de Contenido
6.5 Perceptrón de Control

El punto principal que incorporamos al Algoritmo del Perceptrón en Este Libro, es la Función de Activación, a la que le
dedicaremos un Punto en especial después del Código. Otro punto importante, es el que trabajaremos el Perceptrón en 2
tiempos, en el primero calcularemos el valor del Perceptrón, y con el valor arrojado, en este caso ocupado para empujar
el Carro, el simulador realizará la acción, y solo después de terminar la ejecución, podremos evaluar el desempeño del
Perceptrón, por lo que es cuando entrará el segundo tiempo, en el que se calculará el Error, el Delta, se Ajustarán los
Pesos y se guardará el Aprendizaje. Como notaras habrá un tiempo de actividad sin que intervenga el Perceptrón, en
donde esperamos a cada ciclo se acerque más a la vertical con un solo empuje, el que se evaluará; lo anterior en una
sola función. Hay otra forma de programarlo, que sería separarlo en dos funciones, una para cálculo y la otra para
evaluación y aprendizaje.

Este fragmento de código comienza con la inicialización, donde se verifica se hallan creado las variables, y si no, las
crea, para los Pesos, si los puede tomar del archivo lo hace, si no, genera los valores pseudoaleatoriamente.

Después verifica en que tiempo se encuentra, en (1) realiza el cálculo del Perceptrón y regresa el resultado. Al
resultado, si así se ha escogido, se le aplica la función Sigmoide, la que tiene dos asíntotas, lo que nos da un control de
desborde implícito (se explica en otro punto). Ahora que si usamos otra función sin asíntotas, debemos recordar topar
los valores a (-1 y 1) para que el Perceptrón no se desborde, igual que lo haremos para cuando no ocupemos la función
de activación; y claro antes de salir debemos convertir el valor al rango de fuerza del motor para que pueda ser
utilizado, en nuestro caso por (1,000).

En el segundo tiempo el Perceptrón no se calculará y se irá directo a su evaluación, comenzando con el cálculo del
Error, lo que corresponde al momento en que daremos por terminado el ejercicio, con lo que se ajustarán los Pesos
aplicando el Aprendizaje como factor a cada entrada de cada Peso, agregándose a su valor; para después ser guardada
en el archivo para este propósito. El Perceptrón guarda cada ajuste de Pesos en el Arreglo y en el Archivo, aunque si se
prefiere se puede modificar el código y guardar a Archivo por Orden en el Control Manual, o bien al terminar el
Entrenamiento, ahora que esto una vez Entrenado el Perceptrón no será problema, pues esta parte del código ya no se
requerirá, ya no será necesario que siga aprendiendo, pues ya lo hará bien sin aprendizaje.

El como calcular el Error es un punto crítico al diseñar un Perceptrón. Se puede simple y burdamente incorporar todas
las variables de que se disponen y con paciencia el mismo Perceptrón acabara después de muchos ciclos de
entrenamiento, distinguiendo la información que le es más útil y discriminando el resto, con lo que podrá resolver el
problema encomendado, claro, siempre que dentro de las variables elegidas tenga suficiente información para este
propósito, y que el Perceptrón sea lo suficientemente robusto para poder producir las suficientes combinaciones, lo que
por lo regular implica varias capas de Neuronas. Ahora que es posible ahorrarle este trabajo al Perceptrón, reduciendo y
simplificando significativamente su estructura y con ello los calculos requeridos y con ello a su vez el tiempo de
cómputo, y si también, nuestro tiempo de espera. Por su importancia a éste punto le dedicaremos un apartado en
especial más adelante, por ahora nota que el Perceptrón es muy similar al del Libro Anterior que hemos trabajado.

Tabla de Contenido
6.5.1 Código

def Control( t, v, Tiempo ):


global Error
# Inicializa Variables
if not hasattr( Control, "Apr" ):
Control.Apr = Apr
if not hasattr( Control, "Pes" ):
try:
file = open(Archivo, 'r')
Control.Pes = []
Control.Pes += [float(file.readline())]
Control.Pes += [float(file.readline())]
Control.Pes += [float(file.readline())]
Control.Pes += [float(file.readline())]
file.close()
except Exception:
Control.Pes = [random.uniform( -0.125, 0.125 ) for
j in range(4)]
# Calculo del Perceptron
if Tiempo:
Eng = 0
Eng += Control.Pes[0] * t
Eng += Control.Pes[1] * sin(t)
Eng += Control.Pes[2] * v
Eng += Control.Pes[3]
if Sigmoide:
Eng = (2/(1+pow(e,-Eng))-1)
else:
if Eng > 1: Eng = 1
if Eng -1: Eng = -1
return Eng * 1000
# Control de Error y Aprendizaje
else:
# Error
Err = v + t
Dlt = Err * Control.Apr
Error = Err
# Ajuste de los Pesos
Control.Pes[0] += t * Dlt
Control.Pes[1] += sin(t) * Dlt
Control.Pes[2] += v * Dlt
Control.Pes[3] += Dlt
# Guarda lo Aprendido
file = open(Archivo,'w')
file.write(str(Control.Pes[0])+"\n")
file.write(str(Control.Pes[1])+"\n")
file.write(str(Control.Pes[2])+"\n")
file.write(str(Control.Pes[3])+"\n")
file.close()
return 0

Tabla de Contenido
6.6 Definición de la Ventana

Esto depende básicamente de las librerías que hallas elegido para graficar el simulador, en este caso con Pyglet. Como
este no es un curso de Pyglet, solo te daré una explicación sencilla de este código. Pyglet maneja su propia forma de
desplegar ventanas, una de las ventajas que le encuentro pues aumenta su portabilidad entre sistemas; también te
comento que como varias librerías, tiene varias formas de trabajar la graficación, y que incluso esta no sea la que más te
acomode, lo importante es que es una forma que funciona lo suficientemente bien. Pues bien las cuatro primeras lineas
tiene el propósito de preparar una ventana para ser desplegada, las dos siguientes definen el tamaño en pantalla en
pixeles de 800x400, y las dos últimas nos permitirán capturar el teclado para nuestro control manual. Si quieres saber
más de Pyglet, hay referencias y tutoriales que encontraras con facilidad en internet.

Tabla de Contenido
6.6.1 Código

display = pyglet.canvas.get_display()
screen = display.get_default_screen()
config = screen.get_best_config()
window = pyglet.window.Window(config=config)
window.width = 800
window.height = 400
keyboard = key.KeyStateHandler()
window.push_handlers(keyboard)

Tabla de Contenido
6.7 Creación de Elementos

Si has programado con orientación a objetos notaras que esta parte de código es solo la creación de instancias de los
objetos que hemos definido para poderlos ocupar. Si no estas familiarizado con programación orientada a objetos te
comento que es una forma muy práctica de reutilizar código, defines primero su funcionamiento y variables con las que
trabajará, y generas una variable que tiene por tipo este objeto, que es como una función que retiene sus variables cada
vez que la llamamos, solo que además puedes crear varias, cada una la asignas a una variable y la manejas como un
objeto independiente que opera dependiendo de los parámetros con los que la hallas creado y con las variables que le
vayas actualizando, cada instancia con total independencia. En este programa solo trabajamos un Carro con Péndulo,
pero con unos pequeños cambios podrías tener varios de diferentes tamaños, colores y a diferentes velocidades,
trabajando simultaneamente, si te gustaría hacer juegos, pues ya tienes una idea de como.

Con lo anterior te darás una idea de que lo usual es que un objeto contenga todo lo que necesita, incluyendo sus propios
gráficos, sin embargo a mi me pareció que sería más fácil para la explicación separarlo sobretodo para los que no
manejas orientación a objetos, así que tendremos una instancia para la parte abstracta de la simulación (los cálculos), y
otra para cada una de las figuras que ocuparemos. Pues bien las primeras dos lineas son para crear una instancia de la
parte abstracta que llamo Carro, y ponerle el estado de Entrenamiento; enseguida están las tres instancias de las figuras
de graficación, después la instancia que ocuparemos para poner las etiquetas que nos mostrarán en pantalla los datos de
control, y por último el color del fondo de pantalla, que será blanco.

Tabla de Contenido
6.7.1 Código

Carro = Movil()
Carro.Entrenamiento = Estado
circulo = Circulo((0, 1, 1))
cuadrado = Cuadrado((0, 0, 1))
linea = Linea((0, 0, 0, 1))
etiqueta = Etiqueta()
glClearColor(*(1,1,1,1))

Tabla de Contenido
6.8 Dibujado en Ventana

El como funcione esto y de que tendrás que hacer también dependerá de las librerías de graficación que estés ocupando.
En Pyglet esta función será llamada cada vez que se actualice la ventana dibujando como aquí se indique.

Las dos primeras lineas le indican a Pyglet que esta es la función de Dibujo de la Ventana llamada window, por lo que
cuando se active el evento de dibujo, ocupe esta función.

Las cuatro lineas siguientes solo le avisan a la función que cuando hagamos referencia a estas variables (Error, Fuerza,
Itr, Ang) serán las globales.

Despues window.clear() limpiará de dibujos la Ventana, dejándola en Blanco, como previamente lo definimos.

Enseguida viene el establecimiento del sistema de coordenadas, el que defino para X de (-400 a 400) y para Y de (-250
a 150). Ahora que la simulación la trabajé en metros por lo que en las figuras de graficación las convierto a centímetros,
lo que fue necesario ya que las etiquetas en Pyglet no se pueden mostrar a tan baja resolución y son convertidas
multiplicándolas por (100).

Lo siguiente es el dibujar las figuras geométricas, para lo que simplemente llamamos su función que para este propósito
cada una tiene, los que estarán actualizados cada vez con la función (update) que enseguida veremos.

El resto de las lineas es para dibujar las etiquetas de la información de control. Como notarás es solo una etiqueta
dibujada varias veces, cada vez en coordenadas diferentes con contenido diferente, y todas se mostrarán al mismo
tiempo cada vez que se actualice la función de dibujo de la ventana. Las primeras tres corresponden al estado del
Perceptrón, mostrando si esta Entrenando, Aprendiendo y si está Trabajando; a su derecha las teclas con las que se
Activa y Desactiva cada Modo de Operación. Y las últimas tres lineas muestran del lado derecho las variables que nos
permitirán darnos una idea de en que va el Simulador. (Error último, Ángulo al terminar, Ciclo de entrenamiento que se
ejecuta, y la Fuerza que está ocupando).

Tabla de Contenido
6.8.1 Código

@window.event
def on_draw():
global Error
global Fuerza
global Itr
global Ang
window.clear()
# Establece Sistema de Coordenadas
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-400.0, 400.0, -250.0, 150.0, 0, 10)
glMatrixMode(GL_MODELVIEW)
# Dibuja Figuras
circulo.dibujar()
cuadrado.dibujar()
linea.dibujar()
# Dibuja Etiquetas
if Carro.Entrenamiento:
etiqueta.dibujar(-375.0,-75.0,"Entrenando (8/2)")
else:
etiqueta.dibujar(-375.0,-75.0,"En Prueba (8/2)")
if Carro.Activo:
etiqueta.dibujar(-375.0,-125.0,"Aprendiendo (7/9)")
else:
etiqueta.dibujar(-375.0,-125.0,"Sin Aprender (7/9)")
if Encendido:
etiqueta.dibujar(-375.0,-175.0,"Trabajando (5/0)")
else:
etiqueta.dibujar(-375.0,-175.0,"Libre (5/0)")
etiqueta.dibujar(-75.0,-75.0,"Error: " + str(Error))
etiqueta.dibujar(-75.0,-125.0,"Angulo: " + str(Ang))
etiqueta.dibujar(-75.0,-175.0,"Ciclo: " + str(Itr) + "
Fuerza: " + str("{0:.2f}".format(Fuerza)))

Tabla de Contenido
6.9 Actualización y Control Manual

Esta es la función de actualización. Es llamada (60 veces por segundo), como lo definimos en los parámetros iniciales
(Fraccion = 60), y a cada actualización redibujará la ventana. Puede variar un poco la velocidad de actualización de
gráficos, lo que no notarás a esa velocidad, que además es mínimo. La Función de Actualización es la que le dice que
hacer de acuerdo a los parametros dados, y según quien emita instrucciones, ya sea el Perceptrón o nosotros con el
Control Manual por las teclas que presionemos. Después de indicarle que tomaremos las cuatro variables globales
(Encendido, Fuerza, Itr, y Ang), encontramos la inicialización de la variable (running), si no esta inicializada, esta
variable permite que se trabajen dos secciones que funcionan en tiempos diferentes mientras se va llamando la función
(update), que son la parte del ciclo del simulador, el tiempo del Ciclo de Trabajo y la parte del Ciclo de Control.

A continuación encontramos el Control Manual. Las dos primeras teclas que se capturan son (8) para que comience a
Entrenar, por lo que se ponen en (1) Entrenamiento, Activo para que el Perceptrón Aprenda y Encendido, para que
Trabaje; y se captura (2) para interrumpir los ejercicios de Entrenamiento, se apaga el Aprendizaje, quedando en
Trabajo el Perceptrón, por lo que si ya aprendió se mantendrá en equilibrio, y se pone a (running = False) para que
termine si esta en medio de un ejercicio de entrenamiento.

Después encontraremos las teclas (5) para poner a trabajar el Perceptrón y (0) para apagarlo. Ya que no tiene sentido
dejarlo Aprendiendo ni Entrenando si no está trabajando, también se apagarán y terminará si hay algún ejercicio
pendiente.

Las siguientes teclas son (7) para que comience a Aprender, por lo que si no está Trabajando lo enciende, si no, no
podría Aprender; y (9) para que deje de Aprender, con lo que termina también si está en Entrenamiento.

Ahora encontramos la captura de las teclas (4 y 6). Estas teclas nos permitirán hacer ejercicios con Control Manual
completamente, empujaran el Carro a la Izquierda y a la Derecha respectivamente para que si gustes intentes equilibrar
tu mismo el Péndulo en la Vertical.

A continuación, están la captura de las teclas (1 y 3), que desbalancearán el Péndulo aleatoriamente haciéndolo girar
hacia un lado u otro, para que pongas a prueba el Perceptrón cuando ya halla entrenado.

Y por último las teclas [PAGEUP] y [PAGEDOWN], Agrandarán o Reducirán la Masa del Péndulo, también para
poner a prueba lo Aprendido por el Perceptrón.

Ahora veremos el Ciclo de Trabajo, el que opera solo cuando el Perceptrón está en Entrenamiento. Mientras se
encuentra entrando a esta sección se le está dando tiempo al simulador para que ejecute, con la fuerza que el Perceptrón
calculó para alcanzar la vertical, y lo único que se hace mientras, en cuanto a control, es verificar si ha alcanzado la
vertical, se a pasado, o si se le ha acabado la velocidad para alcanzarla; y al terminar este ciclo se vaya al Ciclo de
Control donde se realizará la evaluación del desempeño del Perceptrón, si está en Entrenamiento pasará al siguiente
Ejercicio.

En el Ciclo de Control encontramos la evaluación del desempeño del Perceptrón. En seguida, si esta en Entrenamiento,
reinicializa las variables para que realice el Perceptrón un nuevo Ejercicio de Entrenamiento, con valores
pseudoaleatorios para el ángulo y la velocidad del Péndulo, en el rango configurado. Después guarda los valores con
que inicia un nuevo ejercicio para al terminarlo pueda ser evaluado el cálculo del Perceptrón con estos mismos valores.
Lo siguiente, si está Encendido el Perceptrón, es que de acuerdo a los nuevos datos, ya sea de un ejercicio de
Entrenamiento, o generados por el Control Manual, el Perceptrón calcule la Fuerza para levantar hasta la Vertical al
Péndulo, Empujando el Carro. A continuación, si esta en Entrenamiento, incrementa el contador de Ciclos de
Entrenamiento y verifica si ha cumplido con la meta, si es el caso, apaga el Entrenamiento, si no, pone al Simulador en
Ciclo de Trabajo. Por último, realiza los cálculos con los nuevos datos, actualiza los de la parte gráfica del simulador y
pasa el nuevo ángulo a la variable global para mostrarlo en pantalla.

Tabla de Contenido
6.9.1 Código

def update(value):
global Encendido
global Fuerza
global Itr
global Ang
if not hasattr(update, "running" ):
update.running = False
if keyboard[key.NUM_8]:
Carro.Entrenamiento = 1
Carro.Activo = 1
Encendido = 1
elif keyboard[key.NUM_2]:
Carro.Entrenamiento = 0
Carro.Activo = 0
update.running = False
elif keyboard[key.NUM_5]:
Encendido = 1
elif keyboard[key.NUM_0]:
Encendido = 0
Carro.Activo = 0
Carro.Entrenamiento = 0
update.running = False
elif keyboard[key.NUM_7]:
Carro.Activo = 1
Encendido = 1
elif keyboard[key.NUM_9]:
Carro.Activo = 0
Carro.Entrenamiento = 0
update.running = False
elif keyboard[key.NUM_4]:
Fuerza = 20
Carro.Empujar(Fuerza)
elif keyboard[key.NUM_6]:
Fuerza = -20
Carro.Empujar(Fuerza)
elif keyboard[key.NUM_1]:
Carro.t = random.uniform( 0, t_ini )
Carro.v = random.uniform( 0, v_ini )
elif keyboard[key.NUM_3]:
Carro.t = random.uniform( -t_ini, 0 )
Carro.v = random.uniform( -v_ini, 0 )
elif keyboard[key.PAGEUP]:
Carro.m += 0.1
if Carro.m > 10.0: Carro.m = 10.0
Carro.d = pow(Carro.m, 0.3333333333333333)
elif keyboard[key.PAGEDOWN]:
Carro.m -= 0.1
if Carro.m 0.1: Carro.m = 0.1
Carro.d = pow(Carro.m, 0.3333333333333333)
# Ciclo de Trabajo
if update.running:
if Carro.It > 0:
if (Carro.v)>=0 or (Carro.t)=0:
update.running = False
elif Carro.It 0:
if (Carro.v)=0 or (Carro.t)>=0:
update.running = False
else:
update.running = False
# Ciclo de Control
else:
# Evaluacion y Ajuste
if Carro.Activo:
Control(Carro.It, Carro.Iv, 0)
# Inicializacion del Carro
if Carro.Entrenamiento:
Carro.X = 0.0
Carro.V = 0.0
Carro.A = 0.0
Carro.t = random.uniform( -t_ini, t_ini )
Carro.v = random.uniform( -v_ini, v_ini )
Carro.a = 0.0
Carro.It = Carro.t
Carro.Iv = Carro.v
# Dispara Respuesta del Control Automatico
if Encendido:
Fuerza = Control(Carro.It, Carro.Iv, 1)
Carro.Empujar(Fuerza)
# Control de Ciclos
if Carro.Entrenamiento:
Itr += 1
if Itr > Ciclos:
Carro.Entrenamiento = 0
else:
update.running = True
Carro.Calcular()
Carro.Actualizar()
Ang = Carro.t

Tabla de Contenido
6.10 Arranque de Programa

Por último definimos la velocidad de operación del Reloj de Pyglet, el que definimos en los Parámetros iniciales
(Fraccion = 60), con lo que realizará (60) actualizaciones por segundo, con los correspondientes (60 fps). Las
actualizaciones se harán con la función de actualización (update), en donde le decimos que hacer y nos toma los
eventos del teclado para el Control Manual. Y por último, ya teniendo todo listo, arranca el programa.

Tabla de Contenido
6.10.1 Código

pyglet.clock.schedule_interval(update, 1.0/Fraccion)
pyglet.clock.set_fps_limit(Fraccion)
pyglet.app.run()

Tabla de Contenido
6.11 Programa Completo

Ahora te muestro el código completo para que lo pruebes y lo hagas tuyo. En los capítulos siguientes te hago
comentarios, y te propongo reflexiones y ejercicios para que te familiarices con él, para ayudarte a acelerar tu curva de
aprendizaje, y a partir de aquí comiences tus propias pruebas y mejoras al código.

Tabla de Contenido
6.11.1 Código Completo en Paython 2

# coding=utf-8
import random
import pyglet
from pyglet.gl import *
from pyglet.window import key
from math import sin, cos, pi, e, fabs

# Parametros Iniciales
Encendido = 0
Fraccion = 60.0
Ciclos = 1000
Estado = 0
Activo = 0
Sigmoide = 1
Apr = 0.001
t_ini = 1.0
v_ini = 0.1
Archivo = 'Pesos.pes'
# Inicializa Variables
Error = 0
Fuerza = 0
Itr = 0
Ang = 0

# # # Definición de Figuras # # #
class Circulo:
def __init__(self, (x, y, d)=(0, 0, 0)):
self.x, self.y, self.d = x, y, d
def dibujar(self):
x = self.x*100
y = self.y*100
d = self.d*100
gl.glColor3f(*(0,0,0))
gl.glBegin(gl.GL_POLYGON)
gl.glVertex3f(x + 0.09659*d, y + 0.02588*d, 0)
gl.glVertex3f(x + 0.08660*d, y + 0.05000*d, 0)
gl.glVertex3f(x + 0.07071*d, y + 0.07071*d, 0)
gl.glVertex3f(x + 0.05000*d, y + 0.08660*d, 0)
gl.glVertex3f(x + 0.02588*d, y + 0.09659*d, 0)
gl.glVertex3f(x + 0.00000*d, y + 0.10000*d, 0)
gl.glVertex3f(x + -0.02588*d, y + 0.09659*d, 0)
gl.glVertex3f(x + -0.05000*d, y + 0.08660*d, 0)
gl.glVertex3f(x + -0.07071*d, y + 0.07071*d, 0)
gl.glVertex3f(x + -0.08660*d, y + 0.05000*d, 0)
gl.glVertex3f(x + -0.09659*d, y + 0.02588*d, 0)
gl.glVertex3f(x + -0.10000*d, y + 0.00000*d, 0)
gl.glVertex3f(x + -0.09659*d, y + -0.02588*d, 0)
gl.glVertex3f(x + -0.08660*d, y + -0.05000*d, 0)
gl.glVertex3f(x + -0.07071*d, y + -0.07071*d, 0)
gl.glVertex3f(x + -0.05000*d, y + -0.08660*d, 0)
gl.glVertex3f(x + -0.02588*d, y + -0.09659*d, 0)
gl.glVertex3f(x + 0.00000*d, y + -0.10000*d, 0)
gl.glVertex3f(x + 0.02588*d, y + -0.09659*d, 0)
gl.glVertex3f(x + 0.05000*d, y + -0.08660*d, 0)
gl.glVertex3f(x + 0.07071*d, y + -0.07071*d, 0)
gl.glVertex3f(x + 0.08660*d, y + -0.05000*d, 0)
gl.glVertex3f(x + 0.09659*d, y + -0.02588*d, 0)
gl.glVertex3f(x + 0.10000*d, y + -0.00000*d, 0)
gl.glEnd()

class Cuadrado:
def __init__(self, (x, y, d)=(0, 0, 0)):
self.x, self.y, self.d = x, y, d
def dibujar(self):
x = self.x*100

y = self.y*100
d = self.d*100
gl.glColor3f(*(0,1,0))
gl.glBegin(gl.GL_QUADS)
gl.glVertex3f(x + 0.25*d, y + 0.0, 0)
gl.glVertex3f(x +-0.25*d, y + 0.0, 0)
gl.glVertex3f(x +-0.25*d, y + -0.3*d, 0)
gl.glVertex3f(x + 0.25*d, y + -0.3*d, 0)
gl.glEnd()

class Linea:
def __init__(self, (x1, y1, x2, y2)=(0, 0, 0, 0)):
self.x1, self.y1, self.x2, self.y2 = x1, y1, x2, y2
def dibujar(self):
x1 = self.x1*100
y1 = self.y1*100
x2 = self.x2*100
y2 = self.y2*100
gl.glColor3f(*(0,0,0))
gl.glBegin(gl.GL_LINES)
gl.glVertex3f(x2, y2, 0)
gl.glVertex3f(x1, y1, 0)
gl.glEnd()

class Etiqueta:
def __init__(self):
self.e = pyglet.text.Label( ''
, font_size=20
, x=0, y=0
, color=(0,0,0,255)
, anchor_x='left'
, anchor_y='center')
def dibujar(self, x, y, t):
self.e.x = x
self.e.y = y
self.e.text = t
self.e.draw()

# # # Definición de Movil # # #
class Movil():
def __init__(self):
# Propiedades de Carro
self.M = 1.0
self.D = pow(self.M, 0.33333333)
self.b = 0.05
self.X = 0.0
self.V = 0.0
self.A = 0.0
self.F = 0.0
# Propiedades de Pendulo
self.m = 1.0
self.d = pow(self.m, 0.33333333)
self.l = 1.0
self.t = 0.0
self.v = 0.0
self.a = 0.0
self.It = 0.0
self.Iv = 0.0
# Otros
self.G = 9.8
self.FT = Fraccion
self.Entrenamiento = Estado
self.Activo = Activo
def Actualizar(self):
X = self.X
t = self.t + pi
l = self.l
x = X + sin(t) * l
y = cos(t) * l
M = self.M
m = self.m
D = self.D
d = self.d
circulo.x = x
circulo.y = -y
circulo.d = d
cuadrado.x = X
cuadrado.d = D
linea.x2 = x
linea.y2 = -y
linea.x1 = X
def Calcular(self):
FT = self.FT
F = self.F
G = self.G
M = self.M
X = self.X
V = self.V
b = self.b
m = self.m
l = self.l
v = self.v
t = self.t
if V > 0:
B = b
elif V 0:
B = -b
else:
B = 0
S = sin(t)

C = cos(t)
A = (F - S * C * G * m + S * m * v**2 * l - B *
M * G - B * C * C * G * m + B * C * m * v**2 *
l) / (M + S * S * m + B * C * S * m)
a = S * G - C * A
self.a = a
self.A = A
self.V += A / (2*FT)
self.v += a / (2*FT)
self.X -= V / (1*FT)
self.t += v / (1*FT)
if self.X > 4: self.X = -4
if self.X -4: self.X = 4
if self.t > pi: self.t -= 2*pi
if self.t -pi: self.t += 2*pi
self.F = 0
def Empujar(self, F):
self.F = F

# # # Perceptrón de Control # # #
def Control( t, v, Tiempo ):
global Error
# Inicializa Variables
if not hasattr( Control, "Apr" ):
Control.Apr = Apr
if not hasattr( Control, "Pes" ):
try:
file = open(Archivo, 'r')
Control.Pes = []
Control.Pes += [float(file.readline())]
Control.Pes += [float(file.readline())]
Control.Pes += [float(file.readline())]
Control.Pes += [float(file.readline())]
file.close()
except Exception:
Control.Pes = [random.uniform( -0.125, 0.125 ) for
j in range(4)]
# Calculo del Perceptron
if Tiempo:
Eng = 0
Eng += Control.Pes[0] * t
Eng += Control.Pes[1] * sin(t)
Eng += Control.Pes[2] * v
Eng += Control.Pes[3]
if Sigmoide:
Eng = (2/(1+pow(e,-Eng))-1)
else:
if Eng > 1: Eng = 1
if Eng -1: Eng = -1
return Eng * 1000
# Control de Error y Aprendizaje
else:
# Error
Err = v + t
Dlt = Err * Control.Apr
Error = Err
# Ajuste de los Pesos
Control.Pes[0] += t * Dlt
Control.Pes[1] += sin(t) * Dlt
Control.Pes[2] += v * Dlt
Control.Pes[3] += Dlt
# Guarda lo Aprendido
file = open(Archivo,'w')
file.write(str(Control.Pes[0])+"\n")
file.write(str(Control.Pes[1])+"\n")
file.write(str(Control.Pes[2])+"\n")
file.write(str(Control.Pes[3])+"\n")
file.close()
return 0

# # # Definición de la Ventana # # #
display = pyglet.canvas.get_display()
screen = display.get_default_screen()
config = screen.get_best_config()
window = pyglet.window.Window(config=config)
window.width = 800
window.height = 400
keyboard = key.KeyStateHandler()
window.push_handlers(keyboard)

# # # Creación de Elementos # # #
Carro = Movil()
Carro.Entrenamiento = Estado
circulo = Circulo((0, 1, 1))
cuadrado = Cuadrado((0, 0, 1))
linea = Linea((0, 0, 0, 1))
etiqueta = Etiqueta()
glClearColor(*(1,1,1,1))

# # # Dibujado # # #
@window.event
def on_draw():
global Error
global Fuerza
global Itr
global Ang
window.clear()
# Establece Sistema de Coordenadas
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-400.0, 400.0, -250.0, 150.0, 0, 10)
glMatrixMode(GL_MODELVIEW)
# Dibuja Figuras
circulo.dibujar()
cuadrado.dibujar()
linea.dibujar()
# Dibuja Etiquetas
if Carro.Entrenamiento:
etiqueta.dibujar(-375.0,-75.0,"Entrenando (8/2)")
else:
etiqueta.dibujar(-375.0,-75.0,"En Prueba (8/2)")
if Carro.Activo:
etiqueta.dibujar(-375.0,-125.0,"Aprendiento (7/9)")
else:
etiqueta.dibujar(-375.0,-125.0,"Sin Aprender (7/9)")
if Encendido:
etiqueta.dibujar(-375.0,-175.0,"Trabajando (5/0)")
else:
etiqueta.dibujar(-375.0,-175.0,"Libre (5/0)")
etiqueta.dibujar(-75.0,-75.0,"Error: " + str(Error))
etiqueta.dibujar(-75.0,-125.0,"Angulo: " + str(Ang))
etiqueta.dibujar(-75.0,-175.0,"Ciclo: " + str(Itr) + "
Fuerza: " + str("{0:.2f}".format(Fuerza)))

# # # Actualización y Control Manual # # #


def update(value):
global Encendido
global Fuerza
global Itr
global Ang
if not hasattr(update, "running" ):
update.running = False
if keyboard[key.NUM_8]:
Carro.Entrenamiento = 1

Carro.Activo = 1
Encendido = 1
elif keyboard[key.NUM_2]:
Carro.Entrenamiento = 0
Carro.Activo = 0
update.running = False
elif keyboard[key.NUM_5]:
Encendido = 1
elif keyboard[key.NUM_0]:
Encendido = 0
Carro.Activo = 0
Carro.Entrenamiento = 0
update.running = False
elif keyboard[key.NUM_7]:
Carro.Activo = 1
Encendido = 1
elif keyboard[key.NUM_9]:
Carro.Activo = 0
Carro.Entrenamiento = 0
update.running = False
elif keyboard[key.NUM_4]:
Fuerza = 20
Carro.Empujar(Fuerza)
elif keyboard[key.NUM_6]:
Fuerza = -20
Carro.Empujar(Fuerza)
elif keyboard[key.NUM_1]:
Carro.t = random.uniform( 0, t_ini )
Carro.v = random.uniform( 0, v_ini )
elif keyboard[key.NUM_3]:
Carro.t = random.uniform( -t_ini, 0 )
Carro.v = random.uniform( -v_ini, 0 )
elif keyboard[key.PAGEUP]:
Carro.m += 0.1
if Carro.m > 10.0: Carro.m = 10.0
Carro.d = pow(Carro.m, 0.3333333333333333)
elif keyboard[key.PAGEDOWN]:
Carro.m -= 0.1
if Carro.m 0.1: Carro.m = 0.1
Carro.d = pow(Carro.m, 0.3333333333333333)
# Ciclo de Trabajo
if update.running:
if Carro.It > 0:
if (Carro.v)>=0 or (Carro.t)=0:
update.running = False
elif Carro.It 0:
if (Carro.v)=0 or (Carro.t)>=0:
update.running = False
else:
update.running = False
# Ciclo de Control
else:
# Evaluacion y Ajuste
if Carro.Activo:
Control(Carro.It, Carro.Iv, 0)
# Inicializacion del Carro
if Carro.Entrenamiento:
Carro.X = 0.0
Carro.V = 0.0
Carro.A = 0.0
Carro.t = random.uniform( -t_ini, t_ini )
Carro.v = random.uniform( -v_ini, v_ini )
Carro.a = 0.0
Carro.It = Carro.t
Carro.Iv = Carro.v
# Dispara Respuesta del Control Automatico
if Encendido:
Fuerza = Control(Carro.It, Carro.Iv, 1)
Carro.Empujar(Fuerza)
# Control de Ciclos
if Carro.Entrenamiento:
Itr += 1
if Itr > Ciclos:
Carro.Entrenamiento = 0
else:
update.running = True
Carro.Calcular()
Carro.Actualizar()
Ang = Carro.t

# # # Arranque de Programa # # #
pyglet.clock.schedule_interval(update, 1.0/Fraccion)
pyglet.clock.set_fps_limit(Fraccion)
pyglet.app.run()

Tabla de Contenido
7. Tiempos de Trabajo del Perceptrón:

En los Libros Anteriores ya trabajamos estos dos momentos en los que trabaja el Perceptrón, solo que los trabajamos
uno tras otro. No parese importante y te puede pareser obvio, pero lo remarco por la relevancia que tiene y porque a
algunos les cuesta trabajo identificar estos momentos para hacer eficiente el funcionamiento del Perceptrón.

Al diseñar e integrar el Perceptrón en nuestra aplicación, debemos identificar el mejor momento para que el Perceptrón
lea las variables para realizar los cálculos, e igual de importante es identificar en que momento realizamos la
comparación entre el resultado obtenido y el que queremos. Hasta ahora esta apreciación no había sido necesaria, pues
realmente hemos estado alimentando en los algoritmos anteriores, los datos de ambos momentos al mismo tiempo.

Pues bien, como casi todos los problemas, hay más de una manera de resolverlo. Por lo pronto te quiero decir que
simplemente lo podríamos hacer como los anteriores y a la vez hacer ambos, y funcionará como más adelante lo
probaremos, pero el fin de esta serie es enseñarte de manera de ir incorporando conocimiento que te pueda ser útil, en
ejemplos prácticos y permitirte compararlos y que tú saques tus propias conclusiones en lugar de solo darte las mías.

Además de que hacerlo en dos tiempos tiene sus ventajas, para comenzar, menor monitoréo y control, requiere menos
tiempo de cómputo, y en este ejemplo solo es un elemento a monitorear y solo una acción a realizar, pero imagínate
cuando estemos trabajando con un robot completo, que realiza acciones mientras camina, que ya implica monitorear
visión, y con ello es necesario monitorear y controlar una serie de sensores, con sus respectivas implicaciones, las que
tiene diferentes prioridades, pues el poder reducir el monitoréo y control de una acción, cobra relevancia.

Pues ahora simplificando lo que queremos es crear un ciclo en el que el Perceptrón lee las variables elegidas, regresa al
Simulador la magnitud de Fuerza que debe aplicar, el Simulador la aplica produciéndose un movimiento. Pues
trabajaremos con esto. Por lo que comenzaremos el ciclo leyendo las variables, sin importar como esté (para este
sencillo ejemplo). El Simulador hará lo suyo, ¿Y? ¿Cómo saber que ya ha terminado?

Pues como lo que queremos es que alcance el Péndulo la vertical y permanezca, prevemos que de una posición
diferente al ser empujado se dirija a esta posición, y que puedan pasar que el empuje sea contrario a lo requerido, que el
empuje no sea suficiente y no llegue a la vertical, o bien que el empuje sea demasiado y que se pase de la vertical.
Ahora que lo sabemos, buscamos las variables que lo representen, que será cuando la Velocidad del Péndulo sea Cero o
contraria en signo a la requerida, según el signo del Ángulo del Péndulo o que el Ángulo sea Cero, ahora que si ambos
son Cero, es que lo logramos, si no, volveremos a ingresar las variables al Perceptrón y comenzamos de nuevo, con lo
que ya tenemos nuestro ciclo de trabajo del Perceptrón.

Recordemos que el Perceptrón trabaja solo con datos numéricos, por lo que para poderlo trabajar, lo tenemos que poder
cuantificar. Objetivos claros y cuantificados en variables. Pues el primer ejercicio que te propongo, es que identifiques
lo anterior en el código, para que te familiarices con él.

Tabla de Contenido
8. Variables a Ingresar al Perceptrón:

Ya identificamos los tiempos en los que el Perceptroń leerá Variables, el final, cuando ó el Ángulo ó la Velocidad sea
Cero, y el de inicio en el momento siguiente. Ahora, ¿Qué variables debe procesar el Perceptrón?

No siempre las variables que nos permitan saber los tiempos del Perceptrón serán las ideales a ingresar en el Proceso
del Perceptrón, pero en este caso lo son. Sinembargo, cuando te sea posible te sugiero los datos que le entregues al
Perceptrón sea refinados y filtrados, de tal manera que el Perceptrón con ello tenga en cada dato la proporción, y con
ello pueda representar lo que está pasando, en lo que a su trabajo respecta.

En este caso además del Ángulo y la Velocidad, el sistema es afectado por la Gravedad, y aunque es constante, la
proporción en la que afecta al sistema, esta en función del Ángulo. Ves, si nosotros alimentamos la Gravedad
directamente el Perceptrón no tendrá manera de saber en que proporción afectará y solo resultaría en un dato fijo sin
utilidad y lo terminaría descartando. Podríamos también omitirlo y el Perceptrón tendría que hacer más trabajo para
distinguir que el Ángulo tiene una implicación más e implicar en sus cálculos que a mayor Ángulo hay una Fuerza
implícita que se incrementa. Lo lograría, pero con mayor Trabajo.

También podríamos calcularle la magnitud de la Gravedad, y como para este sistema el Ángulo Cero es la Vertical,
multiplicar la Gravedad por SIN(T). Sinembargo la forma de Trabajar del Perceptrón, no requiere el cálculo real, lo que
ocupa, es solo la proporción en la que este dato afecta, con lo que será suficiente que le entreguemos para cálculo
SIN(T).

Es posible tanto trabajar con los datos en Bruto, como entregarle la pura Proporción, como fracción de la Unidad, y el
Perceptrón se adaptará; solo debemos asegurarnos de que si usamos los datos en Bruto, de reducir la proporción de
Aprendizaje, para que el Ajuste resulte en una aproximación adecuada.

Algo curioso con el Perceptrón, es que como trabaja con Proporciones, y después de realizar los procesos, las variables,
si se seleccionaron adecuadamente, deberían reducirse en la misma proporción que el Error, lo que hace que podamos
tomar las variable para cálculo como quedaron después del proceso. Por ejemplo en el Código que te proporciono para
poder tomar las variables con las que inicia el cálculo al principio y al final, en los dos tiempos del Perceptrón, creo las
variables (It, Iv), en lugar de usar directamente (t y v).

Con lo que te recomiendo tomes para tu conocimiento la relevancia que tiene la Proporción para el Perceptrón y
reflexiona un poco sobre esto.

Tabla de Contenido
9. Definición del Cálculo del Error:

Pues ya sabemos, con que variables alimentar al Perceptrón, de que manera alimentarlas, ahora lo que falta es definir
como calculamos el Error. En especial en este punto cobra importancia el saber que queremos y que sea algo medible,
de otra manera como decirle al Perceptrón que esta mal, y que tan mal, o bien, y que tan bien. Usualmente será una
fórmula en la que simplemente se relacionen las Proporciones de las Variables de alimentación, sin embargo, así como
(SIN(T)) representó la Proporción en a que afecta la Gravedad, sin la Gravedad, encontraras situaciones en las que una
sola variable representará mejor el Error, que una relación entre todas las variables alimentadas, para comenzar porque
requiere menos cálculos. En este caso escogí la suma de las Proporciones de Velocidad y de Ángulo, e ignoro la
Proporción de la Gravedad, en este caso porque es esperado que sea Cero, ¿Ahora qué? ¿Que tanto beneficia al cálculo?

A veces el impacto de agregar variables es reducido, yo acostumbro tomar el criterio de, suficientemente bueno y
económico en demanda de tiempo de cómputo. Claro que el criterio debe de ser de acuerdo a lo demandante de
velocidad y precisión que sea la aplicación a la que se incorpore el Perceptrón.

Tabla de Contenido
10. Función de Activación o Transferencia:

Siendo que lo que una función aporta es la proporción en la relación entre lo que calcula el Perceptrón y lo que entrega,
lo que a su vez repercutirá en la secuencia de aprendizaje: salida, diferencia o error, y ajuste; esta proporción en la
Etapa de Entrenamiento, por un lado, hará que en los rangos en los que la relación entre la energía calculada y la salida
de la función sea más alta, el Perceptrón con menos ajustes pueda acercarse a los valores esperados, requiriendo menos
ciclos para aprender; y por otro lado, que en el rango en el que la función mantiene una proporción menor, el
Perceptrón requiera más ajustes para poder acercarse al valor esperado; con lo que este efecto puede ser usado a favor,
pues se pueden usar funciones con proporción menor de cambio en los rangos donde se requiere en el Aprendizaje un
ajuste más fino y corresponda un cambio mayor en los rangos donde es útil un aprendizaje más acelerado; esta
combinación en conjunto, cuando es adecuada la función, permitirá que el Perceptrón tenga mejores resultados tanto en
la velocidad de aprendizaje como en la precisión de su respuesta.

Otra aportación es que cuando usamos una función que presenta asíntotas (valores a los que indefinidamente se acerca
pero nunca llega), no llegue el Perceptrón a los valores no deseados, que propicien desborde. Como había comentado
en el Libro Pasado, esto nos proporciona una protección contra una oscilación descontrolada del Perceptrón, en especial
cuando la ajustamos para que las asíntotas se encuentren en (0 y 1) o bien en (-1 y 1), según el algoritmo que
trabajemos del Perceptrón, ya que los números que se multiplican entre sí, menores a (1) resultarán menores a (1), y los
números mayores a (1) multiplicados entre sí darán números mayores a (1); a priori no parese gran cosa, pero cuando
estamos hablando de miles de multiplicaniones, esto nos permite imaginarnos porque el Perceptrón puede
repentinamente dar valores incrementalmente más altos y los ajustes se queden cortos para impedir que el Perceptrón
entre un ciclo incremental del que no regrese, y si bien en muchos casos lo podremos controlar reduciendo el valor del
Aprendizaje, el usar este tipo de funciones no solo nos dan la comodidad de despreocuparnos de esto, además tienen
otras aportaciones como ya comente.

En particular para el caso del Péndulo Invertido, la Función Sigmoide es muy adecuada, pues existe una proporcion
directa entre la cantidad de impulso requerido y el SIN(t), es decir cuando el Ángulo es mayor, se requiere una Fuerza
mayor, y la tolerancia a fallar, es también mayor en este rango; mientras que para cuando el Ángulo es menor, no solo
la Fuerza requerida es también menor, además la tolerancia también es menor, lo que perfectamente coincide con
ajustes más finos, lo que corresponde a este otro rango de la Función Sigmoide.

Por ahora para escoger una función nos concentraremos en lo siguiente:

Valores o rangos de valores en los que queremos trabaje el Perceptrón: binario (0 y 1), binario (-1 y 1), rango de
(0 a 1), rango de (-1 a 1), u otro rango.
Valores en los que la función tiene asíntota
Rangos en los que tiene la función una mayor proporción de incremento a entregar con respecto a la Energía del
Perceptrón
Rangos en los que tiene la función una menor proporción de incremento a entregar con respecto a la Energía del
Perceptrón

Haciendo una pequeña clasificación podemos dividir las Funciones de Activación de la siguiente manera:

Identidad: Es con la que trabajamos en el Libro pasado, en la que se ocupa directamente la energía que arroja
el Perceptrón, para poder hacer una comparación directa en este Libro lo incluiré en los ejemplos para que sea
más clara la comparación.
Escalera: Es cuando la salida la comparas contra un Umbral, a partir del cual entrega un determinado valor,
que sería como fue usado en el Primer Libro. Aunque yo en lo personal considero a las Funciones de Activación
independientes de los Umbrales, pues, después de aplicar una función de Activación, aún puedes aplicar un
Umbral y a partir de tal tomar un determinado valor.
Gausianas, Cuadráticas, Sinusoidal: Este tipo de funciones pueden tomar una gran variedad de formas y en
casos en especial puede dar al Perceptrón la venaja de tener una mejor aproximación a determinados rangos de
valores, mientras que en otros rangos, se aproximarán con incrementos mucho menores, lo que permitirá un
ajuste mejor en estas condiciones. Aplicarlas requiere de más conocimiento de la aplicación en si, del
comportamiento de la función a emplear, así como del comportamiento del Perceptrón mismo. Yo lo considero
un tema avanzado, que requiere de mayor conocimiento matemático y experiencia trabajando con Perceptrones.
Sigmoides: Son las que pondremos a prueba en este Libro. Su nombre viene de su similitud con una "S", y son
varias las que producen este efecto. Cuando se trabaja en el rango de (0 a 1) es común: 1 / 1 + (e)^-x; cuandos
se trabaja en el rango de (-1 a 1) es común la tangente hiperbólica: ( (e)^x - (e)^-x ) / ( (e)^x + (e)^-x ).
Combinaciones: adicionalmente podemos encontrar que hay quien por un extremo aplica una y por el otro otra
función, e incluso que aplican una función por rango. Como te comento puede haber ventaja en esto, pero
requiere mayor conocimiento y experiencia.

Nosotros comenzaremos a trabajar con la Función Sigmoide, que tiene una forma al graficarla como de una "S"
alargada en lo horizontal, en realidad existen varias funciones que toman esta forma y por lo tanto este nombre, sin
embargo la más usada es: e^x / (e^x + 1); que es equivalente a 1 / (1 + e^-x); ahora que esto es útil si vamos a trabajar
con valores para el Perceptrón entre (0 y 1), y para este particular caso estamos trabajando el rango de (-1 a 1). Las
siguiente son algunas de las funciones que nos pueden ayudar a dar una idea de que tan diferente puede ser la respuesta
con unas y otras funciones.

Funciones para rangos de (0 a 1)

y = 1/(1+e^-x)
y = (x÷(1+|x|))/2 + 0.5
y = (x÷√(1+x^2)/2 + 0.5
y = ((2÷pi)arctan((pi÷2)x))/2 + 0.5

Funciones para rangos de (-1 a 1)

y = x÷(1+|x|)
y = x÷√(1+x^2)
y = (2÷pi)arctan((pi÷2)x)
y = 2/(1+e^-x) - 1

Como veras las funciones se pueden convertir de un rango a otro fácilmente, solo es necesario ampliar o reducir el
rango y recorrerlo con aritmética, esto te será más comprensible si lo graficas en un plano de coordenadas, lo que
además te ayudará cuando selecciones tu Función de Activación.

Recuerda cuando decidas usar funciones sin asíntotas topar los valores a (-1 y 1) para que el Perceptrón no se desborde,
igual que lo hice para cuando no ocupo la función de activación; y claro antes de entregar el valor al Simulador
debemos convertir el valor al rango de fuerza del motor para que pueda ser utilizado, en nuestro caso por (1,000).

Por otro lado debemos de tomar en cuenta que estamos trabajando con una sola neurona, y que su capacidad de
respuesta es lineal, con esta limitante, notaremos que en algunos casos su respuesta no es óptima a pesar de que entrene
con un valor de aprendizaje muy fino y con grandes ciclos de aprendizaje. Por lo menos no en una sola respuesta, en la
que con un solo impulso del motor alcance la vertical sin pasarse, pero si en una serie de aproximaciones sucesivas, en
las que primero se acerque a la vertical, y si se pasa, haga pequeños ajustes para conservarla. Ahora que con un
Perceptrón de varias capas podremos lograr una mejor respuesta y a problemas más complejos, lo que veremos en
Otros Libros.

Tabla de Contenido
11. Entrenamiento y Controles:

Una vez completado el programa, lo podrás correr y controlar con la teclas del apartado numérico, y lo primero que
veras será en el centro, arriba, el Carro con Péndulo Invertido equilibrado, esto es un poco irreal, pues no esta operando
el Perceptrón y no se cae, es porque justamente esta a la mitad, en la vida real no ocurriría, y basta con darle un
pequeño empujón para que ya no pueda regresar a este estado.

Los empujones laterales por el Control Manual, se dan con el [4] hacia la Izquierda y con el [8] hacia la derecha, con
estos controles, si gustas puedes intentar equilibrar el Péndulo, es posible, pero igual que el Perceptrón requiere de
Entrenamiento y lo lograrás, sin embargo, con estos sencillos controles estas en desventaja, pues no ofrecen control
sobre la magnitud del empuje que das, puedes ajustar la magnitud, y con las teclas solo se controla el momento en que
se aplica la fuerza.

Lo siguiente que es deseable ver, es su primer Entrenamiento, que le permitirá al Perceptrón equilibrar el Péndulo
Invertido. El Entrenamiento se activa presionando la tecla [8], con lo que comienza con lo que tiene preconfigurado, lo
que consta de (1,000 ciclos), con un Aprendizaje de (0.001), con la Función de Activación, rangos angulares (de +1 a
-1 radianes), y rangos de velocidad (de +0.1 a -0.1 m/s). Con esta configuración bastará para que el Perceptrón Aprenda
a equilibrar el Péndulo Invertido, y enseguida te diré como ponerlo a prueba. También si gustas como parte de las
pruebas que le puedes realizar, puedes interrumpir el Entrenamiento con la tecla [2], de manera que lo vayas probando,
digamos a cada (100 ciclos), lo paras, lo pruebas, y lo vuelves a poner a entrenar, para ir comparando.

La forma de poner a prueba el Perceptrón, será desequilibrando el Péndulo, para lo que puedes usar las teclas [1] para
inclinarlo hacia la Izquierda y [3] para inclinarlo hacia la Derecha. Es importante hacerte notar que esta diseñado para
que el Perceptrón lo levante desde ángulos de la vertical (de +1 a -1 radianes), por lo que fuera de este rango puede
llegar a levantarlo, pero lo normal es que no solo no lo haga, además puede al querer hacerlo acelerar demasiado,
hacerlo que quede el Péndulo girando a alta velocidad, e incluso hacer que el programa falle o se trabe, a lo que la
mayoría de las veces bastará con presionar la tecla [8], Entrenamiento, para que se desbloquee, o vuelva a funcionar.

Una vez terminado el Perceptrón el Entrenamiento, quedará funcionando, listo para ser probado, aunque lo puedes
apagar, para que salga de equilibrio con la tecla [0], y reactivarlo con la tecla [5], lo que te permitirá realizarle otro tipo
de pruebas al Perceptrón, a diferentes ángulos y veolocidades de caida, al combinar con empujones que le des antes de
encender el Perceptrón.

También tenemos las teclas [7] para activar el Aprendizaje y [9] para desactivarlo, lo que opera claro con el Perceptrón
Trabajando.

Y por último, veremos las teclas [PAGEUP] y [PAGEDOWN], con las que aumentarás la dificultad para el Perceptrón,
incrementando y decrementando la Masa del Péndulo.

Ejercicios:

El siguiente ejercicio que te propongo, es quitar al Perceptrón del cálculo, con su respectivo Peso y Ajuste, la
Entrada (sin(t)). Lo que te permitirá seguir familiarizándote con el código, y notarás el impacto de la selección
de Entradas al Perceptrón.
Algo curioso con el Perceptrón, es que como trabaja con Proporciones, y después de realizar los procesos, las
variables, si se seleccionaron adecuadamente, deberían reducirse en la misma proporción que el Error, lo que
hace que podamos tomar las variable para cálculo como quedaron después del proceso. Por ejemplo en el
Código que te proporciono para poder tomar las variables con las que inicia el cálculo al principio y al final, en
los dos tiempos del Perceptrón, creo las variables (It, Iv). Pues te propongo el siguiente ejercicio, para que
pruebes esto, usa en lugar de (It y Iv) directamente (t y v).
Al calcular el Error, el siguiente ejercicio que te sugiero, es que cambies la fórmula de Error, y que pruebes con
diferentes variables y diferentes formas de relacionarlas, como sumas y multiplicaciones, solo recuerda que
representen Proporción, comenzando con agregar (SIN(T)) a la suma. A veces el impacto de agregar variables
es reducido, yo acostumbro tomar el criterio de, suficientemente bueno y económico en demanda de tiempo de
cómputo. Claro que el criterio debe de ser de acuerdo a lo demandante de velocidad y precisión que sea la
aplicación a la que se incorpore el Perceptrón.

Tabla de Contenido
12. Comparando con y sin Función de Activación:

La Función de Activación no está incluida en las teclas, pues cambiar el ponerla o no, cambia el comportamiento del
Perceptrón y los Pesos de Uno no son adecuados para el Otro. Por lo que para cambiarlo es necesario parar el
programa, cambiar la variable [Sigmoide], en (1) para que Trabaje con Función de Activación y (0) para que No.

Pues ahora que haz corrido el Entrenamiento con Función de Activación, y observaste su respuesta, ahora borra o
cambia el nombre del Archivo de Pesos (Pesos.pes), y cambia el valor de la viariable (Sigmoide a 0), y corre
nuevamente el programa y activa el Entrenamiento con la tecla [8], con lo que verás la enorme diferencia y las
cualidades de la Función de Activación.

Ahora si quieres que trabaje mejor el Perceptrón sin la Función de Activación, es posible, para comenzar corriéndolo
más ciclos, mejorará, aunque solo al principio, después para seguir mejorando, será necesario hacer más pequeño el
valor de Aprendizaje. Podría se algo como: (10,000 ciclos con Apr=0.001) y (10,000 ciclos con Apr=0.0001). Puedes ir
probando cada (1,000 ciclos), para que veas como se comporta.

Lo que ahora debemos resaltar es que no todas las Funciones de Activación funcionan igual de bien con cada
Perceptrón, en cada situación, aún siendo Sigmoides.

Ejercicio: Para comprobarlo, la siguiente serie de ejercicios será cambiar la fórmula de la Función de Activación e ir
comparando. Los elementos con los que puedes comparar además de los ciclos necesarios para levantarlo, pueden ser el
Ángulo al que llega cuando ya lo está equilibrando, la Fuerza que tiene a usar y la magnitud del Error.

Otro aspecto a tomar en cuenta cuando no es significativa la diferencia entre dos Funciones de Activación, como
decidir cual usar. Yo te recomiendo: De lo suficientemente bueno, lo más económico en tiempo de cómputo.
Recordemos que esta es solo una neurona y se corre la Función de Activación una vez por cada Neurona, cada vez que
se activa; después de todo una vez entrenado el Perceptrón si con dos funciones trabaja igual de bien, la diferencia
trabajando, ya solo será cual trabaja más rápido, aunque se hubiera tardado (10 veces) más en Aprender. Por otro lado
no hay una regla absoluta, y a veces queremos que el Perceptrón siga aprendiendo permanentemente.

Tabla de Contenido
13. Entrenamiento con Respuesta Inmediata:

Como habíamos comentado, también se puede Entrenar con respuesta inmediata, aunque no sea tan eficiente en
consumo de tiempo de cómputo, pero lo mejor es tener alternativas y cuando llega el momento tenemos más de donde
elegir para lograr del Perceptrón un desempeño adecuado.

Pues bien, si analizas el código, veras que una vez terminado el Entrenamiento entra el Perceptrón en un ciclo envía la
Fuerza de actuación al Simulador, este calculo y el Perceptrón entra a leer las variables y evaluar, en el mismo ciclo.

Ejercicio: Si pones al Perceptrón a Aprender estando en la vertical, presionando las teclas [5] para que trabaje el
Perceptrón y [7] para que Aprenda, y lo dejas trabajando en la vertical, verás como cada vez ocupa menos Fuerza para
mantenerlo en la vertical, Trabaja en un menor Ángulo, y con un menor Error; y no solo mientras esta aprendiendo.
Apaga el Aprendizaje presionando la tecla [9], y comienza a desbalancearlo con las teclas [1] y [3], y observa como es
más común que recupere la vertical con un menor Ángulo, menos Fuerza y con menor Error.

Tabla de Contenido
14. Ventajas del Aprendizaje Permanente:

Hay un par de teclas que no hemos usado, son para cambiar la Masa del Perceptrón, [PAGEUP] aumenta la Masa y
[PAGEDOWN] la disminuye. Cuando ha Entrenado el Perceptrón, sin cambiar la masa ya lo hace bien dentro del rango
de Ángulos razonables. Ahora probemos con variantes adicionales. Ve incrementando la Masa del Perceptrón y
desequilíbralo. No lo hace mal, pero lo puede hacer mejor, porque no ha Entrenado para esto, pues la forma de que
mejore es Entrenando en estas nuevas condiciones, y se adaptará, sin embargo con las limitantes de este pequeño
Perceptrón, una vez vuelvas a cambiar la Masa tendrá que volver a Aprender para ajustarse a las nuevas condiciones, lo
cual es de por sí ya útil, pero aún lo puede hacer mejor. Te propongo un nuevo ejercicio, modifica el código en dos
puntos, el primero es para generarle un Entrenamiento más variado, el segundo es para que en las Proporciones de las
Entradas del Perceptrón se incluya la Masa.

Para el Entrenamiento:

Incluye en la configuración variables para el rango mínimo y el máximo. Como se hace para (It y Iv) en los "#
Parámetros Iniciales", agregando la línea "m_ini = 10.0", poniendo el mayor valor del rango.
En el "# Ciclo de Control" de la Función "update", en "# Inicializacion del Carro" agrega una línea para la
generación pseudoaleatoria del valor "Carro.m = random.uniform( -m_ini, m_ini )". También como se hace
para (It y Iv).
Después, en la siguiente línea de código actualiza la Dimensión graficada, para que sea proporcional. Sigue la
lógica del código, es lo que se hace para las teclas [PAGEUP] y [PAGEDOWN], agregando la línea "Carro.d =
pow(Carro.m, 0.3333333333333333)" tambien en "# Inicializacion del Carro" en la función "update".
Y en "# # # Definición de Movil # # #", en "# Propiedades de Pendulo", agrega la línea "self.Im = 0.0"; para
tener el valor para su evaluación.

Para las Entradas del Perceptrón:

Agrega un Peso más al Leer el Archivo, agrega una línea más, con "Control.Pes += [float(file.readline())]", en
"try:", en "# Inicializa Variables", del "# # # Perceptrón de Control # # #", para que sean 5.
Agrega la variable de Masa, tanto en la llamada de la función de Control del Perceptrón, como en su definición.
Para que quede "def Control( t, v, m, Tiempo ):" en "# # # Perceptrón de Control # # #"; y
"Control(Carro.It, Carro.Iv, Carro.Im, 0)", tanto en "# Evaluacion y Ajuste", como en "# Dispara
Respuesta del Control Automatico".
Multiplica la Masa por el Nuevo Peso como Entrada en "# Calculo del Perceptron" de "# # # Perceptrón de
Control # # #". Agregando una línea más con "Eng += Control.Pes[4] * m".
Incluye la Masa y el Nuevo Peso en "# Ajuste de los Pesos" de "# # # Perceptrón de Control # # #".
Agregando la línea "Control.Pes[4] += m * Dlt".
Y finalmente, agregaremos una línea más para guardar el Peso adicional con
"file.write(str(Control.Pes[3])+"\n")" en "# Guarda lo Aprendido" de "# # # Perceptrón de Control # # #".

Con lo anterior le darás una mayor capacidad de adaptarse al Perceptrón con los cambios de Masa del Péndulo, con lo
que mejorará su respuesta.

Conocer estas alternativas y capacidades, en este caso en particular en cuanto al equilibrio se refiere, al Trabajar con los
Perceptrones como formas de Control Automático de diferentes dispositivos, nos permitirá crear mejores Perceptrones
y más adecuados para nuestros proyectos. Imagínate que solo estamos trabajando con Una Sola Neurona, que podrás
hacer con una Red Neuronal con una Topología adecuada bien enfocada, cuando quieras hacer caminar un robot por
ejemplo, mientras esta moviendo carga útil, o que se tenga que enfrentar a variantes en el camino, como un resbalón o
empujón, o tener que compensar una avería en un músculo. En fin el potencial es grande si se sabe manejar bien.

Tabla de Contenido
15. Configuración en Espejo:

Como te habrás dado cuenta el Perceptrón está trabajando ambos lados del Péndulo, y lo hace bien; sinembargo no es la
única forma de hacerlo e incluso no la mejor. Lo trabajé de esta forma para que vayas conociendo diferentes formas de
trabajar el Perceptrón, y aquí viene la otra y más eficiente, lo que nos da lugar a proponerte un nuevo ejercicio.

Ejercicio: Ya que el Carro con Péndulo Invertido es totalmente simétrico, te propongo modifiques tu código para que
lo pongas a trabajar de un solo lado, desde el punto de vista del Perceptrón, y que por medio del Signo del Ángulo, por
Fórmula, aplicando el signo a la Fuerza, completes la otra parte. Es sencillo pero no trivial, y el impacto en el
desempeño del Perceptrón con algo así, dependerá de la dificultad de lo que le pongas. En este caso no es muy
impactante en desempeño, se notará más en un Perceptrón cuando las variantes que tiene que aprender hacen que
requiera más variantes con ajustes más finos, pues estarás duplicando su capacidad.

Tabla de Contenido
16. Modelado Matemático del Simulador

La importancia de un modelo matemático radica en que represente el comportamiento de las variables con las que
queremos trabajar y que son las que a su vez determinan el del sistema, por lo menos en la parte que nos interesa
controlar, y que lo haga lo suficientemente bien, para que sea el Control que consideremos útil en la realidad. La otra
parte a tomar en cuenta, por eficiencia de nuestro esfuerzo, es la sencillez, de manera que nuestro esfuerzo lo
apliquemos en el desarrollo del Control, más que en una simulación perfecta, sobre todo porque suele ser posible cubrir
las imperfecciones de la simulación, ya en el modelo real, sobre todo porque contamos con un Perceptrón, que tiene
esta capacidad. Lo que puede hacer que sea crítico el que la simulación sea una copia fiel de la realidad, es cuando
esten en juego vidas, o recursos o equipos difíciles de remplazar; lo que incluso se puede en ocasiones cubrir en parte
tomando precauciones para minimizar riesgos durante el entrenamiento, como lo pueden ser colgarlo de lineas de
seguridad que no permitan que llegue a caer, pero si le permita moverse como para aprender de las caidas sin la parte
final de recibir el daño.

A continuación describo el proceso de una forma para llegar a la representación del modelo que nos servirá para
realizar la simulación y con él las pruebas. No es indispensable que lo entiendas al 100% para poder trabajar con el
Entrenamiento y Pruebas del Perceptrón, pero creo que te servirá darte una idea, así que te recomiendo le des una leída.
Tampoco es indispensable que estés de acuerdo con las ecuaciones que ocupo, y fácilmente las puedes cambiar, en una
busqueda abierta en internet puedes encontrar varias opciones o usar la tuya, lo importante es tener un modelo que se
asemeje lo suficiente a la realidad como para que puedas poner a prueba el Perceptrón y la Función de Activación
Sigmoide.

Nuestro modelo representará un Péndulo con libertad de movimiento en dos dimensiones, por lo que podrá realizar una
rotación de (360°), además del desplazamiento horizontal por estar montado sobre un Carro, el que se moverá solo en
linea recta, por lo que tendremos dos grados de libertad, considerando la fricción o rozamiento, solo en el
desplazamiento del Carro, no pongo en el Péndulo fricción, lo que haría que el equilibrio se facilitara un poco al
retardardarse ligeramente la perdida de balance. Las variables a considerar serán:

Dadas al Sistema:

G La atracción de la Gravedad
F La fuerza de empuje al Carro
M Masa del Carro
R Coeficiente de Rozamiento del Carro
X Posición en X del Carro
m La masa del Péndulo
l La longitud del Péndulo
t El ángulo del Péndulo con respecto a la vertical

Calculadas:

V Velocidad del Carro


A Aceleración del Carro
v velocidad angular del Péndulo
a aceleración angular del Péndulo

Se simplificará la fórmula al tomar para la simulación un Péndulo con una masa puntual al extremo, lo que implica que
no tomaremos para el cálculo masa alguna para la barra que ensambla con el Carro.

Para facilitar la distinción ocuparé para el Péndulo letras minúsculas y para el resto mayúsculas. La lógica que
buscaremos representar en el sistema, será la de la interacción que buscamos. Por un lado introduciremos un empuje,
que será la única forma de interactuar con el sistema, ya sea por nosotros o por el Perceptrón, una vez dadas las
condiciones iniciales, a lo que el sistema corresponderá con una aceleración, tanto en el Carro, como en el Péndulo, es
con esta aceleración con la que propiciaremos por una parte, contrarrestar el movimiento que tenga ya el Péndulo en el
momento, dandole movimiento en dirección de la vertical, buscando este sea mínimo, de manera que en el trayecto se
vaya contrarestando con el de la gravedad y al llegar a la vertical, idealmente, ya no requiera fuerza excesiva que lo
haga mantener la vertical. Así que necesitamos dos ecuaciones en las que podamos introducir los datos que tenemos,
una que nos dé la aceleración del Carro, y otra que nos dé la del Péndulo. Ahora partiremos de la interacción:

Primera Ecuación: Igualamos la Fuerza de empuje que aplicamos a la suma de las fuerzas en las que se ocupa ese
empuje, con lo que nos queda.

(Fuerza de Empuje) = (Empuje en Carro) + (Contra Empuje por Rozamiento) + (Empuje en Péndulo)

(Fuerza de Empuje) = F
(Empuje en Carro) = M * A
(Contra Empuje por Rozamiento) = (Dirección) * (Coeficiente de Rozamiento) * ((Peso de Carro) + (Peso de
Péndulo) + (Centrífuga del Péndulo))
(Dirección) = V/abs(V)
(Coeficiente de Rozamiento) = R
(Peso de Carro) = M * G
(Peso de Péndulo) = abs(cos(t)) * m * G
(Centrífuga del Péndulo) = -cos(t) * m * v2 * l
(Empuje en Péndulo) = (Carro en Péndulo) + (Gravedad en Péndulo) + (Centrífuga del Péndulo)
(Carro en Péndulo) = abs(sin(t)) * m * A
(Gravedad en Péndulo) = sin(t) * (cos(t) * m * G)
(Centrífuga del Péndulo) = -sin(t) * m * v2 * l

Llegando a:

F = ( M * A ) + ( V/abs(V) * b * ( (M * G) + (abs(cos(t)) * m * G) - (cos(t) * m * v**2 * l) ) ) + ( (abs(sin(t)) * m * A)


+ ( sin(t) * cos(t) * m * G ) - ( sin(t) * m * v**2 * l ) )

La trabajamos un poco:

F = A ( M + abs(sin(t)) * m ) + ( V/abs(V) * b * ( (M * G) + (abs(cos(t)) * m * G) - (cos(t) * m * v**2 * l) ) ) + ( sin(t)


* cos(t) * m * G ) - ( sin(t) * m * v**2 * l )

Despejamos la Aceleración del Carro:

A = ( F - ( V/abs(V) * b * ( (M * G) + (abs(cos(t)) * m * G) - (cos(t) * m * v**2 * l) ) ) - ( sin(t) * cos(t) * m * G ) + (


sin(t) * m * v**2 * l ) ) / ( M + abs(sin(t)) * m )

Segunda Ecuación: Ahora obtenemos la aceleración del Péndulo.

(Aceleración del Péndulo) = (Gravedad sobre el Péndulo) + (Aceleración transferida del Carro)

(Aceleración del Péndulo) = a


(Gravedad sobre el Péndulo) = sin(t) * G
(Aceleración transferida del Carro) = cos(t) * A

Llegando a:

a = sin(t) * G - cos(t) * A

Si quisiéramos aplicar la formula con todo el rigor, en estos términos de representación física, requeriríamos realizar la
integral por el rango de tiempo que quisiéramos calcular para nuestras ecuaciones, pero ya que no requerimos de tanta
precisión, linearizaremo el cálculo, esto es, lo tomaremos por la fracción de tiempo que calcularemos como si el
desplazamiento del Péndulo fuera en linea recta, con lo que perderemos en este calculo es lo correspondiente a la
modificación que deberían sufrir nuestras variables al recorrer esta distancia linealmente, contra el movimiento circular
que en realizad experimenta, la diferencia por lo tanto será mayor entre mayor sea el desplazamiento angular, con lo
que solo perderemos menos precisión, entre menor sea la fracción que tomemos, en este caso será suficiente con 60,
que además es el máximo de cuadros que Glut puede mostrar por segundo.

Tabla de Contenido
Retroalimentación:

Tus comentarios, dudas o sugerencias serán bien recibidas. Te dejo mi correo:

redes.neuronales.paso.a.paso@gmail.com

Tabla de Contenido

También podría gustarte