Dia bom!Hoje eu gostaria de compartilhar uma implementação do algoritmo para determinar a largura de um objeto usando um rangefinder ultrassônico e codificadores na linguagem de programação RobotC (usando a plataforma VEX EDR).Pré-história
Recentemente, me ofereceram a realização de uma master class sobre solução de problemas interessantes usando a linguagem de programação RobotC. Durante a master class, considerei a tarefa de determinar a largura de um objeto, cuja implementação do algoritmo desejo compartilhar nesta publicação.Base elementar
Como campo de treinamento experimental, usei o ambiente Robot Virtual Worlds para a plataforma VEX, o modelo de robô virtual VEX Launcher, modelos virtuais de elementos de competição VRC Turning Point (Figura 1) e as fórmulas matemáticas mais simples (para determinar o comprimento de um acorde em um círculo com um ângulo central conhecido).
Figura 1 . Campo de treinamento virtual com um robôTarefa
- Determinar o diâmetro da bola usando apenas um telêmetro ultrassônico e codificadores montados no robôBase teórica
Para determinar a largura do objeto, usei o conceito de padrão de radiação (Figura 2).
Figura 2. Sensibilidade e padrão direcional do telêmetro ultrassônicoEm essência, foi necessário determinar o ângulo formado ao girar da posição extrema direita para a extrema esquerda entre as tangentes nos pontos extremos do diagrama.Considere a Figura 3.
Figura 3 . Geometria do algoritmoProcuraremos o ângulo central do arco com base na relação entre o raio do ângulo e o arco de rotação do robô. O valor final da largura corresponderá ao acorde m do arco.Parâmetros de entrada
Como parâmetros de entrada, selecionei:- dist = 100 mm (a distância na qual o robô para para medir, o parâmetro é selecionado com base na presença de outros objetos ao redor do objeto que podem cair no campo de visão do sensor e interferir na medição)
- d_wheel = 102 mm (diâmetro da roda do robô)
- d_ball = 102 mm (diâmetro real da bola)
Um erro foi determinado como o parâmetro de saída desta tarefa, que indicará a precisão do nosso método e os parâmetros selecionados:- erro = abs (d_ball_exper - d_ball)
Algoritmo de Operação do Programa
Os seguintes estágios do algoritmo foram identificados.- Movimento para o objeto.
- Gire para o ponto mais à direita de um objeto.
- Gire para o ponto mais à esquerda do objeto.
- Cálculo do ângulo usando leituras extraídas de codificadores.
- Cálculo de erro.
Implementação do algoritmo RobotC
Primeiro de tudo, precisamos inicializar a configuração padrão do robô virtual:#pragma config(StandardModel, "VEX Launchbot")
Implementamos uma função que será responsável por girar o robô para a extrema direita e / ou extrema esquerda. A função retorna o codificador após uma volta, que será usada em outros cálculos:int turn_to_over_object(int leftSpeed, int rightSpeed, int distance, bool need_object, bool left_side)
{
if(need_object == true)
{
if(left_side == true)
{
while(SensorValue[sonarSensor] > distance)
{
setMultipleMotors(-leftSpeed, leftMotor,frontLeftMotor);
setMultipleMotors(rightSpeed, rightMotor,frontRightMotor);
}
}
else
{
while(SensorValue[sonarSensor] > distance)
{
setMultipleMotors(leftSpeed, leftMotor,frontLeftMotor);
setMultipleMotors(-rightSpeed, rightMotor,frontRightMotor);
}
}
}
else
{
if(left_side == true)
{
while(SensorValue[sonarSensor] < (distance + 1))
{
setMultipleMotors(-leftSpeed, leftMotor,frontLeftMotor);
setMultipleMotors(rightSpeed, rightMotor,frontRightMotor);
}
}
else
{
while(SensorValue[sonarSensor] < (distance + 1))
{
setMultipleMotors(leftSpeed, leftMotor,frontLeftMotor);
setMultipleMotors(-rightSpeed, rightMotor,frontRightMotor);
}
}
}
return getMotorEncoder(leftMotor);
}
Vamos dar uma olhada nos argumentos da função:- leftSpeed - velocidade da unidade esquerda
- rightSpeed - velocidade certa
- rightSpeed - velocidade certa
- distance - distância do objeto em que o robô parou
- need_object - mode mode: True, se um objeto for necessário no campo de visão do sensor, False, se um objeto for necessário
- left_side - direção de rotação do robô. Verdadeiro - vire à esquerda, Falso - vire à direita
Com o valor need_object = True, o robô girará até que o objeto esteja a uma distância do robô (no nosso caso, 100 mm).Com o valor need_object = False, o robô girará até que o objeto esteja a uma distância (distância + 1) do robô. O parâmetro unitário no total afeta a precisão final de determinar a ausência de um objeto no campo de visão do sensor (é possível melhorar o programa levando esse parâmetro a argumentos de função).Vamos escrever o corpo principal do programa:task main()
{
int d_ball = 10.2; //sm
int d_wheel = 10.2;
int dist = 10; //sm
//
setMotor(armMotor, -50);
wait(1);
while(SensorValue[sonarSensor] > 10)
{
setMultipleMotors(50, leftMotor, rightMotor, frontLeftMotor, frontRightMotor);
}
stopAllMotors();
int enc = 0;
enc = turn_to_over_object(50, 50, dist, false, false);
enc = turn_to_over_object(50, 50, dist, true, true);
resetMotorEncoder(leftMotor);
enc = turn_to_over_object(50, 50, dist, false, true);
stopAllMotors();
float teta = abs(enc) * PI * d_wheel * d_wheel / (dist * 627);
float d_ball_exper = 2 * dist * sin(teta / 2);
float error = abs(d_ball_exper - d_ball);
while(1)
{
}
}
O primeiro loop while é executado até o robô atingir a distância especificada para o objeto. Em seguida, precisamos chamar a função escrita acima uma a uma para medir a leitura do codificador entre as posições mais à direita e mais à esquerda (observe que antes de medir é necessário redefinir o codificador para zero).Para obter a fórmula do ângulo, fui guiado pelas seguintes fórmulas:- enc = N * 627, onde N é o número de rotações da roda, enc é a leitura do encoder, 627 é a resolução do encoder => express N;- S = N * l, onde l é o comprimento da roda, l = PI * d_wheel * d_wheel => substituímos N e l => S = enc * PI * d_wheel * d_wheel / 627;- por outro lado, S = dist * teta, onde S é a magnitude do arco que o robô girou, teta é o ângulo central desejado;- com base nos dados acima, expressamos teta => teta = enc * PI * d_wheel * d_wheel / (627 * dist)Para encontrar o acorde igual ao diâmetro desejado da bola, usamos a fórmula: d_ball_exper = 2 * dist * sin (teta / 2)O loop while sem fim no final do programa é necessário para ver os valores recebidos no depurador.Dados resumidos
Os seguintes valores do diâmetro e erros da bola foram obtidos no campo virtual: d_ball_exper = 10,6 cm erro = 0,4 cmComo você pode ver, o método obtido para medir a largura fornece um pequeno valor de erro, aceitável para a classe de precisão dos sensores utilizados. O valor do erro pode ser reduzido selecionando o valor do parâmetro dist (por exemplo, iniciando um ciclo com o robô retornando com uma determinada etapa que muda para dist) ou usando o controlador PID, que reduzirá a influência da inércia do robô no valor final do codificador durante a frenagem.Perspectivas
No futuro, considerarei outros métodos de uso de sensores de robô para determinar parâmetros ambientais.