Sendo este o primeiro trabalho, seu objetivo principal foi apresentar aos alunos as ferramentas básicas. As atividades propostas incluem montar um robô baseado na “handybug” (montagem especificada no livro Robotics Exploration, de Fred Martin) acrescentando uma caneta para permitir que o robô desenhe algumas trajetórias. As únicas formas exigidas foram linhas retas, círculos e quadrados. A avaliação consiste em programar o robô para desenhar uma seqüência de três quadrados e outra de três círculos.
Logo no início do desenvolvimento, buscamos estabelecer conceito básicos que guiariam o projeto. Os principais foram:
Estas características visam facilitar o cálculo da trajetória da caneta em relação ao resto do robô, e acrescentar robustez ao comando da trajetória respectivamente. Conforme veremos nas próximas seções, a segunda proposta foi implementada com sucesso. Já a primeira não pode ser completamente adotada porque o eixo de tração localiza-se na região central do robô, e devido ao volume vertical da caneta, esta teve de ser coloca na extremidade traseira do robô (mas ainda em posição simétrica em relação às rodas). Outra característica desejável, mas de menor importância, é a capacidade de o robô abaixar e levantar a caneta. Na próxima seção veremos que esta funcinalidade também foi implementada adequadamente.
Conforme sugerido na proposta do trabalho, nossa montagem foi baseada na handybug, cujas etapas de montagm estão descritas no livro “Robotics Explorations”, página 29. As principais mudanças que executamos foram:
A handyboard foi fixada na placa de lego superior apenas encaixando-a no espaço entre as vigas de suporte e com uma gominha prendendo-a pela parte da frente do robô. As figuras a seguir mostram o robô completamente montado.
Visto que o objetivo do robô é desenhar quadrados e circulos, planejamos desenvolver duas funções, uma para desenhar arcos e a outra para desenhar retas. Para facilitar a e generalizar o uso destes códigos, ambos recebem parâmetros que caracterizam a figura a desenhar (comprimento para o caso da reta, ângulo e raio para o arco).
Antes de criar estas duas funções, foi necessário implementar a leitura da velocidade a partir dos sensores óticos. O funcionamento adequado deste tipo de rotina depende de sua execução continua, portanto ela é chamada em um processo separado para cada roda, ambos concorrentes entre si e à função principal. A cada meio segundo o valor da velocidade é armazenado em uma variável global. Destaca-se que, como há apenas uma função escrevendo em cada variável compartilhada, não há condições de disputa que exijam controle de acesso.
A partir disto, tanto a função de desenhar retas quanto a de arcos dependem do sistema de leitura de velocidade. Nas duas rotinas, é necessário determinar a distância já percorrida pelo robô, além de manter a velocidade constante, daí a importância das leituras de shaft-encoding.
Também seria interessante desenvolver uma função para abaixar e levantar a caneta. No entanto, como há um motor dedicado para este movimento, esta tarefa pode ser executada com três linhas de código (aciona o motor, espera, pára o motor), assim o tempo gasto para processr a tarefa é curto em relação ao overhead associado à chamada de uma função. Portanto preferimos acrescentar trechos de código para realizar esta atividade quando necessário.
Todos os códigos desenvolvidos se encontram na versão pdf do relatório. Para maior comodidade, também adicionamos a esta página um arquivo contendo apenas os códigos das funções e comentários explicativos.
No enunciado do trabalho solicita-se que sejam apresentados os gráficos levantados durante a calibração do robô. Porém, devido ao uso de um sistema em malha fechada, esta montagem não se utilizou de calibração ou mesmo levantamento de características do motor. Portanto esta seção cobre apenas os desenhos feitos durante os testes e discussões a respeito. Para avaliar todas as funcionalidades básicas do robô, programamos na função “main” o seguinte algoritmo:
Desenhar retas e e círculos são aplicações diretas das funções citadas na seção 4. Já para desenhar o quadrado seria usamos chamadas à função “reta” intercaladas com comandos para executar rotações de noventa graus. A princípio usaríamos a função “arco” para realizar esta tarefa (precedida de um recuo linear e um avanço, para posicionar a caneta no ponto certo), porém descobrimos que a função “arco” possui um bug, de modo que o ângulo desenhado é muito maior do que o especificado. Além disso aparentemente não havia uma relação linear entre o ângulo de entrada e o de saída, de modo que não poderíamos contornar o problema usando um “fator de escala”. Após várias tentativas infrutíferas de identificar a fonte do erro, decidimos alterar o algoritmo de desenhar retângulos, de modo que o giro seria feito acionando cada motor em uma direção e aguardando um determinado tempo.
Vamos avaliar os resultados de cada desenho separadamente:
O vídeo 1 da seção de anexos mostra o robô executando esta primeira parte do algoritmo:
Para verificar o desvio entre execuções consecutivas, fizemos com que o robô desenhasse duas linhas paralelas. O resultado deste experimento está na imagem abaixo.
Nota-se que há uma tendência de desvio para a esquerda, mas as duas retas são bastante semelhantes. Este é um indício de boa repetibilidade, porém seriam necessários mais testes para verificar esta característica.
O segundo vídeo da seção de anexos mostra o procedimento adotado para gerar a figura anterior.
Conforme explicado no início desta seção, foram feitas mudanças em relação ao algoritmo original para esta parte. A função alterada e a original estão disponíveis na versão PDF do relatório, e também estão anexadas separadamente a esta página.
O terceiro vídeo da seção de anexos a execução da função “retângulo”, cujo o resultado está ilustrado a seguir
Como a imagem não se assemelha ao desenho esperado, numeramos as retas correspondentes a cada lado na ordem em que foram desenhados, e acrescentamos setas para indicar o sentido em que foram traçadas.
Observando a figura, nota-se que os lados 1 e 2 estão perpendiculares entre si, assim como os lados 3 e 4, porém houve um problema em posicionar a caneta após as rotações. Nota-se que o começo de cada lado está mais próximo do ponto inicial do anterior, o que indica um erro na distância de recuo. Além disso, o tempo de giro está inadequado na transição do entre os lados 2 e 3. Curiosamente, as demais rotações foram bastante próximas a uma volta de noventa graus, sendo que todas usaram a mesma temporização.
Apesar do desempenho bem abaixo das espectativas nesta tarefa, este era esperado, devido à detecção tardia do problema com a função “arco”. De fato, esperávamos não ter de usar controle em malha aberta, então investimos todo o tempo tentando mudar ou consertar a função arco, e quando decidimos mudar a função retângulo, não tivemos tempo de calibrá-la adequadamente.
Nota-se que a ligação entre duas retas adjacentes depende de três parâmetros:
Por exemplo, nas trasições de 1 para 2 e 2 para 3, a caneta foi baixada muito cedo, e na transição de 3 para 4 ela demorou a tocar o papel. Neste aspecto, uma deficiência da implementação atual é acionar o motor da caneta com o robô em movimento. Obviamente isso implica em diversas complicações, principalmente devido a incertezas. Uma solução simples seria parar o robô antes de mover a caneta, mas devido à iminência da data de apresentação este problema nos passou despercebido.
Por fim, nota-se que houve uma atenuação do desvio observado no desenho das retas em relação ao teste da sub-seção anterior. Como naquele teste as retas possuíam três vezes o comprimento dos lados deste quadrado, seria interessante avaliar se este erro seria detectado caso o robô tivesse que desenhar quadrados maiores.
A seguinte figura mostra o resultado da função de desenhar círculos.
Apesar de a imagem estar fora de foco, percebe-se que há uma translação entre os centros, porém cada círculo é bastante uniforme.
Conforme citado anteriormente, houve um problema com a função círculo, que fazia o arco de saída apresentar um ângulo muito superior ao de entrada. e não conseguimos identificar sua origem, tampouco detectadar uma relação linear entre o ângulo de entrada e o ângulo de saída.
O quarto vídeo da seção de anexos mostra a execução deste teste
O principal destaque deste trabalho foi o uso de um controle de velocidade com realimentação. Esta característica permitiu que nosso robô apresentasse resultados satisfatórios mesmo com quase nenhuma calibração e relativamente pouco tempo de desenvolvimento.
As maiores dificuldades foram na parte de software, porém isso já era esperado, visto que esta etapa foi deixada para o final e o grupo teve problemas em gerenciar o tempo disponível.
A realização correta das atividades propostas para apresentação dependia fortemente da função de desenhar arcos, de modo que gastamos muito tempo para projetá-la e posteriormente para tentar corrigi-la. Outra deficiência foi a falta de dados sobre as características dos motores. O sistema realmente se apresentou bastante robusto em relação a variações de parâmetros, porém quando foi necessário usar um pequeno trecho do sistema em malha aberta os resultados foram desastrosos, conforme mostrado no teste da função de desenhar o quadrado.
Além disso, mais conhecimento sobre as características do sistema poderia explicar outros comportamentos observados, como a tendência que o robô apresentava de virar à esquerda quando desenhava retas ou o fato de a transição ente os lados do quadrado apresentar resultados distintos em cada vértice, mesmo usando a mesma função e temporização para todos.
As principais lições que tivemos neste trabalho foram:
Ao longo de todo o texto destacamos pontos do robô que poderiam ser alterados. Aqui acrescentamos mais algumas idéias de mudanças que consideramos importantes para os próximos trabalhos:
Além dos membros do grupo, algumas outras pessoas e entidades merecem nosso reconhecimento por colaborações prestadas a este trabalho: