The Lost Period


Introdução a Robótica

— Professor: Mário Fernando Montenegro Campos

— 2° semestre de 2011

Integrantes

Leandro Henrique Costa Andrade 2011/09/04 12:16

Guilherme Silva Terra 2011/09/04 12:16

Daniel Salviano Araújo 2011/09/04 12:16

Paulo Eduardo 2011/09/04 12:16

"Wer hat davon spricht der Mund, was er will", Samuel de Jesus


TP final (competição):

competicao


Trabalho Prático 1



Trabalho Prático 2

#use fencdr5.icb
#use fencdr6.icb

int i = 0, u = 0, sum = 0, option, init, power0, power1;
int startButton, stopButton, lineFollowID, waitBlockID, alignPolarizedLightID, showDistanceID, showValuesLineID;
float ratio_point = 0.977; Valor percorrido pela roda a cada contagem do Encoder
float d_rot = 15.0; Diametro do eixo
float grad_point =1)

1) d_rot*3.14)/ratio_point)/360.0; Graus rotacionados pelo eixo a cada contagem do Encoder
int rot_ref = (int) (90.0*grad_point); Conuts necessrios para rotacionar 90 graus
float goOn_dist1 = 15.0; Distancia percorrida perpendicular a linha
float goOn_dist2 = 30.0; Distancia percorrida paralela a linha
int dist = knob();

int MOTOR_LEFT = 0; Encoder 5
int MOTOR_RIGHT = 1; Encoder 6

int LINE_LEFT_LIMIT = 96; > preto
int LINE_RIGHT_LIMIT = 55; > preto

int LINE_SENSOR_LEFT = 3;
int LINE_SENSOR_RIGHT = 2;
int PROX_SENSOR = 4;

int LIGHT_HORIZONTALLY = 3; Esquerda (Mesa) → Torta
int LIGHT_VERTICALLY = 2; Direita (Armario)

int YELLOW = 3001;
int GREEN = 3002;
int BLUE = 3003;
int RED = 3004;

default
int GO_AROUND_LEFT = YELLOW;
int GO_AROUND_RIGHT = GREEN;
int PUSH_BLOCK = BLUE;
int STOP = RED;

int BLOCK_DETECTED = 0;

float RED_red_default = 115.0;
float RED_green_default = 155.0;
float RED_blue_default = 144.0;
float GREEN_red_default = 137.0;
float GREEN_green_default = 80.0;
float GREEN_blue_default = 95.0;
float YELLOW_red_default = 80.0;
float YELLOW_green_default = 70.0;
float YELLOW_blue_default = 83.0;
float BLUE_red_default = 190.0;
float BLUE_green_default = 140.0;
float BLUE_blue_default = 100.0;

float vermelho;
float verde;
float azul;
float errovermelho;
float erroverde;
float erroamarelo;
float erroazul;

