Mudanças entre as edições de "Grupo2-PJI2-2018-1"
(40 revisões intermediárias por 4 usuários não estão sendo mostradas) | |||
Linha 3: | Linha 3: | ||
---- | ---- | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
=Estrutura do EV3= | =Estrutura do EV3= | ||
− | + | Inicialmente, na primeira versão do robô, utilizamos um modelo adaptado do [https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-model-core-set-gyro-boy-f8a14d8e3d0e63fa23b87f798bf197f4.pdf Gyro Boy] LEGO® MINDSTORMS® Education EV3. Porém por questões de desempenho optamos por montar de uma forma diferente, este novo formato foi criado pela equipe.<br /> | |
As interfaces de entrada e saída utilizadas no controle do robô seguem a nomenclatura tabela: | As interfaces de entrada e saída utilizadas no controle do robô seguem a nomenclatura tabela: | ||
{| class="wikitable" | {| class="wikitable" | ||
Linha 158: | Linha 34: | ||
|} | |} | ||
− | [[Imagem: | + | [[Imagem:roboev3.jpeg|thumb|EV3 criado e montado pela Equipe|centro]] |
=Acesso via WiFI= | =Acesso via WiFI= | ||
Linha 221: | Linha 97: | ||
'''RNF04''' O tabuleiro deve ser formado por 100 blocos com dimensões de 0,2 metros por 0,2 metros. <br> | '''RNF04''' O tabuleiro deve ser formado por 100 blocos com dimensões de 0,2 metros por 0,2 metros. <br> | ||
'''RNF05''' O tabuleiro deve ter 6 cores (vermelho, azul, amarelo, verde, branco e marrom). <br> | '''RNF05''' O tabuleiro deve ter 6 cores (vermelho, azul, amarelo, verde, branco e marrom). <br> | ||
− | '''RNF06''' Ao redor do tabuleiro deve ter um contorno preto de 0, | + | '''RNF06''' Ao redor do tabuleiro deve ter um contorno preto de 0,05 metros. <br> |
'''RNF07''' Cada robô deve ter uma cor para identificação. <br> | '''RNF07''' Cada robô deve ter uma cor para identificação. <br> | ||
Linha 357: | Linha 233: | ||
'''Sumário:''' Juiz utiliza o Sistema de Auditoria para configurar os dados para a partida. <br> | '''Sumário:''' Juiz utiliza o Sistema de Auditoria para configurar os dados para a partida. <br> | ||
'''Ator Primário:''' Juiz.<br> | '''Ator Primário:''' Juiz.<br> | ||
+ | '''Ator Secundário:''' Sistema Supervisor. <br> | ||
'''Fluxo Principal:''' | '''Fluxo Principal:''' | ||
− | # O Juiz | + | # O Juiz seleciona o modo de operação, manual ou autônomo, e os robôs que participaram da partida; |
− | # O | + | # O Juiz inicia a partida; |
+ | # Dados são mandados para o Sistema Supervisor. | ||
+ | # O Juiz dá inicio a partida. | ||
==== Verificar Histórico (CSU-SA02) ==== | ==== Verificar Histórico (CSU-SA02) ==== | ||
Linha 367: | Linha 246: | ||
'''Ator Secundário:''' Sistema Supervisor. <br> | '''Ator Secundário:''' Sistema Supervisor. <br> | ||
'''Fluxo Principal:''' | '''Fluxo Principal:''' | ||
− | # O Juiz solicita ao Sistema de Auditoria | + | # O Juiz solicita ao Sistema de Auditoria consulta ao histórico das partidas. |
− | # O Juiz | + | # O Juiz visualiza a tabela de partidas jogadas com seus respectivos resultados. |
'''Fluxo Alternativo:''' | '''Fluxo Alternativo:''' | ||
# Se o sistema não possuir o registro de partidas anteriores, ou seja, se não tiver ocorrido partidas anteriormente, o mesmo informa ao Juiz a não ocorrência de partidas. | # Se o sistema não possuir o registro de partidas anteriores, ou seja, se não tiver ocorrido partidas anteriormente, o mesmo informa ao Juiz a não ocorrência de partidas. | ||
Linha 375: | Linha 254: | ||
==== Cadastrar Robôs (CSU-SA03) ==== | ==== Cadastrar Robôs (CSU-SA03) ==== | ||
− | '''Sumário:''' O Juiz realiza o cadastro dos | + | '''Sumário:''' O Juiz realiza o cadastro dos robôs para a partida. <br> |
'''Ator Primário:''' Juiz. <br> | '''Ator Primário:''' Juiz. <br> | ||
'''Ator Secundário:''' Sistema Supervisor. <br> | '''Ator Secundário:''' Sistema Supervisor. <br> | ||
'''Fluxo Principal:''' | '''Fluxo Principal:''' | ||
# Os robôs que participaram da partida, são cadastrados pelo Juiz através do Sistema de Auditoria. | # Os robôs que participaram da partida, são cadastrados pelo Juiz através do Sistema de Auditoria. | ||
− | + | # O cadastro consiste no nome do robô e seu IP. | |
− | # O cadastro consiste no nome do robô. | + | # Os cadastros são enviados para os Sistemas Supervisor. |
− | # Os cadastros são enviados para os Sistemas Supervisor | ||
'''Fluxo Alternativo:''' | '''Fluxo Alternativo:''' | ||
# Caso o robô já esteja cadastrado, o sistema informará ao Juiz. | # Caso o robô já esteja cadastrado, o sistema informará ao Juiz. | ||
Linha 393: | Linha 271: | ||
'''Ator Primário:''' Juiz. <br> | '''Ator Primário:''' Juiz. <br> | ||
'''Ator Secundário:''' Sistema Supervisor. <br> | '''Ator Secundário:''' Sistema Supervisor. <br> | ||
− | |||
'''Fluxo Principal:''' | '''Fluxo Principal:''' | ||
− | # | + | |
+ | # Ao iniciar a partida o Sistema gera randomicamente as posições dos alvos. | ||
# As posições dos alvos são enviadas para o Sistema Supervisor de cada jogador. | # As posições dos alvos são enviadas para o Sistema Supervisor de cada jogador. | ||
− | |||
# O Sistema de Auditoria apresenta ao Juiz o tabuleiro com os alvos posicionados e a contagem do tempo de início da partida. | # O Sistema de Auditoria apresenta ao Juiz o tabuleiro com os alvos posicionados e a contagem do tempo de início da partida. | ||
+ | |||
'''Regras de Negócio:''' RN01, RN05. | '''Regras de Negócio:''' RN01, RN05. | ||
Linha 410: | Linha 288: | ||
'''Regras de Negócio:''' RN01. | '''Regras de Negócio:''' RN01. | ||
− | ==== Validar Alvo (CSU-SA06) ==== | + | ==== Validar Alvo Modo Autônomo (CSU-SA06) ==== |
'''Sumário:''' A Câmera valida o encontro do alvo usando o Sistema de Auditoria. <br> | '''Sumário:''' A Câmera valida o encontro do alvo usando o Sistema de Auditoria. <br> | ||
'''Ator Primário:''' Câmera. <br> | '''Ator Primário:''' Câmera. <br> | ||
− | |||
'''Fluxo Principal:''' | '''Fluxo Principal:''' | ||
# A Câmera visualiza o tabuleiro e os jogadores. | # A Câmera visualiza o tabuleiro e os jogadores. | ||
# Ao ocorrer o encontro do jogador com o alvo a Câmera envia uma mensagem ao Sistema de Auditoria validando o encontro do alvo. | # Ao ocorrer o encontro do jogador com o alvo a Câmera envia uma mensagem ao Sistema de Auditoria validando o encontro do alvo. | ||
+ | |||
+ | ==== Validar Alvo Modo Manual (CSU-SA07) ==== | ||
+ | '''Sumário:''' A Câmera valida o encontro do alvo usando o Sistema de Auditoria. <br> | ||
+ | '''Ator Primário:''' Juiz. <br> | ||
+ | '''Fluxo Principal:''' | ||
+ | # O Juiz visualiza o tabuleiro e os jogadores. | ||
+ | # Ao ocorrer o encontro do jogador com o alvo o Juiz envia uma mensagem ao Sistema de Auditoria validando o encontro do alvo. | ||
[[Arquivo:UseCase Diagram0.png|850px]] | [[Arquivo:UseCase Diagram0.png|850px]] | ||
Linha 448: | Linha 332: | ||
{{collapse bottom}} | {{collapse bottom}} | ||
− | = | + | =Etapa 1= |
+ | |||
+ | Nesta etapa foram feitos os diagramas e implementações do modo manual sem o Sistema de Auditoria. | ||
+ | |||
==Diagrama de Classe== | ==Diagrama de Classe== | ||
− | [[Arquivo:Class DiagramModoManual.png| | + | [[Arquivo:Class DiagramModoManual.png|600px|center]] |
==Diagrama de Sequência== | ==Diagrama de Sequência== | ||
− | [[Arquivo: | + | |
+ | ==Códigos== | ||
+ | |||
+ | Nesta seção apresentamos os códigos implementados na Etapa 1 do projeto. O primeiro código é o encapsulamento dos códigos dos motores para os movimentos do robô. O segundo código é a Web Service do robô que recebe da página Web os comandos para movimentar o robô. Os códigos da página Web estão no arquivo comprimido no final desta seção. | ||
+ | |||
+ | Código '''manual.py''': | ||
+ | <code> | ||
+ | from ev3dev.ev3 import * | ||
+ | from time import sleep | ||
+ | |||
+ | class manual(object): | ||
+ | |||
+ | def __init__(self, direcao, passos): | ||
+ | self.dire = direcao | ||
+ | self.steps = passos | ||
+ | self.gy= GyroSensor() | ||
+ | self.ts = TouchSensor() | ||
+ | self.mA = LargeMotor('outA') | ||
+ | self.mD = LargeMotor('outD') | ||
+ | assert self.gy.connected | ||
+ | self.gy.mode = 'GYRO-ANG' | ||
+ | self.units = self.gy.units | ||
+ | |||
+ | def movimento(self): | ||
+ | if self.dire == 2: | ||
+ | self.oeste() | ||
+ | self.andar() | ||
+ | self.alinhar() | ||
+ | elif self.dire == 6: | ||
+ | self.mA.run_timed(time_sp = 200, speed_sp = 100) | ||
+ | elif self.dire == 7: | ||
+ | self.mD.run_timed(time_sp = 200, speed_sp = 100) | ||
+ | elif self.dire == 3: | ||
+ | self.leste() | ||
+ | self.andar() | ||
+ | self.alinhar() | ||
+ | elif self.dire == 1: | ||
+ | self.andar() | ||
+ | self.alinhar() | ||
+ | else: | ||
+ | self.sul() | ||
+ | |||
+ | def oeste(self): | ||
+ | while not self.ts.value(): | ||
+ | angle = self.gy.value() | ||
+ | print(str(angle) + " " + self.units) | ||
+ | self.mA.run_timed(time_sp = 300, speed_sp = 100) | ||
+ | if angle >= 90: | ||
+ | self.mA.stop(stop_action = "brake") | ||
+ | break | ||
+ | |||
+ | def leste(self): | ||
+ | while not self.ts.value(): | ||
+ | angle = self.gy.value() | ||
+ | print(str(angle) + " " + self.units) | ||
+ | self.mA.run_timed(time_sp = 300, speed_sp = -120) | ||
+ | if angle <= -90: | ||
+ | self.mA.stop(stop_action = "brake") | ||
+ | break | ||
+ | |||
+ | def sul(self): | ||
+ | for x in range(0, self.steps): | ||
+ | print ("1 passo") | ||
+ | self.mA.run_timed(time_sp = 1000, speed_sp = -400) | ||
+ | self.mD.run_timed(time_sp = 1000, speed_sp = -400) | ||
+ | sleep(1) | ||
+ | |||
+ | def andar(self): | ||
+ | for x in range(0, self.steps): | ||
+ | print ("1 passo") | ||
+ | self.mA.run_timed(time_sp = 1000, speed_sp = 400) | ||
+ | self.mD.run_timed(time_sp = 1000, speed_sp = 400) | ||
+ | sleep(1) | ||
+ | |||
+ | def alinhar(self): | ||
+ | print("alinhando") | ||
+ | if self.dire == 2: | ||
+ | while not self.ts.value(): | ||
+ | angle = self.gy.value() | ||
+ | print(str(angle) + " " + self.units) | ||
+ | self.mD.run_timed(time_sp = 500, speed_sp = 120) | ||
+ | if angle <= 1: | ||
+ | self.mD.stop(stop_action = "brake") | ||
+ | break | ||
+ | elif self.dire == 3: | ||
+ | while not self.ts.value(): | ||
+ | angle = self.gy.value() | ||
+ | print(str(angle) + " " + self.units) | ||
+ | self.mA.run_timed(time_sp = 500, speed_sp = 120) | ||
+ | if angle >= -1: | ||
+ | self.mA.stop(stop_action = "brake") | ||
+ | break | ||
+ | else: | ||
+ | pass | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Código '''webservice.py''': | ||
+ | <code> | ||
+ | #!/usr/bin/pythonfrom | ||
+ | from flask import Flask, jsonify | ||
+ | from flask import abort | ||
+ | from flask import make_response | ||
+ | from flask_cors import CORS, cross_origin | ||
+ | from flask import request | ||
+ | from flask import url_for | ||
+ | from flask.ext.httpauth import HTTPBasicAuth | ||
+ | from manual import * | ||
+ | |||
+ | auth = HTTPBasicAuth() | ||
+ | |||
+ | app = Flask(__name__) | ||
+ | CORS(app) | ||
+ | |||
+ | oper = [ | ||
+ | { | ||
+ | 'id': 1, | ||
+ | 'dir' : 0, | ||
+ | 'steps' : 0, | ||
+ | }, | ||
+ | ] | ||
+ | |||
+ | @app.route('/oper', methods=['GET']) | ||
+ | def obtem_oper(): | ||
+ | return jsonify({'oper': oper}) | ||
+ | |||
+ | @app.route('/atualiza', methods=['PUT']) | ||
+ | def atualizar_valores(): | ||
+ | resultado = [resultado for resultado in oper if resultado['id'] == 1] | ||
+ | resultado[0]['dir'] = request.json.get('dir', resultado[0]['dir']) | ||
+ | resultado[0]['steps'] = request.json.get('steps', resultado[0]['steps']) | ||
+ | dire = request.json.get('dir', resultado[0]['dir']) | ||
+ | steps = request.json.get('steps', resultado[0]['steps']) | ||
+ | |||
+ | mov = manual(dire,steps) | ||
+ | mov.movimento() | ||
+ | |||
+ | print('atualizou') | ||
+ | return jsonify({'ok': '1'}), 201 | ||
+ | |||
+ | if __name__ == "__main__": | ||
+ | print('Servidor no ar!') | ||
+ | app.run(host='0.0.0.0', debug=True) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Códigos da página Web: | ||
+ | [[Arquivo:InterfaceWEB_SS.zip]] | ||
+ | |||
+ | =Etapa 2= | ||
+ | |||
+ | Nesta seção apresentamos os diagrama de sequência dos casos de uso do modo manual com a integração do Sistema de Auditoria. | ||
+ | |||
+ | ==Diagramas de Classe== | ||
+ | |||
+ | [[Arquivo:CS_Servidor.png|600px]] | ||
+ | |||
+ | ==Diagramas de Sequência== | ||
+ | [[Arquivo:Configurar Partida (CSU-SA01).png|850px]] | ||
+ | |||
+ | [[Arquivo:Cadastrar Robôs (CSU-SA03).png|850px]] | ||
+ | |||
+ | [[Arquivo:Iniciar Partida (CSU-SA04).png|850px]] | ||
+ | |||
+ | [[Arquivo:verificar.jpeg|850px]] | ||
+ | |||
+ | [[Arquivo:pausar.jpeg|850px]] | ||
=Links Auxiliares= | =Links Auxiliares= | ||
+ | |||
+ | Pseudocódigo: | ||
+ | http://thetechnicgear.com/2014/03/howto-create-line-following-robot-using-mindstorms/ | ||
+ | |||
+ | Demonstração de Funcionamento do sensor e do tabuleiro colorido: | ||
+ | https://www.youtube.com/watch?v=fnwWcGqY3VA | ||
+ | |||
+ | =Arquivos teste= | ||
+ | |||
+ | [[Arquivo:Ev3-master.zip]] |
Edição atual tal como às 12h47min de 16 de junho de 2018
Equipe
Luísa Machado
Marina Souza
Natália Miranda
Estrutura do EV3
Inicialmente, na primeira versão do robô, utilizamos um modelo adaptado do Gyro Boy LEGO® MINDSTORMS® Education EV3. Porém por questões de desempenho optamos por montar de uma forma diferente, este novo formato foi criado pela equipe.
As interfaces de entrada e saída utilizadas no controle do robô seguem a nomenclatura tabela:
Interfaces | |||
---|---|---|---|
Input | Output | ||
1 | Sensor de Toque | A | Motor Direita |
2 | Sensor Ultrassônico | B | |
3 | Sensor de Giro | C | |
4 | Sensor de Cor | D | Motor Esquerda |
Acesso via WiFI
Para acessar o robô via rede Wi-Fi utilizamos um dispositivo Wi-Fi (TP-Link N500) conectado à porta USB do EV3 e acessamos as configurações de rede na tela do EV3 para obter o endereço IP.
A partir de um computador conectado na mesma rede local que o robô, configuramos o software Moba para gerar uma interface gráfica de programação e permitir o envio de arquivos via SSH ao software do EV3.
O tutorial completo pode acessado neste link.
Execução de programas na linguagem Python
O primeiro código em Python enviado ao EV3 foi um teste no sensor de toque. O objetivo do programa é acionar o led verde do EV3 quando o sensor de toque for pressionado.
Teste do Sensor de Toque |
---|
Teste de sensores e motor
Teste dos Motores |
---|
Teste do Sensor de Cor |
---|
Teste do Sensor de Giro |
---|
Teste do Sensor de Ultrassônico |
---|
Estudo do artigo do Borenstein e pesquisas sobre métodos de localização
Review Técnicas de Indoor Positioning
Implementação e Teste de Soluções de Navegação de Robôs Móveis com Base no Sistema NXT/EV3 da LEGO®
Mobile Robot Positioning & Sensors and Techniques
Sumário Executivo
Levantamento de Requisitos
Requisitos Funcionais |
---|
RF01 O robô entra em funcionamento a partir de instruções originadas no sistema de auditoria. |
Requisitos Não Funcionais |
---|
RNF01 O sistema de auditoria deve ser compartilhado entre os robôs. |
Restrições |
---|
As limitações encontradas pela equipe para o desenvolvimento do projeto envolvem:
|
Casos de uso
Atores |
---|
Casos de Uso do Sistema de Auditoria:
Casos de Uso do Sistema Supervisor:
Casos de Uso do Sistema do Robô:
|
Diagramas de Casos de Uso | ||||||
---|---|---|---|---|---|---|
|
Regras de Negócio | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Etapa 1
Nesta etapa foram feitos os diagramas e implementações do modo manual sem o Sistema de Auditoria.
Diagrama de Classe
Diagrama de Sequência
Códigos
Nesta seção apresentamos os códigos implementados na Etapa 1 do projeto. O primeiro código é o encapsulamento dos códigos dos motores para os movimentos do robô. O segundo código é a Web Service do robô que recebe da página Web os comandos para movimentar o robô. Os códigos da página Web estão no arquivo comprimido no final desta seção.
Código manual.py:
from ev3dev.ev3 import *
from time import sleep
class manual(object):
def __init__(self, direcao, passos):
self.dire = direcao
self.steps = passos
self.gy= GyroSensor()
self.ts = TouchSensor()
self.mA = LargeMotor('outA')
self.mD = LargeMotor('outD')
assert self.gy.connected
self.gy.mode = 'GYRO-ANG'
self.units = self.gy.units
def movimento(self):
if self.dire == 2:
self.oeste()
self.andar()
self.alinhar()
elif self.dire == 6:
self.mA.run_timed(time_sp = 200, speed_sp = 100)
elif self.dire == 7:
self.mD.run_timed(time_sp = 200, speed_sp = 100)
elif self.dire == 3:
self.leste()
self.andar()
self.alinhar()
elif self.dire == 1:
self.andar()
self.alinhar()
else:
self.sul()
def oeste(self):
while not self.ts.value():
angle = self.gy.value()
print(str(angle) + " " + self.units)
self.mA.run_timed(time_sp = 300, speed_sp = 100)
if angle >= 90:
self.mA.stop(stop_action = "brake")
break
def leste(self):
while not self.ts.value():
angle = self.gy.value()
print(str(angle) + " " + self.units)
self.mA.run_timed(time_sp = 300, speed_sp = -120)
if angle <= -90:
self.mA.stop(stop_action = "brake")
break
def sul(self):
for x in range(0, self.steps):
print ("1 passo")
self.mA.run_timed(time_sp = 1000, speed_sp = -400)
self.mD.run_timed(time_sp = 1000, speed_sp = -400)
sleep(1)
def andar(self):
for x in range(0, self.steps):
print ("1 passo")
self.mA.run_timed(time_sp = 1000, speed_sp = 400)
self.mD.run_timed(time_sp = 1000, speed_sp = 400)
sleep(1)
def alinhar(self):
print("alinhando")
if self.dire == 2:
while not self.ts.value():
angle = self.gy.value()
print(str(angle) + " " + self.units)
self.mD.run_timed(time_sp = 500, speed_sp = 120)
if angle <= 1:
self.mD.stop(stop_action = "brake")
break
elif self.dire == 3:
while not self.ts.value():
angle = self.gy.value()
print(str(angle) + " " + self.units)
self.mA.run_timed(time_sp = 500, speed_sp = 120)
if angle >= -1:
self.mA.stop(stop_action = "brake")
break
else:
pass
</syntaxhighlight>
Código webservice.py:
- !/usr/bin/pythonfrom
from flask import Flask, jsonify
from flask import abort
from flask import make_response
from flask_cors import CORS, cross_origin
from flask import request
from flask import url_for
from flask.ext.httpauth import HTTPBasicAuth
from manual import *
auth = HTTPBasicAuth()
app = Flask(__name__)
CORS(app)
oper = [
{
'id': 1,
'dir' : 0,
'steps' : 0,
},
]
@app.route('/oper', methods=['GET'])
def obtem_oper():
return jsonify({'oper': oper})
@app.route('/atualiza', methods=['PUT'])
def atualizar_valores():
resultado = [resultado for resultado in oper if resultado['id'] == 1]
resultado[0]['dir'] = request.json.get('dir', resultado[0]['dir'])
resultado[0]['steps'] = request.json.get('steps', resultado[0]['steps'])
dire = request.json.get('dir', resultado[0]['dir'])
steps = request.json.get('steps', resultado[0]['steps'])
mov = manual(dire,steps)
mov.movimento()
print('atualizou')
return jsonify({'ok': '1'}), 201
if __name__ == "__main__":
print('Servidor no ar!')
app.run(host='0.0.0.0', debug=True)
</syntaxhighlight>
Códigos da página Web:
Arquivo:InterfaceWEB SS.zip
Etapa 2
Nesta seção apresentamos os diagrama de sequência dos casos de uso do modo manual com a integração do Sistema de Auditoria.
Diagramas de Classe
Diagramas de Sequência
Links Auxiliares
Pseudocódigo:
http://thetechnicgear.com/2014/03/howto-create-line-following-robot-using-mindstorms/
Demonstração de Funcionamento do sensor e do tabuleiro colorido:
https://www.youtube.com/watch?v=fnwWcGqY3VA
Arquivos teste