Proyecto Fin de Carrera

Robótica, software y telecomunicaciones.

Diferencia de bucle for en C y C++

Esta es un pequeño consejo de Pablo Manzano Gómez, que a él le acarreó algunos problemillas al usar por primera vez código de ejemplos de ARToolKit que estaban escritos en C y él quería pasarlos a su aplicación en C++.

El código en cuestión es del tipo:

for(i=0, a=1; i<30; i++)
{}

El código anterior se interpreta de forma distinta en C y en C++, en el caso de C, sería lo mismo que el siguiente código:

a=1;
for(i=0; i<30; i++)
{}

En cambio en C++, el código se interpreta como el que sigue:

for(i=0; i<30; i++)
{a=1;}

29 junio 2011 Posted by | all | , | Deja un comentario

Negar una variable de tipo bool

Me gustaría compartir un tip muy simple, pero que me ha costado mucho dar con él, de hecho no he encontrado nada en internet, ni en castellano ni en inglés.

Se trata de negar una variable booleana, es decir, la negación lógica que se suele representar con el símbolo ¬, de forma que si a es falso, ¬a sería cierto.

Lo que he visto por internet eran las siguientes expresiones:

-a;
!a;
!~a;
a!=a;

Pero ninguna de esas expresiones hacen lo esperado.

La solución me la ha dado un profesor del departamento de Robótica (gracias Paco), que ha dado con ella tras unas pruebas:

a=!a;

De esta forma si a=true; después de la expresión a=!a; entonces a tendrá el valor false.

 

31 marzo 2011 Posted by | all | | Deja un comentario

Scope, namespace y ::

Es posible que entre los errores que nos encontramos en la fase de compilación, se encuentren errores relacionados con el SCOPE. Aunque no son errores muy comunes y uno puede advertirlos con facilidad, os explicaré brevemente cómo evitarlos o solucionarlos.

En otras entradas del blog he mencionado expresiones del tipo worker::compute() o std::cout>>, la expresión de cuatro puntos :: se conoce como operador de ámbito, y su función principal es evitar los problemas de SCOPE.

El problema de SCOPE ocurre principalmente cuando se usan dos o más métodos con el mismo nombre pero con implementaciones diferentes. Por ejemplo nosotros podemos estar haciendo una calculadora para lo que incluiremos una librería matemática math.h que tiene sus propios métodos (sum(), plow(), abs()…), si nos creamos un método llamado sum(), y luego en main() llamamos a sum(), obtendríamos un claro error de SCOPE al intentar compilar, pues de este modo el compilador no puede averiguar si en main() nos referimos al sum() de math.h o al sum() que nosotros hemos creado.

Esto se soluciona con el operador de ámbito ::, de modo que en main() podríamos escribir math::sum() o main::sum() para que el compilador sepa a cual de los dos nos referimos. De forma que para asegurarnos de no tener problemas de SCOPE lo ideal sería utilizar contínuamente el operador de ámbito, sin embargo puede llegar a ser engorroso si usamos a menudo los métodos de un ámbito determinado. Es decir, imaginemos que en nuestra calculadora solemos usar con mucha frecuencia el math::sum(), y sólo algunas veces usamos main::sum(), en ese caso podemos usar:

using namespace math;

De este modo en caso de que el compilador se encuentre con sum(), da por hecho que nos referimos a math::sum().

30 marzo 2011 Posted by | all | , , | 1 comentario

Mejorar el código con variables

Si miramos cualquier libro sobre programación, nos encontraremos una gran cantidad de consejos y trucos para mejorar el código, estos normalmente se van convirtiendo en normas universales, ya que su origen viene de la experiencia de la mayoría de programadores.

Algunos consejos tratan de comentar adecuadamente lo que se escribe, usar nombres de funciones y variables que sean simples, pero que a su vez describan de forma clara su propósito. Otros hacen mención a la identación del código, de forma que aún sin sintaxis coloreada podamos observar la estructura de todo el archivo.

Hoy yo os voy a recomendar otra: No usar valores en las llamadas a funciones o en el procesado de información, mejor usar variables.

