Table of Contents
Modificación de CRRCSIM para agregar la funcionalidad de modelado de ráfagas de viento II
Elaborado por: Jose Pablo Espinoza Barahona
Introducción
Este trabajo es una continuación del proyecto anterior; donde se hará uso de los elementos encontrados para lograr el objetivo principal: otorgar la funcionalidad de tener ráfagas aleatorias. Se verán conceptos sobre la elaboración y modificación de un paquete debian(tomar un paquete existente, re-bulding it, aplicar cambios, preparar cambios para enviarlos como un parche.), particularidades de las ráfagas de viento y abstracción de su comportamiento para su traspaso a código.
Objetivos
Objetivo General
Dotar al programa “crrcsim” la funcionalidad de modelado de ráfagas de viento.
Objetivos Específicos
- Definir y estudiar un algoritmo que abstraiga la naturaleza de una ráfaga de viento y su influencia el ambiente.
- Construir un modulo de yarp que implemente el modelo de viento para ser enviado mediante yarp a crrcsim.
- Realizar la modificación a crrcsim para que acepte la velocidad del viento desde un puerto yarp.
- Realizar pruebas de funcionamiento.
Preparación del equipo
1. build-essential, fakeroot, devscripts
sudo apt-get install build-essential fakeroot devscripts
2. configurar apt
sudo nano /etc/apt/sources.list
Añadir:
deb-src http://http.us.debian.org/debian unstable main
Actualizar:
sudo apt-get update
3. crear un directorio de trabajo. Una vez añadido la url podemos descargar la fuente(source). Es una buena práctica tener una carpeta exclusiva para trabajar que contenga la fuente del software.
mkdir -p src/debian/
4. Debemos instalar el paquete antes y que sea la última versión debido a que necesitamos resolver depedencias antes de instalar la modificación.
sudo apt-get crrcsim
5. descargamos el fuente
cd ~/src/debian apt-get source crrcsim
Ahora tenemos 3 archivos (.dsc, .debian.tar.gz, .orig.tar.gz) y un directorio “crrcsim-0.9.12” dentro de este se encuentra la fuente desempaquetada. Dentro de ese directorio encontramos un subdirectorio “debian”. Todo paquete de debian (o derivado de este) incluye un directorio “debian”, este contiene información relacionada con el paquete de debian. Todo lo que se encuentra afuera de ese directorio es “upstream code”, i.e. el codigo original que fue liberado por el desarrollador original.
Del contenido del directorio debian nos interesa entender dos archivos:
Archivo "rules": ejecutable que va ser llamado para construir el paquete. Directorio "patches": parches aplicados por el encargado del paquete.
6. obteniendo las dependencias de build.
Para construir satisfactoriamente la mayoría de los programas, necesitamos solventar ciertas dependencias. generalmente son paquetes que tienen el sufijo “-dev”, pero tambien pueden ser otros como “automake” o “gcc”; “apt” nos ofrece la siguiente forma para instalar todas las dependencias necesarias.
sudo apt-get build-dep crrcsim
7. Build sin cambios.
Con esto garantizamos que se construyo e instalo correctamente el paquete. cd ~/src/debian/crrcsim-0.9.12/ debuild -b -uc -us Crea un ".deb" (binary only package) y previene que se firme el paquete. Lo que ejecuta es lo que dicte el archivo "rules".
8. instalación
sudo dpkg -i ../crrcsim-0.9.12_<your arch>.deb
donde:
<your arch> = [i386|amd64]
8. ejecutarlo
crrcsim
Debería de funcionar.
9. Pre-requisitos “quilt”. Estas son Herramientas para trabajar con parches de paquetes. Los parches contienen código que debe ser inyectado para solucionar bugs y mantener una documentación de los cambios realizados.
sudo apt-get install packaging-dev vi ~/.quiltrc insertamos esto: #----- QUILT_PATCHES=debian/patches QUILT_NO_DIFF_INDEX=1 QUILT_NO_DIFF_TIMESTAMPS=1 QUILT_REFRESH_ARGS="-p ab" QUILT_DIFF_ARGS="--color=auto" # If you want some color when using `quilt diff`. #-----
10. Crear un parche
existe directorio debian y el archivo rules. cd ~/src/debian/crrcsim-0.9.12/ quilt push -a quilt new <NOMBRE> add <path a archivo a modificar> ... MOFICAR FUENTE ... quilt refresh <NOMBRE> quilt pop -a
11. Editar un parche
cd ~/src/debian/crrcsim-0.9.12/ quilt push <NOMBRE> ... MOFICAR FUENTE ... quilt refresh <NOMBRE> quilt pop -a
Con esto ya debemos de ser capaces de realizar cambios en el código fuente de crrcsim y solventamos cualquier tipo de dependencia requerida.
Viento
El objetivo es tener ráfagas aleatorias, pero debemos de dar nuestra definición de aleatorio para la funcionalidad que deseamos obtener. Vamos a definir ráfaga aleatórea como: una graduación variable de los parametros de velocidad y dirección que permitan al piloto enfrentarse ante situaciones que obliguen una estabilización del vehículo.
Teniendo esto en cuenta tenemos que procedemos a realizar una comparación de los parametros de velocidad para comprender su magnitud. Usamos el siguiente cuadro.
km/hr | ft/s | descripción |
---|---|---|
1 | 0.9 | calmado |
1-5 | 0.9-4.5 | viento ligero |
6-11 | 5.4-10 | brisa suave |
19-38 | 17.3-34.6 | brisa muy fuerte |
39-49 | 35.5-44.6 | viento fuerte |
117 | 106.6 | huracán |
fuente:http://www.windows2universe.org/earth/Atmosphere/wind_speeds.html
Teniendo la idea de la magnitud de los valores con los que contamos, se considera que el rango que se debe de manejar no debería de sobrepasar los 20 ft/s.
Ciclo de Juego
De la parte uno del proyecto identificamos el ciclo de juego y se concluyó que nuestro código debe ser inyectado en el ciclo y antes de que de invoque el método draw(). Por lo tanto lo que queremos desarrollar es el siguiente esquema.
Haciendo uso de módulos de yarp para escritura y lectura se busca brindar los datos de: windBase: Viento base el cual es tomado como referencia para oscilar entre los límites superior e inferior. dirBase: Direccion base el cual es tomado como eje central de los cambios. limInf: límite inferior, usado por windBase. limSup: límite superior, usado por windBase. Implementado de la forma presentado en el esquema:
Debido a problemas con la configuración de yarp este objetivo no podrá ser cumplido por el momento. Por lo tanto para lograr un comportamiento similar se hará uso de un patrón de grafos donde los nodos contienen una velocidad base y sus enlaces indican la probabilidad de pasar al otro nodo ,i.e. cambiar de velocidad. Representado en el siguiente diagrama:
Tomaremos las velocidades base del cuadro[1] como {1,10,20} por lo que vamos a tener 3 niveles de intensidad. Se usará un arreglo con una incidencia mayor de ciertos vientos base para aumentar la probabilidad de aparación. Del gráfico C podemos hacer la implementación en código
version 0.0.2 softcoded not cleaned.
void rafagas(){ srand(time(NULL)); //calculo del porcentaje percentWin = rand() % 100 + 1; if(percentWin+percentBooster > 95){//cambio de banda //escoger banda indexWin = rand() % 6 + 1; cfg->wind->setVelocity(range[indexWin]); if(indexWin == 6){//esto es para evitar que pase mucho tiempo en high percentBooster=40; } }else if(percentWin > 40){//aumenta o disminuye conditionalWin = rand() % 8 + 1; if(conditionalWin+tendencyWin>4){//aumenta cfg->wind->setVelocity(cfg->wind->getVelocity()+1); tendencyWin = 2; }else{//disminuye cfg->wind->setVelocity(cfg->wind->getVelocity()-1); tendencyWin = -2; }//END Conditional +/- percentBooster=0; }//END conditional }//END rafagas
Una muestra de los valores obtenidos durante ejecución (x,y):(iteración, velocidad)
De forma similar hacemos un diagrama de grafos para la dirección del viento. El cual va tener como nodos los puntos cardinales {0,90,180,270} y sus enlaces son las probabilidad de que se cambie. Representado en el siguiente diagrama:
Del gráfico podemos hacer la implementación en código:
version 0.0.2 softcoded not cleaned.
void cambioDireccion(int pchange){ int newDirection = cfg->wind->getDirection() + pchange; if(newDirection >= 360){ newDirection = newDirection - 360; }else if(newDirection <= 0){ newDirection = 360 - newDirection; } cfg->wind->setDirection(newDirection,cfg); } void direccion(){ //calculo del porcentaje percentDir = rand() % 100 + 1; conditionalDir = rand() % 8 + 1; if(percentDir > 97){//cambio grande corto cfg->wind->setDirection(rosa[indexDir],cfg); indexDir = rand() % 5 + 1; }else if(percentDir > 85){//oscilacion alta indexDir = rand() % 4 + 1; if(conditionalDir+tendencyDir>4){//aumenta cambioDireccion(alto[indexDir]); tendencyDir = 2; }else{//disminuye cambioDireccion(-alto[indexDir]); tendencyDir = -2; }//END condDiritional +/- }else if(percentDir > 55){//oscilacion media indexDir = rand() % 4 + 1; if(conditionalDir+tendencyDir>4){//aumenta cambioDireccion(medio[indexDir]); tendencyDir = 2; }else{//disminuye cambioDireccion(-medio[indexDir]); tendencyDir = -2; }//END condDiritional +/- }else if(percentDir > 40){//oscilacion leve indexDir = rand() % 4 + 1; if(conditionalDir+tendencyDir>4){//aumenta cambioDireccion(bajo[indexDir]); tendencyDir = 2; }else{//disminuye cambioDireccion(-bajo[indexDir]); tendencyDir = -2; }//END condDiritional +/- }//END condDiritional }//END direccion
Implementación usando
cd ~/src/debian/crrcsim-0.9.12/ quilt push -a quilt new randomWind.diff
Ahora insertamos el codigo en ./src/crrc_main.cpp
linea 109
//*******MOD***** #include <stdio.h> #include <stdlib.h> #include <iomanip> //*****END-MOD***
linea 136
//*******MOD***** int range [7] = {1, 1, 1, 1, 10, 10, 20}; //usado para aumentar incidencia de ciertos elementos int rosa [5] = {0, 0, 90, 180, 270}; //{vacum, NORTH, EAST, SOUTH, WEST} int alto [4] = {5, 6, 7, 8}; int medio [4] = {2, 3, 4, 5}; float bajo [4] = {0, 0.25, 0.50, 0.75}; int percentBooster, percentWin, indexWin, tendencyWin, conditionalWin, modCycle = 0; int percentDir, indexDir, tendencyDir, conditionalDir = 0; //*****END-MOD***
linea 518
//*******MOD*** void rafagas(){ srand(time(NULL)); //calculo del porcentaje percentWin = rand() % 100 + 1; if(percentWin+percentBooster > 95){//cambio de banda //escoger banda indexWin = rand() % 6 + 1; cfg->wind->setVelocity(range[indexWin]); if(indexWin == 6){//esto es para evitar que pase mucho tiempo en high percentBooster=40; } }else if(percentWin > 40){//aumenta o disminuye conditionalWin = rand() % 8 + 1; if(conditionalWin+tendencyWin>4){//aumenta cfg->wind->setVelocity(cfg->wind->getVelocity()+1); tendencyWin = 2; }else{//disminuye cfg->wind->setVelocity(cfg->wind->getVelocity()-1); tendencyWin = -2; }//END Conditional +/- percentBooster=0; }//END conditional }//END rafagas void cambioDireccion(int pchange){ int newDirection = cfg->wind->getDirection() + pchange; if(newDirection >= 360){ newDirection = newDirection - 360; }else if(newDirection <= 0){ newDirection = 360 - newDirection; } cfg->wind->setDirection(newDirection,cfg); } void direccion(){ //calculo del porcentaje percentDir = rand() % 100 + 1; conditionalDir = rand() % 8 + 1; if(percentDir > 97){//cambio grande corto cfg->wind->setDirection(rosa[indexDir],cfg); indexDir = rand() % 5 + 1; }else if(percentDir > 85){//oscilacion alta indexDir = rand() % 4 + 1; if(conditionalDir+tendencyDir>4){//aumenta cambioDireccion(alto[indexDir]); tendencyDir = 2; }else{//disminuye cambioDireccion(-alto[indexDir]); tendencyDir = -2; }//END condDiritional +/- }else if(percentDir > 55){//oscilacion media indexDir = rand() % 4 + 1; if(conditionalDir+tendencyDir>4){//aumenta cambioDireccion(medio[indexDir]); tendencyDir = 2; }else{//disminuye cambioDireccion(-medio[indexDir]); tendencyDir = -2; }//END condDiritional +/- }else if(percentDir > 40){//oscilacion leve indexDir = rand() % 4 + 1; if(conditionalDir+tendencyDir>4){//aumenta cambioDireccion(bajo[indexDir]); tendencyDir = 2; }else{//disminuye cambioDireccion(-bajo[indexDir]); tendencyDir = -2; }//END condDiritional +/- }//END condDiritional }//END direccion //*****END-MOD***
linea 954
//*******MOD***** modCycle++; if(modCycle==60){ rafagas(); direccion(); modCycle=0; printf("MODIFICACION REALIZADA\n"); printf(" VIENTO: %f \n", cfg->wind->getVelocity()); printf("DIRECCION: %f \n", cfg->wind->getDirection()); }//end if mod //*****END-MOD***
Luego de haber insertado
quilt refresh randomWind.diff quilt pop -a debuild -b -uc -us sudo dpkg -i ../crrcsim-0.9.12_<your arch>.deb
donde: <your arch> = [i386|amd64]
ejecutamos desde consola
crrcsim
Conclusiones
El programa resiste cambios durante ejecución y no existen inconvenientes si se ingresa un valor no soportado por el dominio, por lo que deja la duda, ¿Por qué no se había implementado esta funcionalidad antes? Si todo lo que tenemos que hacer es jugar con dos variables entonces debió de haber sido implementado por los desarrolladores originales siendo esta una función que incluso en su README.txt se menciona que se quiere implementar.
Se deben de hacer más pruebas sobre la usabilidad del código inyectado ya que no ha sido probado aun con pilotos experimentados.
Apendices
Modulo simple Rx/Tx http://www.yarp.it/yarp_code_examples.html
Presentación: presentacionii.pdf
fuente de crrcsim de los repositorios de debian. crrcsim.tar.gz
paquete generado del proyecto: crrcsim_0.9.12-6.1_amd64.deb
Referencias
Lippman, S. , Lajoie, J. & Moo, B.E. August 16, 2012 C++ Premier, 5th Edition. Boston, Massachusetts : Addison-Wesley Professional.
Tolman, H. November 28, 1990. A third-generation model for wind waves on slowy varying, unsteady, and inhomogeneous depths and currents: Journal of physics oceanography, volume number(21), pp 782-797. Extracted from http://journals.ametsoc.org/doi/pdf/10.1175/1520-0485%281991%29021%3C0782%3AATGMFW%3E2.0.CO%3B2 https://wiki.debian.org/UsingQuilt https://wiki.debian.org/BuildingTutorial