lunes, 2 de octubre de 2017

Reto sacar bloques con Lego NXT

Descripción del reto Reto

El reto consiste en sacar las cajas de icopor de la pista según el color que tenga en la parte superior . Competirán dos robots simultáneamente donde ganará el que más puntos realice.

RetoLegoBloquesRev002.png
Figura 1. Configuración de la pista
  1. Reglas

  • El día del evento se entregará a los concursantes el mapa de los bloques, indicando la ubicación y el color.
  • Los equipos tendrán tiempo de introducir el mapa de los bloques en el programa. El mapa solo se introducirá una vez en el robot.
  • En el momento de participar el color del bloque a sacar se hará de forma aleatoria por medio del lanzamiento de una moneda.
  • Para hacer un punto solo es necesario que el robot toque el bloque del color correcto, no es necesario moverlo o sacarlo de la pista, aunque no hay penalización en caso de hacerlo.
  • El robot debe tener un menú en pantalla para seleccionar el color del bloque que debe sacar.
  1. Puntuación

    Bloques
    Puntos
    1 a 5
    1 punto por bloque
    6 a 10
    2 puntos por bloque
    11 a 12
    5 puntos por bloque

    Tocar o sacar bloques del color opuesto, dará puntos al equipo contrario

    El equipo que termine primero el recorrido tendrá un bonificación de 5 puntos.
  2. Tipo de robot

La configuración empleada será el multibot Seguidor (Figura 2) al cual se le adecuará un sensor de color frontal.

SeguidorLinea.JPG
Figura 2: Multibot Seguidor consultado en: http://nxtprograms.com/NXT2/multi-bot/index.html
  1. Características de la pista de la pista

La pista de exploración tendrá las siguientes características
RetoLegoBloquesRev001
Figura 3: Pista vista superior

  • 1 metros de ancho.
  • 2 metros de largo.
  • Cubos de incopor de 5 cm.
  • Los cubos están distribuidos cada 20 cm
    Cada columna tendrá 8 cubos, 4 verdes y 4 azules distribuidos de forma aleatoria.
  • Fondo del piso de color blanco.
  • Robot inician a la Izquierda.
    El primer cubo estará a 10 cm del punto de inicio del robot.
    El Punto de cruce estará a 10 cm del ultimo cubo de la primer fila
  • Línea negra de 2 cm de ancho.

miércoles, 30 de agosto de 2017

Integrar Java Swing en Processing

Integración de Java Swing en Processing

Estructura básica

Este ejemplo de código implementa la creación del panel en el cual se agregaran los controles de la aplicación en Processing. En la siguiente figura se muestra las ventanas resultantes para este ejemplo, la tradicional ventana correspondiente al lienzo o sketch de Processing y otra correspondiente al aplicativo Java con Swing.
A partir de esta plantilla básica se procede a desarrollar la aplicación agregando botones, sliders, etc.

Ventanas estructura básica.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

MyPanel controlPanel= new MyPanel();
 void setup() {
  JFrame frame = new JFrame("Ejemplo Frame");
  frame.setContentPane(controlPanel);
  frame.pack();
  frame.setVisible(true);
}
void draw() {
}
public class MyPanel extends JPanel {
    public MyPanel() {
       setPreferredSize(new Dimension(200, 400));
       setLayout(null);
   }
}

Agregando Botones

Este ejemplo de código implementa agrega un botón y el evento de click para este botón.
En el ejemplo el botón se llama boton01 pero puede tener cualquier otro nombre, pero se sugiere que para distinguir varios botones en la aplicación estos tengan en su nombre una numeración.
el método boton01.setBounds(0, 0, 200, 25); sirve para indicar la posición y tamaño del botón en el panel, su formato es el siguiente setBounds(x,y,ancho,alto) donde las coordenadas x,y corresponden a la esquina superior izquierda y ancho, alto a las dimensiones del botón.
Para agregar el evento de click se emplea el método y en este se indica como se llama la clase que implementa el método boton01.addActionListener(new ClickBoton01()); para detectar el evento de click en este botón. Para este ejemplo al clase se llama ClickBoton01 pero el nombre puede ser cualquiera, es importante indicar que por lo general cada botón tiene su propio evento de click indicado con un nombre que lo diferencia de los demás.
 