Esto tiene mchas ventajas, pero principalmente son 2:

  • Código más legible.
  • Fácil modificación del código.

4 marzo 2011 Posted by | all | | Deja un comentario

El problema del CMakeLists.txt

Poco a poco voy entendiendo los mensajes que obtengo tras una compilación fallida.

Básicamente los errores pueden ser de los siguientes tipos:

  • Sintaxis: Estos son los que tenía con frecuencia, pero que poco a poco van desapareciendo, el motivo era tener en la cabeza mucho más fresca la sintaxis de MATLAB que la de C. Ocurre cuando no cierras un paréntesis, no pones un ; o no escribes bien las palabras reservadas.
  • Declaración: Estos errores son los que más rápido desaparecen cuando uno se ha enterado de la Programación Orientada a Objetos. Pero a veces tenemos despistes.
  • Errores de inicialización o proceso: Estos errores son bastante más comunes, al menos para mí. Por poner un ejemplo, a la hora de rellenar una QImage y salirme de los límites que yo mismo he establecido para esa imagen.
  • Errores con los MOC: Aún no tengo muy claro lo que son los MOC (MetaObjectC), pero lo que es cierto, que se tienen que crear en uns etapa concreta durante la compilación, si no es así, obtendrás errores del tipo MOC. En este caso la solución es borrar todos los MOC que se han generado en el intento de compilar, y posteriormente volver a compilar todo de nuevo. No es un error común, pero si te pasa es importante identificarlo, en ver de revisar tu código muchas veces sin encontrar ningún fallo.
  • Errores con el CMakeLists.txt: El CMakeLists.txt es ese archivo que contiene todo lo necesario para que la compilación se a correcta, por lo tanto, a veces, si la compilación no es correcta es porque falta o sobra algo en el CMakeLists.txt.

De momento no termino de entender la estructura del archivo CMakeLists.txt, ni su sintaxis, por lo que al principio me costaba mucho editarlo. El truco está en ser observador, es decir, mirar los CMakeLists.txt de otro componentes similares al tuyo. Lo mejor en estos casos es usar un programa comparador, que te resalta las diferencias entre dos archivos. Yo personalmente uso Meld, que es gráfico, claro e intuitivo, pero tambien podeís usar KDiff3 o el comando «diff» en un terminal.

1 marzo 2011 Posted by | all | , | 3 comentarios

Información para programar

La información que podemos obtener en la API de Robocomp, en QTAssistant, o en la wiki de OpenCV es realmente útil y necesaria para mi PFC, sin embargo, tenía la necesidad de obtener de forma resumida la información que necesitaba.

Para casi cualquier tema podréis encontrar en internet unas hojas a modo de chuleta que sintetizan la información necesaria, simplemente buscando en google «cheatsheet tema» o «tema reference» obtendremos muchos enlaces que nos llevan a archivos pdf de pocas páginas.

Yo he estado buscando de los temas relacionados con mi proyecto y me gustaría compartilos con vosotros:

  • ASCII Reference: Muy útil para escribir caracteres ASCII por el terminal, o manipular caracteres.
  • C Reference: Aunque vaya a usar C++, no viene nada mal tener a mano este documento.
  • C++ Reference: Es útil cuando empezamos con C++, luego ya esto te lo conoces como la palma de tu mano.
  • SVN Reference: No sé si ya he mencionado a Subverson antes, pero es un controlador de versiones de código, usamos un servidor en Robolab y también otro en la forja RedIris.
  • OpenCV Reference: De momento es la que mejor me viene, pues no termino de sentirme cómodo con la documentación oficial de OpenCV.
  • LaTeX Reference: Es ideal para mí, ya que quiero documentar todo mi PFC con LaTeX sin haberlo usado anteriormente.
  • UML Reference: En unos de mis primeras entradas publiqué mi intención de usar diagrmas UML para explicar mi código, sé que siempre debería dibujar los gráficos UML antes que generar código, sin embargo me temo que tendré que hacerlo al revés, espero que con la ayuda de este archivo me sea más fácil.

Pero no todo iban a ser chuletas, éstas son sólo un apoyo, el resto se aprende programando, pidiendo ayuda y consejo a compañeros de Robolab y mi tutor del PFC, buscando información en libros, blogs, foros…

