¿Por qué utilizar programación orientada a objetos?
[Artículo previo: Aprender a programar: una breve introducción]
Las facilidades de modularización, encapsulación, abstracción y automatización que ofrece la orientación a objetos, tanto en la conceptualización (análisis y diseño) como en la programación, son las mejores y más maduras que podemos encontrar.
Estas características son imprescindibles para crear el complejo software que necesita la robótica, aunque para la parte del software que se ha de ejecutar en un microcontrolador la mejor solución suele ser simplemente C y programación estructurada. Pero para la robótica también es muy útil otro aspecto, una representación mucho más fácil de los elementos de la realidad que ha de manejar el software (actuadores, sensores, objetos del mundo real a percibir, acciones a realizar, …). Más adelante produndizaremos un poco más.
Las herramientas necesarias para utilizarlas son también muy maduras y muchas de ellas gratuitas y/o libres:
– lenguajes de programación: “libres” como C++, y no tan “libres” como Java y C# (empresas como Oracle y Microsoft mantienen poder sobre ellos)
– herramientas básicas como compiladores y entornos de edición y depuración de programas: los más libres, compilador GNU C++, entornos como Eclipse (no incluye compilador), no tan libre, como MonoDevelop o sólo gratuitos como Visual Studio Express que incluyen “compilador” (realmente no crea ejecutable para procesador, sino para máquina virtual, como Java).
¿En qué consiste?
Básicamente consiste en integrar en un único elemento, un objeto de una clase determinada, todo lo necesario para realizar su trabajo, tanto los datos a manejar como las operaciones que los manejan.
Un par de breves introducciones con mucha más información:
– Sencilla y clara presentación (pdf) de Martha Tello de Universidad Distrital Francisco José de Caldas (copia local por si falla el enlace)
– Clara y detallada presentación (pdf) de E.T.S.I. Telecomunicación Universidad de Málaga (copia local por si falla el enlace)
Libros gratuitos y libres:
– Programación orientada a objetos
– Con este Curso de C# puedes aprender fácil y progresivamente C# (pdf)
Un par de ejemplos en C++ y C#
Los siguientes diagramas y código fuente forman parte del software que da vida a Hexawheels, que tiene una versión en C++ y otra en C#.
Las clases HexaWheels y FuncionesBasicasHexaWheels, contienen el comportamiento, son la cúspide de la pirámide, ya que utilizan otras clases donde se realizan las comunicaciones, se reciben los datos de los sensores y se crean las secuencias de instrucciones para los servos.
Ejemplo C++:
Declaración de clases métodos y funciones:
#ifndef HEXAWHEELS_H_ #define HEXAWHEELS_H_ #include "FuncionesBasicasHexaWheels.h" namespace MiHexaWheels { class HexaWheels : public FuncionesBasicasHexaWheels { public: HexaWheels(); virtual ~HexaWheels(); void andarEvitandoObstaculos(); void rodarEvitandoObstaculos(); protected: int tiempoEspera; int velocidad; }; } /* namespace MiHexaWheels */ #endif /* HEXAWHEELS_H_ */
Definición de clases, métodos y funciones (“el cuerpo”):
#include "HexaWheels.h" namespace MiHexaWheels { HexaWheels::HexaWheels() { tiempoEspera = 500; velocidad = 200; } HexaWheels::~HexaWheels() { parar(); pausa(1000); } void HexaWheels::andarEvitandoObstaculos() { ponerPosicionEspera(); escaneadorFijoDMS.iniciar(1); avanzarAndando(); // Es un bucle infinito while (true) { // Si detecta un obstáculo maniobra para evitarlo if (escaneadorFijoDMS.siObstaculoDetectado()) { // retrocederTransversal(velocidad); // y dejamos pasar un tiempo para que retroceda unos centímetros //walker. //pausa(tiempoEspera); pararAndar(); situarPosicionRuedas(Circular); pausa(tiempoEspera); // esperar o ir comprobando si aún se siguen moviendo los servos girarIzquierda(velocidad * 2); // y dejamos pasar un tiempo para que retroceda unos centímetros pausa(tiempoEspera * 2);// esperar o ir comprobando si aún se siguen moviendo los servos parar(); pausa(tiempoEspera); // esperar o ir comprobando si aún se siguen moviendo los servos // seguimos avanzando continuarAndando(); } } } void HexaWheels::rodarEvitandoObstaculos() { situarPosicionRuedas(Transversal); escaneadorGiratorioDMS.iniciar(3); avanzarTransversal(velocidad); // Es un bucle infinito while (true) { // Si detecta un obstáculo maniobra para evitarlo if (escaneadorGiratorioDMS.siObstaculoDetectado()) { retrocederTransversal(velocidad); // y dejamos pasar un tiempo para que retroceda unos centímetros pausa(tiempoEspera); girarIzquierda(velocidad * 2); // y dejamos pasar un tiempo para que retroceda unos centímetros pausa(tiempoEspera * 2); // seguimos avanzando avanzarTransversal(velocidad); } } } } /* namespace MiHexaWheels */
Ejemplo C#:
namespace MiHexaWheels { // La clase Quadropodo hereda las funciones básicas de la clase FuncionesBasicasQuadropodo class HexaWheels : FuncionesBasicasHexaWheels { protected int tiempoEspera = 500; protected int velocidad = 200; // De momento lo único que sabe hacer es pasear evitando obstáculos public void rodarEvitandoObstaculos() { situarPosicionRuedas(PosicionRuedas.Transversal); escaneoGiratorioDMS.iniciar(); avanzarTransversal(velocidad); // Es un bucle infinito while (true) { // Si detecta un obstáculo maniobra para evitarlo if (escaneoGiratorioDMS.siObstaculoDetectado()) { retrocederTransversal(velocidad); // y dejamos pasar un tiempo para que retroceda unos centímetros pausa(tiempoEspera); girar(DireccionGiro.izquierda, velocidad * 2); // y dejamos pasar un tiempo para que retroceda unos centímetros pausa(tiempoEspera * 2); // seguimos avanzando avanzarTransversal(velocidad); } } } public void andarEvitandoObstaculos() { ponerPosicionEspera(); escaneoFijoDMS.iniciar(); avanzarAndando(); // Es un bucle infinito while (true) { // Si detecta un obstáculo maniobra para evitarlo if (escaneoFijoDMS.siObstaculoDetectado()) { // retrocederTransversal(velocidad); // y dejamos pasar un tiempo para que retroceda unos centímetros //walker. //pausa(tiempoEspera); pararAndar(); situarPosicionRuedas(PosicionRuedas.Circular); pausa(tiempoEspera); // esperar o ir comprobando si aún se siguen moviendo los servos girar(DireccionGiro.izquierda , velocidad * 2); // y dejamos pasar un tiempo para que retroceda unos centímetros pausa(tiempoEspera * 2);// esperar o ir comprobando si aún se siguen moviendo los servos parar(); pausa(tiempoEspera); // esperar o ir comprobando si aún se siguen moviendo los servos // seguimos avanzando continuarAndando(); } } } // ¿qué más le podemos enseñar? 😉 } }