Raspberry Pi 4 + Arduino + Sensores + Socket.IO + HTML

En unos días estaremos llevando adelante un evento muy grande. Se viene la STEMFest por esta zona del planeta (Tauranga, New Zealand).

Y parte de mi trabajo será enseñarle a niños y adolescentes (Muchos… dicen que habrá cerca de 3000) que la tecnología, la programación y las ciencias, en general, son fáciles y divertidas.

Para esto, desde el grupo de “Junior DevTauranga” hemos estado creando diferentes proyectos con los que los asistentes podrán interactuar, armar y desarmar, crear código, editarlo. En fin, jugar!

Uno de estos proyectos ya lo he compartido en otro post. Pero ahora hemos agregado nuevos al repositorio.

Un sensor de temperatura y humedad. Un sensor para medir si debemos agregar más agua a nuestras plantas. Y un piano hecho con frutas.

Todos estos proyectos se pueden descargar desde: https://github.com/MatiasIac/STEMFestTauranga2019

Y, por supuesto, seguiremos agregando más en lo que queda de la semana!

Anuncios

Principios SOLID

Si no los viste o no te enteraste o te olvidaste. En este mes (Y el pasado), cree mucho contenido alrededor de los principios SOLID.

Principios que son parte de la caja de herramientas de cualquier ingeniero, programador, arquitecto, o quien sea que se dedique a crear código.

Este contenido está disponible en mi canal de YouTube, y podés verlo desde acá:

Esta lista seguirá creciendo con más ejemplos, así que te recomiendo visitarla de vez en cuando.

Realidad Aumentada en el navegador – Parte II

Hace una semana les contaba que había estado experimentando con un par de frameworks y herramientas de realidad aumentada para el navegador.

Todo esto se debe a un evento en el que estoy participando donde estaremos enseñando a niños y adolescentes sobre programación, lógica y demás (StemFest), y para divertir un poco a los participantes (Que parece que serán 3000… sí, una locura :S) me puse a crear una aplicación que simule el juego de la búsqueda del tesoro.

Teniendo en cuenta las características del proyecto: Web + JavaScript. Este puede ser ejecutado por cualquier navegador en cualquier dispositvo (Celular o escritorio) y con esto, no tener la necesidad de crear una aplicación nativa para cada plataforma.

En fin, y manteniendo mi palabra, en vez de explicar el código paso a paso, paso a dejar el repositorio de código con todo el proyecto funcionando.

https://github.com/MatiasIac/STEMFestTauranga2019

(El proyecto irá variando en esta semana, pero el core seguirá siendo el mismo 🙂 )

Creando realidad aumentada en el navegador

Image

Hace muchos años atrás (Como 10) hablaba en un evento público sobre el futuro de algunas tecnologías. Que ya había empresas que estaba apostando a ellas y que las herramientas eran cada vez más accesibles y, por lo tanto, más fáciles de usar e implementar.

Hoy, cuando se habla de realidad aumentada siempre pensamos en celulares y aplicaciones al estilo PokemonGO. Aplicaciones construidas con Unity3D, ARKit y otros. Pero nos olvidamos de los principios de la realidad aumentada y las posibilidades que nos brindaba con equipos de casi costo nulo (Nulo en el sentido de que cualquier computadora o dispositivo con cámara podía ejecutarlas).

En fin… este tipo de tecnología nunca murió y, por el contrario, con mayor poder de cómputo en los dispositivos volvió con más fuerza.

Hoy (Hace unos días, pero es el momento en el que escribo el post en contraposición de cuando será publicado :)), me crucé con AR.js, una herramienta que, en conjunto con otras como Three.js y AFrame, nos permite llevar el mundo de la realidad aumentada a la Web. Y cuando digo “Web” me refiero a HTML + JavaScript puro y duro.

Por esto decidí hacer un pequeño ejemplo (Foto que acompaña el post) y paso a dejarlo por acá:

<!DOCTYPE html&gt;
<html lang="en"&gt;
    <head&gt;
        <meta charset="UTF-8"&gt;
        <meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
        <meta http-equiv="X-UA-Compatible" content="ie=edge"&gt;
        <title&gt;Document</title&gt;
    </head&gt;
    <script src="https://aframe.io/releases/0.6.0/aframe.min.js"&gt;</script&gt;
    <script src="https://jeromeetienne.github.io/AR.js/aframe/build/aframe-ar.js"&gt;</script&gt;
    <body style='margin : 0px; overflow: hidden;'&gt;
        <a-scene embedded arjs&gt;
            <a-assets&gt;
                <a-asset-item id="avo" src="avo/Avocado.gltf"&gt;</a-asset-item&gt;
            </a-assets&gt;
            <a-marker-camera preset='hiro'&gt;
                <a-entity gltf-model="#avo" scale="0.3 0.3 0.3"&gt;</a-entity&gt;
            </a-marker-camera&gt;
        </a-scene&gt;
    </body&gt;