A continuación os dejo una lista de libros o manuales que estoy utilizando para aprender:

  • Aprende C++ como si estuviera en primero.
  • Aprende UML en 24 horas.
  • Robocomp for Dummies.
  • Robex and Robocomp: Building intelliget robots.
  • Distribuited Programming with ICE.
  • Metodología para el desarrollo de aplicaciones orientadas a objetos.
  • Programación vanzada en Shell.

27 febrero 2011 Posted by | all | , , , | Deja un comentario

Estructura de un programa en C++

[directivas del pre-procesador: includes y defines]
[declaración de variables globales]
[prototipos de funciones]
[declaraciones de clases]
función main 
[definiciones de funciones]
[definiciones de clases]

12 octubre 2010 Posted by | all | | Deja un comentario

Un poco de C++

Desde que me he puesto a leer sobre C++ he llegado a las siguientes anotaciones:

La declaración de clases:  La forma de declarar clases en C++ es equivalente a la declaración de estructuras en C, pero con bastantes diferencias.

Las clases están divididas en 2 partes, una privada y otra pública. La privada se usa para declarar las variables de la clase a las que no se va a poder acceder desde fuera. Mientras que a la parte pública se le denomina interfaz y es esta parte la que puede modificar a la parte pública, por lo que normalmente suelen ser funciones. Estas funciones se declaran a la hora de construir o declarar la clase, pero normalmente se implementan de forma separada.

class Coche {
int velocidad, gasolina, distancia;
public:
void Repostar (int);
void Acelerar (int);
void Frenar (int);
};

En la clase anterior se puede observar todo lo explicado, la parte privada encima de ‘public:’ y la interfaz debajo.

Implementar  la interfaz: La interfaz se implementa igual que se implementa cualquier función en C pero utilizando ‘::’ para asignar la función implementada a la clase que queramos, quedaría algo así:

void Coche::Repostar (int g)
{
gasolina =+ g ; // Añadimos la cantidad 'g' a la gasolina que ya había en el depósito.
}

void Coche::Acelerar (int a)
{
velocidad =+ a ; // Añadimos la cantidad 'a' a la velocidad que tenía el vehículo.
}

void Coche::Frenar (int f)
{
gasolina =- f ; // Restamos la cantidad 'f' a la velocidad del coche.
}

Utilizando Objetos: Ahora que ya hemos definido la clase, podemos utilizar esta como un nuevo tipo de dato, primero declaramos el objeto y después podremos manipularlo con la interfaz, pero nunca sobre sus variables directamente:

Coche seat;    //Definimos una variable 'seat' del tipo 'Coche', esto en C++ se llama objeto, que es una instancia de una clase.
seat.Repostar(30); // Añadimos 30 litros de gasolina.
seat.Acelerar(50); //Aumentamos la velocidad en 50km/h.
seat.Frenar(20); // Reducimos la velocidad en 20km/h.

Lo que nunca se podrá hacer es: seat.velocidad=30; pues para esto están las interfaces.

1 agosto 2010 Posted by | all | , , , | Deja un comentario

¿Por dónde empezar?

Seguramente esta pregunta nos la hacemos todos los ingenieros cuando nos llega la hora de comenzar el Proyecto Fin de Carrera (PFC). Una de las cosas que aprendí de la asignatura de Proyectos, es que tener claros los objetivos y planificación del mismo es un punto muy importante si queremos garantizar el éxito. Cambiar de objetivos en mitad del desarrollo es algo muy costoso y muchas veces hasta resulta inviable.

Por este motivo, debemos empezar por ahí, por fijar los objetivos y tomar decisiones que sean claves para el desarrollo del proyecto. Aunque también es cierto que si nos podemos permitir el lujo de probar antes de tomar una elección, esto siempre nos ayudará a decidirnos.
Bien, mi proyecto se basará en OpenCV, estará escrito en C/C++ y ejecutable en la plataforma GNU/Linux.

OpenCV C/C++

Seguir leyendo

14 noviembre 2009 Posted by | Recursos | , , , , | Deja un comentario