
Terry Pratchett escribió, “Nadie ha muerto del todo hasta que mueren las ondulaciones que ha provocado en este mundo: hasta que se para el reloj al que dio cuerda, hasta que fermenta el vino que preparó, hasta que se recoge la cosecha que plantó”.
Terry Pratchett escribió, “Nadie ha muerto del todo hasta que mueren las ondulaciones que ha provocado en este mundo: hasta que se para el reloj al que dio cuerda, hasta que fermenta el vino que preparó, hasta que se recoge la cosecha que plantó”.
Uno de los problemas de desarrollar en PHP, es que se interpreta en el lado del servidor y lo que devuelve es la información procesada de la lógica de PHP. Esto nos lleva a la problemática de que es poco útil inundar de trazas de PHP que escriban en el HTML resultante de vuelta, los estados concretos de las variables procesadas durante la ejecución de la lógica programada.
Esto nos obliga a poner algún tipo de servicio de depuración que nos interrumpa la ejecución del intérprete de PHP y nos mande la información del estado de ejecución de cada punto de ruptura o de parada (breakpoint) que queramos añadir.
Uno de los frameworks de depuración más extendidos es XDebug, que además de ofrecer capacidades de depuración (debugging) también ofrece características de análisis de rendimiento (profiling). Este framework se integra muy bien con todos las soluciones de servidor PHP, como es mi caso concreto de XAMPP y mi entorno de desarrollo integrado Netbeans.
Para integrarlo lo primero que tenemos que hacer es localizar el fichero de configuración "php.ini" que contiene la información de configuración del intérprete de PHP que se encuentra en el directorio "xampp/php". Abrimos el fichero con un editor de texto cualquiera y buscamos la existencia de "[XDebug]" y descomentamos las siguiente líneas quitando el punto y coma de delante de cada línea para conseguir las siguiente configuración:
[XDebug] zend_extension = php_xdebug.dll xdebug.remote_enable = 1 xdebug.remote_handler = dbgp xdebug.remote_host = localhost xdebug.remote_port = 9000
En el caso de no estar todas las líneas añade las que falten y si no encuentras nada que te referencie a XDebug, añádelo. En las últimas versiones de XAMPP sigue estando incluido XDebug, pero no hay rastro de él en el fichero de configuración. No obstante comprueba que existe en el directorio "xampp/php/ext" la libería dinámica "php_xdebug.dll".
Si alguno le echa un ojo al resto del fichero "php.ini", se dará cuenta que existen un apartado de extensiones dinámicas (Dynamic Extensions), donde se referencian otras librerías dinámicas del directorio "xampp/php/ext", cargadas con "extension=", en vez de "zend_extension=". Esto es debido a que se carga usando el motor Zend. Si no lo respetáis, no os funcionará a pesar de que PHP os lo reconozca.
Para que la configuración tenga efecto guardamos el fichero y reniniciamos Apache si estaba ya funcionando. Si todo está correcto, entrando en la siguientes direcciones:
... deberíamos poder encontrar XDebug y poder ver toda la configuración.
Ahora vayamos a Netbeans, quien por defecto ya viene con XDebug preconfigurado. En "Herramientas-->Opciones-->PHP-->Debugging", comprobamos que "Debugger Port" sea el 9000 (el que configuramos en el fichero php.ini) y desmarcamos, si lo estuviera, la opción "Stop at First Line" para que no entre en modo depuración en la primera línea del proyecto, sino cuando encuentra un breakpoint.
Ahora si marcamos en cualquier parte del código con un breakpoint y lanzamos el proyecto en modo depuración , la ejecución parará en el breakpoint marcado, pudiendo continuar la ejecución paso a paso si lo necesitásemos, supervisando la lógica y valores tomados durante la ejecución.
Como habéis podido ver, el depurado XDebug configurado en XAMPP e integrado con Netbeans, resulta de los más útil, dotándonos de una herramienta de depuración perfecta para trabajar en nuestros proyectos de PHP.
Me complace presentar como primer invitado en el blog a mi compañero Javier, con el que tuve el gusto de compartir experiencias de trabajo durante un par de años en la misma empresa, en el mismo departamento e incluso hasta en los mismos proyectos, trabajando en ocasiones codo con codo. Ahora Javier, desde hace un tiempo, ha seguido su trayectoria profesional en el campo de los drones, tan en auge en estos últimos años.
Hace poco mantuve una conversación sobre drones con Rubén y me pidió que escribiera una entrada en su blog (Mascando Bits) explicando mis experiencias como desarrollador de software para drones robots. Me pareció una buena idea ya que se trata de una tecnología que está creciendo muy rápidamente y la gente de a pie todavía no tiene claro como funcionan, que componentes necesitan y que son capaces de hacer.
Hasta hace unos meses mis conocimientos sobre drones se reducían que me sonaba un poco el Phantom de DJI y el Parrot. De robots se puede decir que me sonaba un poco la librería ROS. Las circunstancias hicieron que empezase a trabajar en un proyecto con drones robots cuya misión es realizar vuelos autónomos para detectar y clasificar objetos u eventos. Las circunstancias hicieron también que el proyecto fuera mega urgente y tuviéramos que trabajar mano a mano un experto en drones y aviones, un experto en robots y un (experto? jaja) en visión por ordenador que soy yo. Así pues, 7 meses después parece que todos sabemos cómo funcionan los drones. ¡Los nuestros al menos!
Para centrar el tema voy a empezar por definir que es un dron robot. Un dron robot es un vehículo aéreo no tripulado (Unmanned Aerial Vehicle) que funciona de manera autónoma. El término dron vulgarmente se suele asociar a los vehículos aéreos de varios motores con hélices, pero el término preciso es UAV. Para que sea robot solo necesita realizar tareas de forma autónoma, es decir, sin el control directo de un ser humano.
Si nos centramos en el concepto de dron más extendido, típicamente quadrotors, un dron se compone de:
Un dron vuela básicamente porque la batería proporciona energía a los motores que hacen girar las hélices que a su vez propulsan aire hacia abajo elevando el dron. La fuerza de sustentación deberá ser mayor al peso del dron para conseguir elevarlo. Este concepto juega un papel fundamental a la hora de elegir el tamaño de las hélices, baterías, peso del dron, etc.
La controladora de vuelo es la parte más importante de un UAV. Es la encargada de regular la potencia de cada motor y de estabilizar el dron en función de la información que recogen sus sensores. Si todos los motores reciben la misma potencia, el dron se mantendrá estable en el eje vertical. Si los motores traseros reciben más potencia, el dron se desplazará hacia delante, y viceversa.
Los componentes comunes de una controladora de vuelo son:
Las controladoras de vuelo pueden ser muy simples y solamente intentar mantener el dron estable mientras realiza maniobras, o bien complejas y utilizar sensores como el GPS para mantener la posición de dron. Las controladoras de vuelo son la “chicha” de los drones y las que marcan la diferencia de calidad entre unos modelos y otros. Cuanto más avanzada sea la controladora mejor estabilizará el dron, sean cuales sean las circunstancias. Una controladora ideal mantendrá al dron clavado en el punto deseado pase lo que pase, aunque el viento empuje el dron la controladora detectará el desplazamiento no deseado y lo corregirá para mantener esa posición. Obviamente la calidad de los sensores (GPS, brújula, acelerómetro) influyen en los cálculos (PIDs) que realiza la controladora para conseguir su objetivo de mantener o llevar al dron a la posición objetivo, con la velocidad deseada.
Y así es como funciona un dron de la manera más simple que se me ocurre explicarlo. Si analizamos el funcionamiento desde el punto de vista del piloto que utiliza una emisora de radio para controlarlo se podría interpretar de la siguiente manera. El piloto maneja los controles y como consecuencia está enviando comandos de velocidad al piloto automático, que los traduce en señales eléctricas a los variadores o ESC. Estos convierten la corriente continua de la batería en la intensidad que se desea enviar a los motores. Si “armamos” el dron y le damos gas a los motores, el piloto automático recibe comandos de velocidad en la dirección vertical ascendente, y suministrará potencia a los 4 motores por igual hasta que sus ecuaciones detecten que se ha alcanzado la velocidad deseada de ascenso.
Muchas controladoras de vuelo vienen con un software que permite "calibrar" el dron de forma precisa, configurar la sensibilidad de los controles de la emisora de radio, la configuración de los botones, la velocidad máxima del dron, vuelta a casa automática, etc. La calibración y configuración de la controladora de vuelo es una parte esencial para que el dron vuele correctamente y evitar accidentes y sorpresas. Otras controladoras de vuelo permiten además la configuración de misiones basadas en waypoints (puntos GPS). Estas misiones no envían comandos de velocidad al autopiloto, si no que envían puntos GPS de destino o comandos de posición y el autopiloto se encarga de alcanzarlos.
Como introducción al funcionamiento de los drones puede resultar un poco densa, pero los conceptos de comandos de velocidad y de posición que se envían a las controladoras son la clave para diseñar software para drones robots. Si en lugar de ser el mando del piloto el que envía esos comandos es un software programado por nosotros que toma decisiones en función de ciertos eventos o mensajes, estaremos convirtiendo el UAV en un robot. ¿Y de qué forma se pueden tomar estas decisiones? De eso hablaré en la próxima entrada...
Enlaces de interés:
Habitualmente se genera código que funciona, y que no por ello quiere decir que esté bien codificado. Cuando me refiero a bien codificado, me refiero a que no existan secciones de código que no se usan, que los comportamientos del código sean deterministas, que se codifique evitando generar brechas de seguridad, que cumpla unas reglas de codificación que aseguren una buena comprensión del código, que se genere documentación del código... Por ello, algo que funcione no es sinónimo de que esté bien codificado (simplemente funciona).
En mi día a día suelo utilizar habitualmente Python y el estupendo IDE PyCharm para desarrollar mi trabajo. También tengo que orientar a otras personas que se están formando en este lenguaje, y eso conlleva una supervisión del código generado, no en el sentido de revisión que asegure la funcionalidad, sino el de asegurar una serie de buenas praxis en la codificación. Se trata del paso anterior a cualquier tipo de Testing.
Hablando con un compañero surgió el tema de asegurar unas buenas praxis para el lenguaje Python de personas interinas en la empresa que acaban de empezar, que desarrollan sus prácticas, su proyecto PFG (Proyecto Fin de Grado) o PFM (Proyecto Fin de Master). Estas buenas praxis no son otra cosa que la extensión del Zen de Python promulgado por Tim Peters:
Si el código cumple con estas directrices se dice que es código "pythonico". Esta filosofía ha hecho que Python lleve en su ADN esa características de legibilidad y transparencia.
Toda esta introducción nos lleva a las Python Enhancement Proposal (PEP) como formalismo de estas buenas praxis, siendo el Zen de Python la PEP20. Pero la pregunta es: ¿cómo me aseguro cumplir estas buenas praxis?, ¿y qué otros las cumplan?, ¿y qué además la forma de evaluarlas sea la misma? La respuesta es un revisor automático como es el caso de PyLint, que asegura una codificación estandarizada alineada con lo que se entiende con un código pythonico, la corrección de errores, la detección de código duplicado o que no se usa... en definitiva asegurar la buena praxis durante la codificación.
PyLint es un revisor automático ampliamente usado e integrado en otros servicios de mayor envergadura como es el caso de Codacy. Sitio de donde tomé la idea de coger un revisor local que se pudiese ejecutar desde el propio equipo, pero que a la vez se pudiese configurar de manera sencilla en el proyecto, y por supuesto integrarlo en mi IDE PyCharm.
Como primer paso, lo que hice fue instalarlo de manera sencilla con el comando "pip":
pip install pylint
Lo primero tras instalarlo fue hacer la prueba de ejecutarlo contra código que ya tenía evaluado por Codacy para poder comprobar lo estricto que era el revisor por defecto. Para mi mayor pena, el proyecto que arrojaba una calificación de B en Codacy, se quedaba en un 2.5 sobre 10. Inmediatamente me dí cuenta de que la vara de medir era extremadamente estricta por defecto, con lo que exporté los parámetros de revisión con los que Codacy revisaba mi código, ya que entendía que era una revisión más coherente.
Acto seguido revisé aquellas parametrizaciones que correspondían a PyLint y las migré a un fichero "pylintrc" que puede albergar la información de configuración de PyLint. Para ello ejecuté el siguiente comando, obteniendo la plantilla del "pylintrc":
pylint --generate-rcfile > .pylintrc
Una vez obtenida la plantilla del fichero de configuración, posteriormente modifiqué la sección "MESSAGES CONTROL" para deshabilitar todas las reglas de revisión por defecto y añadir las que yo deseaba, y que además coincidían con las de revisión en Codacy.
disable=all enable= E0001,E0100,E0101,E0102,E0103,E0104,E0105,E0106,E0107,E0110, E0113,E0114,E0115,E0116,E0117,E0108,E0202,E0203,E0211,E0236, E0238,E0239,E0240,E0241,E0301,E0302,E0601,E0603,E0604,E0701, E0702,E0703,E0704,E0710,E0711,E0712,E1003,E1102,E1111,E0112, E1120,E1121,E1123,E1124,E1125,E1126,E1127,E1132,E1200,E1201, E1205,E1206,E1300,E1301,E1302,E1303,E1304,E1305,E1306, C0123,C0200,C0303,C1001, W0101,W0102,W0104,W0105,W0106,W0107,W0108,W0109,W0110,W0120, W0122,W0124,W0150,W0199,W0221,W0222,W0233,W0404,W0410,W0601, W0602,W0604,W0611,W0612,W0622,W0623,W0702,W0705,W0711,W1300, W1301,W1302,W1303,,W1305,W1306,W1307 R0102,R0201,R0202,R0203
La serie de códigos que añado son una normalización de distintas reglas aplicables en PyLint para revisar el código. Podéis disponer del fichero completo con las reglas desde el siguiente Gist:
Con ese fichero "pylintrc" ya es posible portar la configuración para el revisor PyLint en cualquier proyecto. Sólo debemos añadirlo a la raíz de cualquier proyecto Python.
Anteriormente he comentado que uso PyCharm como IDE, y claro está, que ejecutar esta herramienta por línea de comandos, no resulta lo ideal. No os preocupéis porque existe una integración bastante directa de PyLint en PyCharm. Para ello solo tenéis que ir a File --> Settings --> Tools --> External Tools en vuestro PyCharm y añadir la siguiente configuración haciendo click en el símbolo + de color verde:
Poned el nombre y una descripción para la herramienta y desmarcad "Synchronize files after execution". En "Program" buscad dentro de la carpeta de instalación de Python en el subdirectorio Scripts el ejecutable "pylint.exe", si sois usuarios Windows, y en el directorio "/usr/bin" si sois usuarios de Linux.
Los parámetros que se introducen son la ubicación del fichero de configuración de PyLint (que debiera estar en la raíz del proyecto) y la macro que corresponde al fichero o carpeta que analizaríamos con PyLint. En "Working directory" ponemos la macro que apunta al directorio del proyecto correspondiente al fichero o carpeta que analicemos. Guardamos y para probarlo basta con ir a la raíz del proyecto y ejecutar PyLint con el botón derecho External Tools --> PyLint.
Como podéis ver, con esta integración tenéis una excelente herramienta que mejorará (si hacéis caso a sus reportes) vuestro código, generando un código mucho más pythonico.