float modulo (float n){
  if (n < 0.0) return -n;
  else return n;
} int color = 0; void showValuesLine () {
  while(1){
      printf ("\nEsq: %d  Dir: %d  Frente: %d", analog(LINE_SENSOR_LEFT), analog(LINE_SENSOR_RIGHT), analog(PROX_SENSOR));
      sleep(0.1);
  }
} void lineFollow (){
  
  int first = 0;
  
  motor(MOTOR_LEFT, 50);
  motor(MOTOR_RIGHT, 50);
  motor(2,50);
  motor(3,50);
  
  showValuesLineID = start_process(showValuesLine());
  
  while (1){        
      
      if (analog(LINE_SENSOR_LEFT) < LINE_LEFT_LIMIT && analog(LINE_SENSOR_RIGHT) > LINE_RIGHT_LIMIT) {
          goRight();
          if (first == 0) first = LINE_SENSOR_RIGHT;
      }
      else if (analog(LINE_SENSOR_LEFT) > LINE_LEFT_LIMIT && analog(LINE_SENSOR_RIGHT) < LINE_RIGHT_LIMIT) {
          goLeft();
          if (first == 0) first = LINE_SENSOR_LEFT;
      }
      else if (analog(LINE_SENSOR_LEFT) > LINE_LEFT_LIMIT && analog(LINE_SENSOR_RIGHT) > LINE_RIGHT_LIMIT) {
          if (first == LINE_SENSOR_RIGHT) {
              power0 = -30;
              power1 = 30;
          }
          else {
              power0 = 30;
              power1 = -30;
          }
          
          motor(MOTOR_LEFT, power0);
          motor(MOTOR_RIGHT, power1);
          
          while (analog(LINE_SENSOR_LEFT) > LINE_LEFT_LIMIT && analog(LINE_SENSOR_RIGHT) > LINE_RIGHT_LIMIT);
          
          if (analog(LINE_SENSOR_LEFT) < LINE_LEFT_LIMIT) first = LINE_SENSOR_RIGHT;
          else first = LINE_SENSOR_LEFT;    
      }            
      else goAhead();
      
  }
} void waitBlock (){
  while(1) {
     
      int erro = 25, atual;
      lineFollowID = start_process(lineFollow());
      while (1){
          atual = analog(PROX_SENSOR);
          sleep(0.1);
          if(analog(PROX_SENSOR) > atual + erro){
              motor(MOTOR_RIGHT, 0);
              motor(MOTOR_LEFT, 0);
              break;
          }  
      }
     
      kill_process(lineFollowID);
     
      motor(MOTOR_LEFT, -50);
      motor(MOTOR_RIGHT, -50);
      sleep(0.2);
      color = lookColor();
      if (color == GO_AROUND_LEFT) goAroundLeft();
      else if (color == GO_AROUND_RIGHT) goAroundRight();
      else if (color == PUSH_BLOCK) pushBlock (dist);
      
  }
} int lookColor() {
  alloff();
  sleep (0.2);
  
  kill_process (showValuesLineID);
  
  poke(0x1009, 0x3c);
  bit_set(0x1008, 0x4c);
  sleep(0.3);
  for (i = 0; i<10;i++){
      sleep(0.3);
      vermelho=vermelho+(float)analog(PROX_SENSOR);
      printf("\nVERMELHO: %d", analog(PROX_SENSOR));
  }
  sleep(0.3);
  bit_clear(0x1008, 0x4c); 
  
  bit_set(0x1008, 0x3c);
  bit_clear(0x1008, 0x1c);
  sleep(0.3);
  for (i = 0; i<10;i++){
      sleep(0.3);
      verde=verde+(float)analog(PROX_SENSOR);
      printf("\nVERDE: %d", analog(PROX_SENSOR));
  }
  sleep(0.3);
  bit_clear(0x1008, 0x3c); 
  
  bit_set(0x1026, 0x80);
  bit_set(0x1000, 0x80);  
  sleep(0.3);
  for (i = 0; i<10;i++){
      sleep(0.3);
      azul=azul+(float)analog(PROX_SENSOR);
      printf("\nAZUL: %d", analog(PROX_SENSOR));
  }
  sleep(0.3);
  bit_clear(0x1000,0x80); 
  errovermelho=modulo(vermelho/(vermelho+verde+azul)- RED_red_default/(RED_red_default + RED_green_default + RED_blue_default));
  errovermelho=errovermelho+modulo(verde/(vermelho+verde+azul)- RED_green_default/(RED_red_default + RED_green_default + RED_blue_default));
  errovermelho=errovermelho+modulo(azul/(vermelho+verde+azul)- RED_blue_default/(RED_red_default + RED_green_default + RED_blue_default));
  erroverde=modulo(vermelho/(vermelho+verde+azul)- GREEN_red_default/(GREEN_red_default + GREEN_green_default + GREEN_blue_default));
  erroverde=erroverde+modulo(verde/(vermelho+verde+azul)- GREEN_green_default/(GREEN_red_default + GREEN_green_default + GREEN_blue_default));
  erroverde=erroverde+modulo(azul/(vermelho+verde+azul)- GREEN_blue_default/(GREEN_red_default + GREEN_green_default + GREEN_blue_default));
  erroamarelo=modulo(vermelho/(vermelho+verde+azul)- YELLOW_red_default/(YELLOW_red_default + YELLOW_green_default + YELLOW_blue_default));
  erroamarelo=erroamarelo+modulo(verde/(vermelho+verde+azul)- YELLOW_green_default/(YELLOW_red_default + YELLOW_green_default + YELLOW_blue_default));
  erroamarelo=erroamarelo+modulo(azul/(vermelho+verde+azul)- YELLOW_blue_default/(YELLOW_red_default + YELLOW_green_default + YELLOW_blue_default));
  erroazul=modulo(vermelho/(vermelho+verde+azul)- BLUE_red_default/(BLUE_red_default + BLUE_green_default + BLUE_blue_default));
  erroazul=erroazul+modulo(verde/(vermelho+verde+azul)- BLUE_green_default/(BLUE_red_default + BLUE_green_default + BLUE_blue_default));
  erroazul=erroazul+modulo(azul/(vermelho+verde+azul)- BLUE_blue_default/(BLUE_red_default + BLUE_green_default + BLUE_blue_default));
  
  if(erroamarelo<erroazul&&erroamarelo<erroverde&&erroamarelo<errovermelho){
      printf("\nAMARELO");
      sleep(2.0);
      return YELLOW;
  }
  if(erroverde<erroazul&&erroverde<erroamarelo&&erroverde<errovermelho){
      printf("\nVERDE");
      sleep(2.0);
      return GREEN;
  }
  if(errovermelho<erroazul&&errovermelho<erroverde&&errovermelho<erroamarelo){
      printf("\nVERMELHO");
      sleep(2.0);
      return RED;
  }
  if(erroazul<erroverde&&erroazul<errovermelho&&erroazul<erroamarelo){
      printf("\nAZUL");
      sleep(2.0);
      return BLUE;
  }    
} void goRight(){
  motor(MOTOR_LEFT, 40);
  motor(MOTOR_RIGHT, 0);    
} void goLeft(){
  motor(MOTOR_RIGHT, 40);
  motor(MOTOR_LEFT, 0);    
} void goAhead(){
  motor(MOTOR_RIGHT, 50);
  motor(MOTOR_LEFT, 50);    
} void stop(){
  motor(MOTOR_RIGHT, 0);
  motor(MOTOR_LEFT, 0);
  sleep(5.0);
} void goOn(float ref){
  power0 = 0;
  power1 = 0;
  encoder5_counts = 0;
  encoder6_counts = 0;
  do {            
      power0 = 10 * ((int) (ref/ratio_point) - encoder6_counts);
      power1 = 10 * ((int) (ref/ratio_point) - encoder5_counts );
      motor(MOTOR_RIGHT, power0);
      motor(MOTOR_LEFT, power1);
  }while (power0 > 0 && power1 > 0);
} void turnLeft(){
  power0 = 0;
  power1 = 0;
  encoder5_counts = 0;
  encoder6_counts = 0;
  do {            
      power0 = 10 * (rot_ref - encoder6_counts );
      power1 = 10 * (rot_ref - encoder5_counts );
      motor(MOTOR_RIGHT, power0);
      motor(MOTOR_LEFT, -power1);
  }while (power0 > 0 && power1 > 0);    
} void turnRight(){
  power0 = 0;
  power1 = 0;
  encoder5_counts = 0;
  encoder6_counts = 0;
  do {            
      power0 = 10 * (rot_ref - encoder6_counts );
      power1 = 10 * (rot_ref - encoder5_counts );
      motor(MOTOR_RIGHT, -power0);
      motor(MOTOR_LEFT, power1);
  }while (power0 > 0 && power1 > 0);
} void goAroundLeft(){
  turnLeft();
  sleep(0.2);
  goOn(goOn_dist1);
  sleep(0.2);
  turnRight();
  sleep(0.2);
  goOn(goOn_dist2);
  sleep(0.2);
  turnRight();
  sleep(0.2);
  goOn(goOn_dist1);
  sleep(0.2);
  turnLeft();
  sleep(0.2);
  
  alloff();
} void goAroundRight(){
  turnRight();
  sleep(0.2);
  goOn(goOn_dist1);
  sleep(0.2);
  turnLeft();
  sleep(0.2);
  goOn(goOn_dist2);
  sleep(0.2);
  turnLeft();
  sleep(0.2);
  goOn(goOn_dist1);
  sleep(0.2);
  turnRight();
  sleep(0.2);
  
  alloff();
} void pushBlock(int dist){
  int ref_dist = (int) ((float)dist/ratio_point);
  power0 = 0;
  power1 = 0;
  encoder5_counts = 0;
  encoder6_counts = 0;
  do {            
      power0 = 10 * (ref_dist - encoder6_counts );
      power1 = 10 * (ref_dist - encoder5_counts );
      motor(MOTOR_RIGHT, power0);
      motor(MOTOR_LEFT, power1);
  }while (power0 > 0 && power1 > 0);
} void alignPolarizedLight (int light_sensor){
  
  float angle = 360.0;
  int erro = 10;
  int minimo = 300;
  int value = 0;
  
  power0 = 0;
  power1 = 0;
  encoder5_counts = 0;
  encoder6_counts = 0;
  do {            
      power0 = 10 * ((int)(angle*grad_point) - encoder6_counts );
      power1 = 10 * ((int)(angle*grad_point) - encoder5_counts );
      motor(MOTOR_RIGHT, power0);
      motor(MOTOR_LEFT, -power1);
      
      value = analog(light_sensor);
      if (value < minimo) minimo = value;
      
  }while (power0 > 0 && power1 > 0);     
  
  motor (MOTOR_RIGHT, -40);
  motor (MOTOR_LEFT, 40);
  
  while(1){
      
      sum = 0;
      for (u = 0; u < 5; u++){
          sum = sum + analog(light_sensor);           
          sleep (0.1);
      }
      value = sum/5;
      if (value < minimo + erro && value > minimo - erro){        
          
          if (light_sensor == LIGHT_VERTICALLY) {
              angle = 30.0; 
              
              power0 = 0;
              power1 = 0;
              encoder5_counts = 0;
              encoder6_counts = 0;
              do {            
                  power0 = 10 * ((int)(angle*grad_point) - encoder6_counts );
                  power1 = 10 * ((int)(angle*grad_point) - encoder5_counts );
                  motor(MOTOR_RIGHT, power0);
                  motor(MOTOR_LEFT, -power1);
              }while (power0 > 0 && power1 > 0);
          }
          
          printf ("\nACHOU LUZ");
          
          goAhead();
          sleep(3.0);            
      }   
  }
} void showDistance(){
  while (1){
      sleep(0.5);
      printf ("\nConfirme a distancia: %d", knob());
  }    
} void waitStop (){
  stop_press();
  option = -1;
} void waitStart (){
  start_press();
  option = 1;
} int wait(){
  option = 0;
  startButton = start_process(waitStart());
  stopButton = start_process(waitStop());    
  while (option == 0)sleep(0.1);
  if (option == -1) kill_process(startButton);
  if (option == 1) kill_process(stopButton);
  return option;
} void initialize(){
  init = 0;
  motor (0,0);
  motor (1,0);
  motor (2,0);
  motor (3,0);
  bit_clear(0x1008, 0x4c); 
  bit_clear(0x1008, 0x1c); 
  bit_clear(0x1008, 0x3c); 
  bit_clear(0x1000, 0x80); 
} void main(){
  
  while (1) {
      
      initialize();
      
      printf ("\nSeguir Linha ?");
      if (wait() == 1){
          
          int choice_AROUND_LEFT = 0;
          int choice_AROUND_RIGHT = 0;
          int choice_STOP = 0;
          int choice_PUSH = 0;
          
          // Yellow
          while (choice_AROUND_LEFT + choice_AROUND_RIGHT + choice_STOP + choice_PUSH == 0) {
              if (choice_AROUND_LEFT == 0) {
                  printf("\nAMARELO->Contornar a esquerda ?");
                  if (wait() == 1) {
                      choice_AROUND_LEFT++;
                      GO_AROUND_LEFT = YELLOW;
                      break;
                  }
              }
              
              if (choice_AROUND_RIGHT == 0) {
                  printf("\nAMARELO->Contornar a direita ?");
                  if (wait() == 1) {
                      choice_AROUND_RIGHT++;
                      GO_AROUND_RIGHT = YELLOW;
                      break;
                  }
              }    
              
              if (choice_STOP == 0) {
                  printf("\nAMARELO->Parar ?");
                  if (wait() == 1) {
                      choice_STOP++;
                      STOP = YELLOW;
                      break;
                  }
              }                       
              
              if (choice_PUSH == 0) {
                  printf("\nAMARELO->Empurrar bloco ?");
                  if (wait() == 1) {
                      choice_PUSH++;
                      PUSH_BLOCK = YELLOW;
                      showDistanceID = start_process (showDistance());
                      while (wait() != 1);
                      kill_process(showDistanceID);
                      dist = knob();    
                  }
              }
          }
          // Blue
          while (choice_AROUND_LEFT + choice_AROUND_RIGHT + choice_STOP + choice_PUSH == 1) {
              if (choice_AROUND_LEFT == 0) {
                  printf("\nAZUL->Contornar a esquerda ?");
                  if (wait() == 1) {
                      choice_AROUND_LEFT++;
                      GO_AROUND_LEFT = BLUE;
                      break;
                  }
              }
              
              if (choice_AROUND_RIGHT == 0) {
                  printf("\nAZUL->Contornar a direita ?");
                  if (wait() == 1) {
                      choice_AROUND_RIGHT++;
                      GO_AROUND_RIGHT = BLUE;
                      break;
                  }
              }    
              
              if (choice_STOP == 0) {
                  printf("\nAZUL->Parar ?");
                  if (wait() == 1) {
                      choice_STOP++;
                      STOP = BLUE;
                      break;
                  }
              }                       
              
              if (choice_PUSH == 0) {
                  printf("\nAZUL->Empurrar Bloco ?");
                  if (wait() == 1) {
                      choice_PUSH++;
                      PUSH_BLOCK = BLUE;
                      showDistanceID = start_process (showDistance());
                      while (wait() != 1);
                      kill_process(showDistanceID);
                      dist = knob();        
                  }
              }
          }
          // Red
          while (choice_AROUND_LEFT + choice_AROUND_RIGHT + choice_STOP + choice_PUSH == 2) {
              if (choice_AROUND_LEFT == 0) {
                  printf("\nVERMELHO->Contornar a esquerda ?");
                  if (wait() == 1) {
                      choice_AROUND_LEFT++;
                      GO_AROUND_LEFT = RED;
                      break;
                  }
              }
              
              if (choice_AROUND_RIGHT == 0) {
                  printf("\nVERMELHO->Contornar a direita ?");
                  if (wait() == 1) {
                      choice_AROUND_RIGHT++;
                      GO_AROUND_RIGHT = RED;
                      break;
                  }
              }    
              
              if (choice_STOP == 0) {
                  printf("\nVERMELHO->Parar ?");
                  if (wait() == 1) {
                      choice_STOP++;
                      STOP = RED;
                      break;
                  }
              }                       
              
              if (choice_PUSH == 0) {
                  printf("\nVERMELHO->Empurrar bloco ?");
                  if (wait() == 1) {
                      choice_PUSH++;
                      PUSH_BLOCK = RED;
                      showDistanceID = start_process (showDistance());
                      while (wait() != 1);
                      kill_process(showDistanceID);
                      dist = knob();        
                  }
              }
          }
          // Green
          while (choice_AROUND_LEFT + choice_AROUND_RIGHT + choice_STOP + choice_PUSH == 3) {
              if (choice_AROUND_LEFT == 0) {
                  printf("\nVERDE->Contornar a esquerda ?");
                  if (wait() == 1) {
                      choice_AROUND_LEFT++;
                      GO_AROUND_LEFT = GREEN;
                      break;
                  }
              }
              
              if (choice_AROUND_RIGHT == 0) {
                  printf("\nVERDE->Contornar a direita ?");
                  if (wait() == 1) {
                      choice_AROUND_RIGHT++;
                      GO_AROUND_RIGHT = GREEN;
                      break;
                  }
              }    
              
              if (choice_STOP == 0) {
                  printf("\nVERDE->Parar ?");
                  if (wait() == 1) {
                      choice_STOP++;
                      STOP = GREEN;
                      break;
                  }
              }                       
              
              if (choice_PUSH == 0) {
                  printf("\nVERDE->Empurrar bloco ?");
                  if (wait() == 1) {
                      choice_PUSH++;
                      PUSH_BLOCK = GREEN;
                      showDistanceID = start_process (showDistance());
                      while (wait() != 1);
                      kill_process(showDistanceID);
                      dist = knob();        
                  }
              }  
          }
          
          waitBlock();
          init = 1;    
      }
      
      if (init == 0) {
          printf ("\nSeguir luz polarizada ?");
          if (wait() == 1){
              
              printf ("\nAlinhar com luz vertical ?");
              if (wait() == 1) {
                  
                  alignPolarizedLight (LIGHT_VERTICALLY);
                  init = 1;
                  
              }
              
              if (init == 0) {
                  printf ("\nAlinhar com luz horizontal ?");    
                  if (wait() == 1) {
                      
                      alignPolarizedLight (LIGHT_HORIZONTALLY);
                      
                  }
              }
              
          }
          sleep(0.1);
      }        
  }
}
Trabalho Prático 3

  • Funções implementadas