</html&gt;

Perceptrón (Inteligencia Artificial) con JavaScript

Ufff! Sí, más de un año desde el último post y, viendo las estadísticas del blog (Claramente) la gente que lo consulta es casi nula. Pero, los que me han seguido sabrán que mudé toda la creación de contenido a mi canal de YouTube: https://youtube.com/user/lacosagorda

En el canal subo un video (Como mínimo) por semana así que todo sigue activo. De cualquier manera, vuelvo por acá y no es que vaya a decir lo que suelo y luego me muerdo a mi mismo porque no puedo cumplirlo. Sí, lo que voy a decir es que iré dejando por acá esas cosas que hago de vez en cuando por puro gusto y que, por algún motivo, no he puesto en videos.

Como ya saben, me gusta explorar más allá de las herramientas que podamos usar. No quiero quedarme con el hecho de poder saber usar tal o cual framework: Quiero hacerlo por mí mismo (Aunque luego use un framework).

En fin, como el mundo de la inteligencia artificial está más movido que nunca y todo el mundo quiere usar este u otro framework, me puse en la tarea de comenzar a crear (Y entender) uno de los conceptos más comunes dentro del mundo de la IA: Cómo crear mi propia red neuronal que pueda aprender por su cuenta y sepa “predecir” determinados resultados en base a entrenamiento.

Así que, para poder iniciar, había que arrancar con la unidad más básica que se usa en este tipo de redes, junto a la función más comunmente usada. Estos son el “perceptrón” y la función “sigmoide”.

Por supuesto, no voy a entrar en detalle sobre cada uno de estas cosas porque (Y queda dicho para todos los siguientes posts que vengan), no quiero escribir tanto detallando cada una de estas ideas, las cuales requieren muchas páginas (Pero muchas). Si hace falta más información siempre se podrá acudir a una búsqueda en Google 🙂

En fin, un perceptrón; en este caso para operaciones tipo OR; nos sirve para poder categorizar entre dos tipos de elementos. La función sigmoide, por otro lado, le ayuda al perceptrón para marcar el umbral de activación para una operación dada en dicho perceptrón.

Básicamente obtendremos un 1 o un 0 si la operación se acerca al valor calculado/esperado. (De nuevo, estoy tratando de explicarlo lo más simple posible para no escribir toneladas de texto)

En definitiva, les dejo el “perceptrón“:

var perceptron = (function() {

    var neuro = function() {
        
        this._seed = 1;
        this._threshold = 1;
        this._bias = 1;
        this._learnRate = 0.1;
        this._weights = [];
        this._neuralData = [];
    };

    neuro.prototype._random = function() {
        var x = Math.sin(this._seed++) * 10000;
        return x - Math.floor(x);
    };

    neuro.prototype._multiply = function (inputs) {
        var result = 0;

        for (var i = 0; i &amp;lt; inputs.length; i++) {
            result += inputs[i] * this._weights[i];
        }

        result += this._threshold * this._weights[this._weights.length - 1];

        return result;
    },

    neuro.prototype._sigmoid = function(x) {
        return 1 / (1 + Math.pow(Math.E, -x));
    };

    neuro.prototype._retrain = function() {
        var neuralDataLength = this._neuralData.length;
        var hasSuccess = true;

        for (var i = 0; i &amp;lt; neuralDataLength; i++) {
            var trainData = this._neuralData.shift();

            hasSuccess = this.train(trainData.input, trainData.target) &amp;amp;&amp;amp; hasSuccess;
        }

        return hasSuccess;
    };

    neuro.prototype.exercise = function(iterations) {
        var i = 0;

        while (i++ &amp;lt; iterations) {
            var trainResult = this._retrain();

            if (trainResult === true) {
                console.log('Retraining ended after ' + i + ' attempts');
                break;
            }
        }
    };

    neuro.prototype.train = function (inputs, expected) {
        
        while (this._weights.length &amp;lt; inputs.length) {
            this._weights.push(this._random());
        }

        //neuron bias
        if (this._weights.length === inputs.length) {
            this._weights.push(this._bias);
        }

        var preceptionResult = this.process(inputs); //this.percieve(inputs);
        this._neuralData.push({input: inputs, target: expected, prev: preceptionResult})

        if (preceptionResult !== expected) {
            for (var i = 0; i &amp;lt; this._weights.length; i++) { var input = (i == inputs.length) ? this._threshold : inputs[i]; var adjustment = (expected - preceptionResult) * this._learnRate * input; this._weights[i] += adjustment; if (isNaN(this._weights[i])) throw new Error('Weight out of boundaries'); } return false; } return true; }; neuro.prototype.process = function (inputs) { return Number(this._sigmoid(this._multiply(inputs, this._weights)) &amp;gt; 0.5);
    };

    return new neuro();
}());