Creación de un botón.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

MyPanel controlPanel= new MyPanel();
 void setup() {
  JFrame frame = new JFrame("Ejemplo Frame");
  MyPanel controlPanel= new MyPanel();
  frame.setContentPane(controlPanel);
  frame.pack();
  frame.setVisible(true);
}
void draw() {
}
public class MyPanel extends JPanel {
  private JButton boton01;
  public MyPanel() {
    setPreferredSize(new Dimension(200, 400));
    setLayout(null);
    boton01 = new JButton ("Presionar");
    boton01.setBounds(0, 0, 200, 25);
    add(boton01);
    boton01.addActionListener(new ClickBoton01());
  }
}
class ClickBoton01 implements ActionListener{
  public void actionPerformed(ActionEvent e){
    JButton b = (JButton)e.getSource();
    b.setLabel("Presionado");
  }


Cambiar el Color de Fondo del Sketch al Presionar un Botón

Este ejemplo permite cambiar el color de fondo de blanco a negro y viceversa al presionar un único botón, para esto se agrega una variable de tipo booleano que cambia de estado cada vez que se presiona el botón.

Botón para cambiar color de fondo


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
MyPanel controlPanel= new MyPanel();
boolean banderaBoton01 = true;
void setup() {
  JFrame frame = new JFrame("Ejemplo Frame");

  frame.setContentPane(controlPanel);
  frame.pack();
  frame.setVisible(true);
  size(400,400);
}
void draw() {
  if (banderaBoton01) {
    background(255);//Blanco
  } else {
    background(0);//Falso
  }
}
public class MyPanel extends JPanel {
  private JButton boton01;
  public MyPanel() {//Metodo constructor
    setPreferredSize(new Dimension(200, 400));
    setLayout(null);
    boton01 = new JButton ("Blanco");
    boton01.setBounds(0, 0, 200, 25);
    add(boton01);
    boton01.addActionListener(new ClickBoton01());
  }
}
class ClickBoton01 implements ActionListener {
  public void actionPerformed(ActionEvent e) {
    JButton b = (JButton)e.getSource();
    banderaBoton01=!banderaBoton01;//Cambia de estado al negarse a si misma
    if (banderaBoton01) {
      b.setLabel("Blanco");
    } else {
      b.setLabel("Negro");
    }
   
  }
}

Cambiar el Color del panel y el botón

Los objetos de Swing como los botones y paneles tienen propiedades de color que se pueden cambiar con el metodo setBackground() .
Los colores que se pueden seleccionar directamente son: Color.lightGray Color.gray Color.darkGray Color.blue Color.cyan Color.green Color.yellow Color.magenta Color.orange Color.pink Color.red Color.white Color.black
Para agregar un color empleando el formato RGB empleamos la objeto Color que en este ejemplo se utilizo  de la siguiente manera para cunado se presiona el botón b.setBackground(new Color( 128, 0, 32 ));

Panel gris y botón amarillo
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

MyPanel controlPanel= new MyPanel();
 void setup() {
  JFrame frame = new JFrame("Ejemplo Frame");
  frame.setContentPane(controlPanel);
  frame.pack();
  frame.setVisible(true);
}
void draw() {
}
public class MyPanel extends JPanel {
  private JButton boton01;
  public MyPanel() {
    setPreferredSize(new Dimension(200, 400));
    setLayout(null);
    setBackground(Color.gray);//Color del panel
    boton01 = new JButton ("Presionar");
    boton01.setBounds(0, 0, 200, 25);
    boton01.setBackground(Color.yellow);//Color del boton
    add(boton01);
    boton01.addActionListener(new ClickBoton01());
  }
}
class ClickBoton01 implements ActionListener {
  public void actionPerformed(ActionEvent e) {
    JButton b = (JButton)e.getSource();
    b.setLabel("Presionado");
    b.setBackground(new Color( 128, 0, 32 ));
  }


Cambiar valores de los controles desde la función  draw()

Las propiedades de los objetos pueden ser cambiados desde la función draw(), en este ejemplo se visualiza el tiempo transcurrido en milisegundo en una etiqueta JLabel esto se hace con la siguiente isntruccion donde se modifica la propiedad del texto controlPanel.texto01.setText(str(millis())); donde el metodo setText cambia el texto que es de tipo string. Para convertir el valor entero de la funcion millis() se emplea la funcion srt() que convierte un dato tipo int o float a una cadena de caracteres string
 
Mostrar tiempo en milisegundos

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
boolean baderaCrono = false;
MyPanel controlPanel= new MyPanel();
void setup() {
  JFrame frame = new JFrame("Cronometro");
  frame.setContentPane(controlPanel);
  frame.pack();
  frame.setVisible(true);
}
void draw() {
  if (baderaCrono) {
    controlPanel.texto01.setText(str(millis()));
  }
}
public class MyPanel extends JPanel {
  private JButton boton01;
  private JLabel texto01;
  public MyPanel() {
    setPreferredSize(new Dimension(200, 400));
    setLayout(null);
    boton01 = new JButton ("Cronometrar");
    boton01.setBounds(0, 0, 200, 25);
    add(boton01);
    boton01.addActionListener(new ClickBoton01());
    texto01= new JLabel("0");
    texto01.setBounds(0, 25, 200, 25);
    texto01.setForeground(Color.blue);
    add(texto01);
  }
}
class ClickBoton01 implements ActionListener {
  public void actionPerformed(ActionEvent e) {
    JButton b = (JButton)e.getSource();
    baderaCrono=!baderaCrono;
    if (baderaCrono) {
      b.setLabel("Pausar");
    } else {
      b.setLabel("Cronometrar");
    }
  }
}

miércoles, 5 de octubre de 2016

Botones En Processing

REALIZACIÓN DE BOTONES EN PROCESSING

Processing no cuenta por defecto funciones o clases que permitan la realización de elementos gráficos como botones u otro tipo de control.
Hay varias opciones, entre ellas la herramienta G4P GUI Builder que se puede instalar desde el propio entorno de desarrollo de Processing.

 
Ejemplo de uso de G4P GUI Bulider