Nesse terceiro TP, o robo realizou três novas funções:

1) Arremesso de uma bolinha em direção a uma fonte de luz polarizada, através de um sistema de catapulta ou lançamento.
2) Interrupção de todas as ações do robo em 60 segundos, contados a partir do acionamento da luz na parde de baixo do campo.
3) Movimentação através do campo com um mapa previamente conhecido, utilizando um algoritmo wavefront

* Construção do lançador de bolinha
Primeiramente foi projetado a construção de uma catapulta que seria inserida ao lado da estrutura do robô, sendo que uma haste ligada ao motor empurraria o braço da catapulta para baixo, tensionando um elástico preso a ela. Quando essa haste liberasse esse braço, o elástico puxaria a catapulta para frente lançando a bolinha. Porém a idéia não se mostrou eficaz, uma vez que no momento dos testes, a haste não coseguiu vencer a resistência da catapulta com o elástico e forçou o motor até soltá-lo da estrutura do robô.
Foi feito um segundo projeto, dessa vez implementamos um atirador em vez da catapulta. Esse atirador consistira em um motor que rodava uma engrenagem com um arco de 180º liso, sem os dentes. Quando a parte dentada estava para baixo, puxava o lançador para trás, esticando o elástico preso a ele. Quando a parte lisa ficava para baixo, o lançador escapava e com a força do elástico empurrava a bolinha para frente.
Com isso conseguimos construir um lançador de bolinhas que atirava na direção da luz polarizada com eficiência.