Para poder utilizar este objeto lo primero que deberemos hacer es entrenar nuestro perceptrón:

perceptron.train([0, 0], 0);
perceptron.train([0, 1], 0);
perceptron.train([1, 0], 0);

El primer parámetro en la función “train” es un vector con los diferentes (En este caso) valores que representan un modelo válido y el segundo, el resultado. Esto es, si tenemos los elementos del primero parámetro, esperamos como resultado el segundo parámetro. Para el primer caso, si tenemos un “0, 0”, esperamos “0” como respuesta.

perceptron.exercise(10000);

El siguiente paso es entrenar intensivamente el perceptrón con los datos enviados. Esto simplemente aplicará la función interna N cantidad de veces hasta encontrar un valor aproximado que pudiese dar los resultados esperados.

Una vez entrenado, ya podemos “preguntarle”:

console.log(perceptron.process([1, 1]));

En este caso, el resultado será “1”. Que, en base al modelo que hemos armado, es lo que esperamos.

Máquinas de estado

Ayer me preguntaban cómo solucionar un problema de flujos de datos y procesos. Lo primero que se me vino a la cabeza fue: Eso es una máquina de estados!

Imaginemos por un momento un diagrama de flujos clásicos. Donde tenemos flechas que indican dirección y conectan diferentes elementos. Estos elementos representan acciones y, desde el inicio al final, los datos fluyen dejando que cada uno de esas acciones hagan algo sobre los mismos antes de pasarlos al siguiente componente.

Adicionalmente, era necesario saber que elemento estaba realizando qué y que dicho elemento conociera cualquier otro elemento que pudiese estar conectado a este para poder enviar los datos hacia ellos.

Por supuesto, hay muchas formas de implementar una máquina de estados. Un simple switch y algunas líneas de código ya son una máquina de estados pero, por supuesto, hay que hacerlo un poco más difícil 🙂

Si aún te preguntas dónde se usan estas máquinas de estado… bueno, son comunes en el desarrollo de videojuegos. Por ejemplo, cuando un personaje está realizando una acción, lo normal es que esa acción sea un estado del personaje. Saltar, correr, caminar, son estados del objeto y solo uno puede ejecutarse en un momento particular. Luego, solo se puede ir de caminar a correr como posible flujo y no de correr a agacharse sin primero caminar (Por dar un ejemplo).

El código

El código necesitaba hacerse en JavaScript (Lenguaje que amo) y debía contemplarse la posibilidad de no tener clases base. Esto quiere decir que, por ejemplo, para un nodo de la máquina de estado pueda conocer un nodo anterior o un nodo siguiente, lo lógico sería tener una clase base que implementase estos métodos y así reusarlos en cada nueva instancia de un nodo.

La máquina

    var stateMachine = {
        currentState: null,
        next: function() {
            if (this.currentState._next !== null) {
                this.currentState = this.currentState._next;
                this.currentState.process.call(this);    
            }
        },
        prev: function() {
            if (this.currentState._prev !== null) {
                this.currentState = this.currentState._prev;
                this.currentState.process.call(this);    
            }
        }
    };

La maquina de estados solo conoce el nodo o acción actual y provee dos funciones para poder moverse hacia adelante o hacia atrás (Más movimientos dependerán de nuestras necesidades).

El nodo

    var step = (function() {

        var s = function (configuration) {
            this._configuration = configuration;
            this._next = null;
            this._prev = null;
        };

        s.prototype.process = function () { };

        return s;
    }());

Una definición de “clase” clásica. Teniendo un constructor y una función que se usará para ejecutar las acciones del nodo.

Las acciones

    var firstStepFunction = function() {
        console.log(this.currentState._configuration.text);
        this.next();
    }

    var secondStepFunction = function() {
        console.log(this.currentState._configuration.text);
        this.next();
    }

    var lastStepFunction = function() {
        console.log(this.currentState._configuration.text);
        this.next();
    }

Cada función representa una acción particular para un nodo particular.

Uniendo todo

    var step1 = new step({text: "step 1"});
    step1.process = firstStepFunction;

    var step2 = new step({text: "step 2"});
    step2.process = secondStepFunction;

    var step3 = new step({text: "step 3"});
    step3.process = lastStepFunction;

    step1._next = step2;
    step2._prev = step1;
    step2._next = step3;
    step3._prev = step2;

    stateMachine.currentState = step1;
    step1.process.call(stateMachine);