 Ejemplo de código:

Otra opción es la programación propia de los controles  como el caso de este ejemplo que incluye un botón tipo encendido y apagado junto con un botón deslizante

Código fuente en Processing

Boton botonUno, botonDos;
SliderH sliderUno,sliderDos;
void setup() {
  size(800, 600);
  botonUno=new Boton(0, 0, 100, 50);
  botonDos=new Boton(100, 0, 100, 50);
  sliderUno=new SliderH(0,200,0,200);
  sliderDos=new SliderH(0,200,200,300);
}
void draw() {
  if (botonUno.getEstado()) {
    background(0);
  } else {
    background(255);
  }
  sliderUno.dibujar();
  sliderDos.dibujar();
  botonUno.dibujar();
  botonDos.dibujar();
  if(mousePressed){
    sliderUno.moverSlider(mouseX,mouseY);
    sliderDos.moverSlider(mouseX,mouseY);
  }
  println("Valor = "+int(sliderUno.calcularValor(0,360)));
  println("Id Boton "+botonUno.getIdOnOff());
}
void mousePressed() {
  botonUno.toggleOver(mouseX, mouseY);
  botonDos.toggleOver(mouseX, mouseY);
}
//Clase para realizar botones on off y con numeracion
class Boton {
  int posX, posY, anchoBoton, altoBoton, idNumero;
  color colorON, colorOff;
  boolean banderaOnOff;
  Boton(int x, int y, int ancho, int alto) {
    posX=x;
    posY=y;
    anchoBoton=ancho;
    altoBoton=alto;
    colorON=color(0, 255, 0);
    colorOff=color(255, 0, 0);
    banderaOnOff=false;
    idNumero=1;
  }
  void dibujar() {
    if (banderaOnOff) {
      fill(colorON);
    } else {
      fill(colorOff);
    }
    rect(posX, posY, anchoBoton, altoBoton);
  }
  void setOn() {
    banderaOnOff=true;
  }
  void setOff() {
    banderaOnOff=false;
  }
  void toggle() {
    banderaOnOff=!banderaOnOff;
  }
  void setDimensiones(int x, int y, int ancho, int alto) {
    posX=x;
    posY=y;
    anchoBoton=ancho;
    altoBoton=alto;
  }
  void toggleOver(int x, int y) {
    if (x>posX && x<(posX+anchoBoton) && y>posY && y<(posY+altoBoton)) {
      banderaOnOff=!banderaOnOff;
    }
  }
  boolean getEstado() {
    return  banderaOnOff;
  }
  void setIdentificacion(int numero) {
    idNumero=numero;
    if (idNumero<=0)//las identificaciones no pueden ser menores o iguales a cero
      idNumero=1;//identificacion por defecto
  }
  int getIdentificacion() {
    return idNumero;
  }
  int getIdOnOff() {//retorna la identificacion se esta on y cero si esta off
    int id;
    if (banderaOnOff) {
      id=idNumero;
    } else {
      id=0;
    }
    return id;
  }
}
//Clase para realizar botones deslizantes
class SliderH {
  int orgX, finX, posX, posVer;
  float minVal, maxVal, resVal;
  color colorSlider;
  SliderH(int x0, int x1, int px, int posv) {
    orgX=x0;
    finX=x1;
    posX=px;
    posVer=posv;
    colorSlider=color(0, 0, 255);
    minVal=x0;
    maxVal=x1;
  }
  void dibujar() {
    line(orgX, posVer, finX, posVer);
    fill(colorSlider);
    rect(posX-5, posVer-10, 10, 20);
  }
  int moverSlider(int x, int y) {
    if (x>=orgX && x<= finX) {
      if (x>(posX-5) && x<(posX+10) && y>(posVer-10) && y<(posVer+20)) {
        posX=x;
      }
    }
    return posX;
  }
  int incSlider(int inc) {
    posX=posX+inc;
    if (posX>finX) {
      posX=finX;
    }
    return posX;
  }
  int decSlider(int dec) {
    posX=posX+dec;
    if (posX<orgX) {
      posX=orgX;
    }
    return posX;
  }
  int getPos() {
    return posX;
  }
  void setPos(int px) {
    posX=px;
    if (posX>finX) {
      posX=finX;
    } else if (posX<orgX) {
      posX=orgX;
    }
  }
  void setValores(float min, float max) {
    minVal=min;
    maxVal=max;
  }
  float calcularValor(float min, float max) {
    minVal=min;
    maxVal=max;
    resVal=map(posX, orgX, finX, minVal, maxVal);
    return resVal;
  }
}



miércoles, 11 de mayo de 2016

Conversion de una cadena a un numero entero en Processing

Conversión De Una Cadena De Caracteres Enviada Por El Puerto Serie A Un Número Entero En Processing

Los datos enviados por el puerto serie corresponden a un código que representa caracteres alfanuméricos, este código empleado se llama ASCII y es un estándar empleado para el envió y recepción de datos.
Muchos de los datos enviados son numéricos pero representados en ASCII por lo cual es necesario una conversion del conjunto de datos o cadena recibida a su valor numérico decimal correspondiente.
En este ejemplo se envía una cadena de caracteres desde un microcontrolador por el puerto serie, la cadena tiene los caracteres de salto de linea y retorno de carro.

Caracteres no imprimibles presentes en la cadena

Caracter Nulo '\0' es el terminador de una cadena su código ASCII es el 0 también se representa con la palabra reservada null
Caracter New Line '\n' es el salto de linea su codigo ASCII es el 10
Caracter Back Space '\b' es el terminador de una cadena su codigo ASCII es el 8
Caracter Carriage Return '\r' retorno de carro su codigo ASCII es el 13
Pinguino o Arduino envía un retorno de carro '\r' y un salto de linea '\n' cuando se emplea la instruction Serial.println()
Pinguino o Arduino con la instrucción Serial.print() no envía los caracteres especiales de salto de linea y retorno de carro

Referencia

Código Pinguino o Arduino

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println("123");
}

Código Processing

import processing.serial.*;//libreria de comunicacion serial
Serial miPuerto;//Objeto puerto
String strNombrePuerto;//Cadena de caracteres para almacenar el nombre del puerto a emplear en la comunicacion
String strDatoRecibido="";//Cadena de caracteres para almacenar el dato enviado por el microcontrolador
String strDato="";
int intDatoRecibido;
void setup() {
  size(200, 200);
  println("Puertos disponible: "+Serial.list());//muestra el listado de los puertos disponibles para comunicacion serial
  strNombrePuerto=Serial.list()[0];//Nombre del puerto 0 del listado de puertos seriales disponibles
  println(strNombrePuerto);//Muestra el nobre del puerto 0 en consola
  miPuerto=new Serial(this, strNombrePuerto, 9600);//configuracion del puerto a 9600 baudios
}
void draw() {
  if ( miPuerto.available() > 0) { //Verifica que hay un nuevo dato 
    strDatoRecibido = miPuerto.readStringUntil('\n');//almacena hasta encontrar el caracter de salto de linea
  }
  if (strDatoRecibido.length()==5) {//la cadena enviada por el microcontrolador tiene 5 caracters tres digitos mas salto de linea y retorno de carro
    strDatoRecibido = trim(strDatoRecibido);//elimina los caracteres especiales de la cadena como retorno de carro y salto de linea
    println("tamaño "+strDatoRecibido.length());//El tamaño a mostrar debe ser 3 ya que elimino el retorno de carro y salto de linea
    println("cadena "+strDatoRecibido);//Muestra la cadena recibida
    intDatoRecibido=Integer.parseInt(strDatoRecibido);//Convierte la cadena recibida a un valor entero
    println("entero "+intDatoRecibido);//Muestra el valor entero
  }
  println("Cantidad de datos en el buffer: "+miPuerto.available());//Muestra cuantos datos hay en el buffer
  miPuerto.clear();//limpia el buffer de recepcion de datos seriales
}

jueves, 5 de mayo de 2016

Como hacer un Slider Button en Processing

Slider Button En Proccesing

Processing no cuenta de forma nativa con una instrucción que permita asignar de forma directa por medio del teclado un valor numérico a las variables que se estén empleando en un programa.
Processing esta enfocado a gráficos e interacción con ellos. En esta publicación se describe como hacer un botón deslizante para asignar variables numéricas a variables que se empleen en un programa.

Botón Deslizante Básico




En este primer ejemplo se muestra el fundamento de botón deslizante que depende de la posición de ratón en el eje X.
El botón es un rectángulo realizado por la instrucción rect(PosDes01,10,5,10) donde la posición en X esta dada por PosDes01.
La posición cambia cuando el ratón es presionado y la variable tomara el valor del ratón en X por medio de mouseX. Esto se hace con las siguientes instrucciones
 if (mousePressed) {
    PosDes01=mouseX;
  }

Código de ejemplo

int PosDes01;
void setup() {
  size(400, 100);
  PosDes01=0;
}
void draw() {
  background(255);
  if (mousePressed) {
    PosDes01=mouseX;
  }
  line(0, 15, 600, 15);
  fill(0);
  rect(PosDes01, 10, 5, 10);
  text("Posición = "+PosDes01,10, 50);
}


Boton deslizante y la funcion map


 

Con la funcion map() podemos adaptar el boton deslizante a un rango deseado, por ejemplo de 0 a 180 para simular la inclinacion de un objeto o de 0 a 5 para representar el valor de voltaje leido desde una tarjeta microcontrolada como Pinguino o Arduino.

Codigo de ejemplo 

int PosDes01;
float Voltaje, Angulo;
void setup() {
  size(400, 100);
  PosDes01=0;
}
void draw() {
  background(255);
  if (mousePressed) {
    if (mouseX<=0) {
      PosDes01=0;
    } else if (mouseX>=width) {
      PosDes01=width;
    } else {
      PosDes01=mouseX;
    }
  }
  line(0, 15, width, 15);
  fill(0);
  rect(PosDes01, 10, 5, 10);
  Angulo=map(PosDes01, 0, width, 0, 180);
  Voltaje=map(PosDes01, 0, width, 0, 5);
  text("Posición = "+PosDes01, 10, 50);
  text("Angulo = "+Angulo, 10, 70);
  text("Voltaje = "+Voltaje, 10, 90);
}