* Desligamento em 60 segundos

Para começar a tarefa, a luz inferior do campo seria ligada e o sensor LDR do robô apontado para baixo seria responsável por captar esse sinal para iniciar a contagem do tempo.
Foi utilizado uma rotina em paralelo as outras atividades do robô para garantir o desligamento no momento certo. Assim que a luz era ligada, uma thread era iniciada por 60 segundos e quando terminava, travava o robô independente do estado atual.

* Movimentação com wavefront

Nessa tarefa foi implementado o controle deliberativo que tinha como objetivo mapear o campo e levar o robô do ponto de partida até o alvo. O campo foi modularizado em quadrados de 30cm e o alvo e os obstáculos eram informados ao robô logo antes do teste. O algoritmo definia o ponto do alvo como valor zero e seus vizinhos como valor um. Os pontos adjacentes eram adicionados de uma unidade e assim sucessivamente até completar todo o campo. Os obstáculos e paredes eram definidos como valores bem alto. O algoritmo informava ao robô para se deslocar para o quadrado adjacente com o menor valor, assim ele se movimentaria em direção ao objetivo sem colidor com os obstáculos, ou com a borda do campo. Esse passo era repetido até chegar ao alvo seguindo o menor caminho. O controle P D, implementado anteriormente, foi incorporado ao algoritmo wavefront para otimizar o deslocamento do robô.

* Reconstrução do robô

Nosso robô apresentou alguns problemas, como a quebra da catapulta, desencaixe do motor com as engrenagens e a falta de espaço para as peças e os fios. Assim o grupo resolveu reconstruir nosso robô.
Nossa base foi criada para dar mais estabilidade para o resto dos equipamentos e ser mais firme

Além disso, as engrenagens, barras e os motores foram ligados de uma forma que evitasse o desprendimento dessas peças, o que comprometeria o desempenho em todos os teste e na competição

Para evitar o problema do excesso de fios soltos, implementamos uma canaleta que conduzia todos os fios até a handybord. Além disso a rampa que serve de base para o lançador de bolinhas foi construida para que se levantesse com facilidade para realizar os reparos necessários nos elementos da base

O lançador de bolinhas foi colocado em cima dessa rampa para efetuar um lançamento com uma boa distancia.

No final, nosso todas as outras partes já implementadas foram colocadas no robô para que ele ficasse completo para a competição. Todas as funções foram testadas e funcionaram dentro do esperado, corrigindo as falhas anteriores.