En este caso, se puede crear un nuevo nodo, asociarle una acción en particular y sus siguientes o previos nodos en la cadena de ejecución.

La línea final dispara la ejecución del primer nodo, el cual se encargará de llamar a sus siguiente nodo y ejecutar todo el flujo.

En resumen. Este tipo de máquinas nos pueden ser de mucha utilidad ahorrándonos condificiones anidades y código poco mantenible. También, poder conocer el estado de un proceso. Aislar los mismos en diferentes unidades especializadas, entre otros beneficios varios.

Interceptores y JavaScript

Primero que nada decir que estoy armando este post desde el celular. Lo que puede llevar a horrendos errores gramaticales y ortográficos. Y se debe a que aún no cuento con acceso a internet (Larga historia).

Segundo, el tema de este post. Básicamente hace bastante tiempo venía pensado cómo poder simular algo cercano a AOP pero en Javascript. Claro, no todo el compendio de AOP, o no rigurosamente, pero algo.

Ese algo, para este caso se limitaba a interceptores en las diferentes llamadas a funciones. Como en el caso de lenguajes como C# o Java, dónde es posible decorar una función para obtener un comportamiento previo a la ejecución de la misma.

Un ejemplo es el clásico caso de los controllers de un proyecto MVC. Algo como:

[HttpPost]
public void HacerAlgo() ...

En este caso el decorador hace que dicha función sea ejecutada solo si se produce una llamada de tipo POST.

Por supuesto, esto no es necesariamente AOP. Pero por lo menos nos permite encapsular comportamiento por fuera de la función y esperar el mismo cada vez que decoramos una función.

Entonces el siguiente paso a pensar es: Qué pasaría si quiero escribir un log antes de que la función sea llamada. O mejor aún: Qué pasa si quiero que un set de reglas se ejecute antes de entrar a la función, como por ejemplo, validar que los campos no estén vacios.

[Validar(variable="nombre", empty=false, throwException=true)]
public void MiFuncion(string nombre) ...

En este caso si al llamarse la función la variable nombre se encuentra vacía, entoces se produce una excepción.

Nuevamente, esto no es AOP real, pero para el ejemplo pensemos que es una aproximación.

El punto a evaluar es que podemos obtener conportamiento repetible adicional a nuestra función sin tener que repetir el mismo código dentro del cuerpo de la misma. Y si bien no nos liberamos del acoplamiento, si podemos tener algunos beneficios próximos al mismo.

Tal vez en el caso de AOP, al momento de compilar deberíamos obtener nuevas funciones con dicho código incorporado en ellas. En el ejemplo de C#, por el contrario, necesitamos de un observador que controle el comportamiento de los objetos, clases y funciones, use algún modelo de reflection e inyecte comportamiento mientras las funciones son llamadas.

Esto quiere decir que la estructura de la función no muta en base a nuestras decoraciones.

¿Pero qué pasa con Javascript?

Bueno, resulta un poco más difícil ya que los métodos reflectivos que tenemos disponibles (Hasta donde yo se) no nos permiten decorar y leer esas decoraciones. (Usuarios de React y Redux y demases abstenerse, eso tiene una capita adicional)

Pero sí podemos recrear una función de forma dinámica. Esto es: Tomar la función existente y sobre escribirla a nuestro gusto en tiempo de ejecución.

Toda esta cantaleta para llegar a esto.

En la imagen se puede ver un objeto en el que tenemos una función que recibe dos parámetros. El primero llamado p y el segundo __interceptor. Y es el segundo el que me interesa.

¿Que pasaría si este dictaminará que dicha función, al ser llamada, debiera primero ejecutar alguna acción definida en ese interceptor y luego, si todo sale bien, seguir el camino esperado?

En la imagen lo que terminé armando.

Básicamente la posibilidad de definir dicho interceptor (o varios en cadena). Que modifican el comportamiento original de la función. La sobre escriben y la dejan lista para ser usada con el nuevo código inyectado.

Como vemos en la consola. Al llamar a las diferentes funciones, antes, los interceptores son ejecutados para luego dar paso al código de las funciones originales.

Algunas aclaraciones.

El código es algo largo como para pegarlo en este mismo post por lo que trataré de colocarlo en GitHub en breve.

No lo hice en ES6 o TypeScript por falta de compiladores.

Seguro hay mejores implementaciones. Angular tiene cosas así. PrototypeJs creo que también. Pero ya saben… Es divertido hacerlas uno mismo.

Por último, una vez suba el código aprovecharé para armar otro post explicando algunas partes.

Espero que les resulte interesante 😛