
Quando você começa a aprender ROS, geralmente deseja trabalhar com plataformas físicas, e não com modelos em um simulador. Na verdade, o Gazebo é suficiente para estudar apenas algoritmos de movimento ou apenas ensinar o próprio ROS, mas trabalhar com uma plataforma real imediatamente permite entender na prática todos os problemas com o movimento das rodas. Bem, e muitas vezes a plataforma é necessária simplesmente como um pré-requisito para o projeto.
Para o futuro, é melhor começar com uma rodada, porque por razões óbvias, tal configuração pode girar em torno do eixo sem levar em consideração o tamanho da parte saliente. O retângulo de retorno é muito menos conveniente, por exemplo, em corredores estreitos - às vezes torna-se necessário desdobrar 3 ou mais manobras, acho que os motoristas vão entender.
Compra de plataformas prontas
Não existem muitas plataformas prontas no mercado, uma lista delas é fornecida no site da ROS .
Ao mesmo tempo, seu custo na Rússia é alto o suficiente para começar a funcionar; a opção mais barata é o Turtlebot Burger 3 - $ 549. Encontramos revendedores diretamente na Rússia por cerca de 90.000 rublos.

Na China, você pode comprar por 45-50 tr ... Em qualquer caso, serão plataformas de pequeno tamanho e capacidade de carga, incapazes de realizar tarefas reais.
Você mesmo pode construir a plataforma, há muitos guias e configurações diferentes. Mas, em média, acontece algo como:
- Slamtech A1-A2 classe lidar
- Rodas baratas baseadas em motores coletores com caixas de câmbio
- , PWM , UART + rosserial.
- Single Board Computer — Raspberry, Jetson Nano
- 2
- gmapping + amcl/rosbot_ekf + move_base

Não gostamos dos motores coletores porque são barulhentos, têm alto consumo e é necessária uma caixa de câmbio. Aqui, devo dizer que as plataformas são consideradas bastante pesadas - ou seja, caixas de engrenagens + motores intertravados, algo como o motor da foto, não funcionarão.
Consequentemente, os motores de roda BLDC foram escolhidos como motores. A opção mais acessível no momento são as rodas de prancha 6.5. Resta apenas gerenciá-los a partir de ROS.
Mas então surgiu um problema: mesmo quando se trabalhava com robôs de golfe , um problema significativo foi percebido com a rotação de tal plataforma em baixa velocidade - o robô girou bastante irregular.
As razões para este comportamento são simples: as forças de fricção deslizante desempenham um papel significativo na resistência ao movimento na curva. E eles têm uma peculiaridade - a resistência depende da massa e da natureza das próprias superfícies - é por isso que um pequeno parafuso segura grandes estruturas com as primeiras 2-3 voltas.
Portanto, tornar as rodas estreitas no centro para que vire torna-se bastante inútil - a resistência mudará muito pouco. A roda de borracha esfrega contra a grama e o solo, que não são uniformes e a força pode mudar drasticamente, por isso foi feito algo como uma caixa de câmbio - na velocidade baixa controlamos o momento na roda, e com movimento direto - a própria velocidade.
Ao dirigir em parquet ou linóleo, a situação deveria parecer melhor, mas, infelizmente, o coeficiente de atrito é quase o mesmo (lembre-se que os calçados antiderrapantes também são feitos de borracha).

E como resultado, um robô pesando 10-15 kg já está começando a se desdobrar com solavancos tangíveis.
A segunda parte do problema é adicionada pelo pacote ROS diff_drive em combinação com placas SBC bastante fracas.
Aqui está uma lista do que eu consegui entender
O gerenciamento é realizado em tempo real, mas não leva em consideração que outros pacotes devem esperar essa abordagem ao trabalhar com o gerenciamento.
Aqui, devemos lembrar que o tempo real não é uma reação instantânea a um evento, mas uma garantia de que o evento será processado em intervalos garantidos de tempo físico. Essa. hidrelétrica condicional, regulada a cada minuto (necessariamente a cada) também é um sistema em tempo real.
Há uma chance de que as mensagens obstruam os tópicos do planejador de rotas e, para posicionamento e subsistemas de planejamento de rotas, esse comportamento geralmente leva à interrupção e reinicialização do fluxo ou à tentativa de ajustar o processo em tempo real.

Como resultado, em SBCs fracos , surge uma situação com recálculo contínuo do caminho, ou a busca por localização consome um tempo de processador bastante grande - e quanto mais tentativas são feitas para acompanhar o componente RT, mais tempo de execução se acumula. Em sua forma pura, feedback positivo, que neste caso não é necessário.
Além disso, o gmapping não começa a funcionar muito rapidamente com mudanças abruptas na posição da plataforma e um lidar fraco - houve pausas de até meio segundo, o que também confunde muito o planejador de rotas.
Os motores são controlados separadamente, portanto, ao usar SBC e uma implementação ingênua de drivers, as rodas serão controladas com algum atraso.
Aqui, o problema é ainda mais simples - precisamos controlar 2-4 rodas através do canal de comunicação, que. Conseqüentemente, os sinais de controle se alinham e começam a ser transmitidos um após o outro - roda esquerda, roda direita, roda esquerda, roda direita.
Com isso, as próprias rodas e, pior ainda, as posições das rodas dos codificadores passam a contribuir para a formação do PIC entre o planejamento do trajeto e o controle dos motores.
A odometria embutida é muito simplista.
Como não estávamos procurando uma maneira simples de sincronizar o comando e o retorno da odometria - não consegui encontrar. A sincronização está sempre associada à espera de alguns comandos na entrada, mas eles não são regulares no tempo e, como resultado, a odometria começa a demorar na saída. Talvez os leitores sugiram uma maneira fácil - aqui não nos consideramos um guru em ROS.
Não conseguimos garantir que tal assembleia se comportasse bem. Mais precisamente, foi possível subestimar a aceleração de deslocamento para 0,05-0,1 m / s ^ 2 e a velocidade angular para 0,03 rad / s.
Achei que seria bom ter:
- Plataforma barata
- Direção de roda sincronizada
- Cálculo de odometria baseado no comportamento e manuseio da roda
- Modos de movimento giratório com controles diferentes
- Restrições diferentes em modos diferentes
O que aconteceu no final
O controlador foi retirado das placas da giro-scooter e o controle da roda foi escrito de forma que o controle de torque é usado ao iniciar o movimento e virar. E se o carrinho está indo em linha reta e acelerado até uma determinada velocidade, o modo de controle de velocidade é ativado. Em ambos os modos, os dados dos codificadores são processados dentro do controlador, levando em consideração a velocidade e o modo, e os dados são enviados com alguma previsão antes de 10-15 ms.
Os codificadores são sempre lidos no controlador, se acumulam em um buffer de 2 a 3 elementos e são transmitidos com atraso. O resultado final é que, quando o controle é recebido, a resposta só vai depois que o comando é executado - ou seja, o buffer é bloqueado até que os valores alterados do codificador sejam recebidos. Mas a odometria está sendo emitida, apenas usa o último valor já transmitido.
Porque Todos os problemas acima resumem-se ao fato de que é necessário em qualquer caso sincronizar o controle na recepção e transmissão síncronas da porta UART, então consideramos não razoável introduzir um sincronizador forçado no pacote diff_drive, então escrevemos nosso próprio pacote de controle.
Ele está localizado aqui github.com/Shadowru/hoverboard_driver e está sendo finalizado ativamente:
O pacote está incluído no arquivo de inicialização como:
<node name="hoverboard_driver" pkg="hoverboard_driver" type="node" output="screen">
<param name="uart" value="{ }"/>
<param name="baudrate" value="115200"/>
<param name="wheel_radius" value="0.116"/>
<param name="base_width” value="0.43"/>
<param name="odom_frame” value="odom"/>
<param name="base_frame” value="base_link"/>
</node>
A própria porta uart deve ter os direitos de acesso apropriados; em algumas plataformas, nem sempre tem acesso para o usuário. Por exemplo - para o Jetson Nano no diretório hoverboard_driver / scripts / jetson_nano_serial.sh, é anexado um script que define os direitos quando o sistema operacional é iniciado.
O próprio pacote contém a leitura do fluxo de dados do controlador e a emissão das informações relevantes para os tópicos:
hoverboard_driver / hoverboard_msg com um pacote como hoverboard_msg
A estrutura da mensagem é a seguinte:
int16 estado1 - informações internas na roda 1
int16 estado2 - informações internas na roda 2
int16 velocidade1 - velocidade instantânea da roda 1
int16 speed2 - velocidade instantânea da roda 2
int16 batVoltage - tensão da bateria
int16 boardTemp - temperatura do controlador
int16 error1 - wheel 1 error
int16 error2 - wheel 2 error
int32 pulseCount1 - wheel 1 encoder counter
int32 pulseCount2 - wheel 2 encoder counter
Além disso, o tópico hoverboard_driver / odometry recebe uma mensagem típica nav_msgs :: Odometry A
posição é calculada da seguinte maneira:
Com base nos parâmetros wheel_radius - radius rodas em metros, base_width - a distância entre os centros das rodas, calculamos quanto cada roda se moveu durante o tempo entre a posição anterior e a lida.
double curr_wheel_L_ang_pos = getAngularPos((double) feedback.pulseCount1); double curr_wheel_R_ang_pos = getAngularPos((double) feedback.pulseCount2); double dtime = (current_time - last_time).toSec(); double delta_L_ang_pos = curr_wheel_L_ang_pos - raw_wheel_L_ang_pos; double delta_R_ang_pos = -1.0 * (curr_wheel_R_ang_pos - raw_wheel_R_ang_pos);
Em seguida, calculamos a aceleração de cada uma das rodas
wheel_L_ang_vel = delta_L_ang_pos / (dtime); wheel_R_ang_vel = delta_R_ang_pos / (dtime);
Em seguida, calculamos a aceleração linear do robô ao longo de cada um dos eixos
robot_angular_vel = (((wheel_R_ang_pos - wheel_L_ang_pos) * wheel_radius / base_width) - robot_angular_pos) / dtime; robot_angular_pos = (wheel_R_ang_pos - wheel_L_ang_pos) * wheel_radius / base_width; robot_x_vel = ((wheel_L_ang_vel * wheel_radius + robot_angular_vel * (base_width / 2.0)) * cos(robot_angular_pos)); robot_y_vel = ((wheel_L_ang_vel * wheel_radius + robot_angular_vel * (base_width / 2.0)) * sin(robot_angular_pos));
Como resultado, obtém-se um conjunto completo - aceleração linear, aceleração angular e multiplicando-as pelo tempo - o deslocamento da posição do robô.
robot_x_pos = robot_x_pos + robot_x_vel * dtime; robot_y_pos = robot_y_pos + robot_y_vel * dtime;
Em seguida, é enviada a mensagem da odometria, mais uma tradução tf entre o quadro da odometria e a base.
O controlador de entrada é controlado por um pacote com 2 parâmetros - velocidade e giro, o pacote é traduzido do giro quase nativamente - a velocidade é dividida pela circunferência e giros são obtidos.
double v = vel.linear.x;
double rps = v / rpm_per_meter;
double rpm = rps * 60;
int16_t speed = static_cast(rpm);
e a aceleração angular é convertida na diferença nas velocidades das rodas na forma de multiplicação por um coeficiente, novo cálculo será adicionado levando em consideração a distância entre eixos, mas na prática isso só é necessário para robôs suficientemente grandes e pesados.
double w = vel.angular.z;
int16_t steer = static_cast<int>(-1 * w * 30);
Como resultado, foi possível obter um controle muito estável do carrinho com componentes baratos.

Criamos robôs, como a grande maioria de vocês. Temos nosso principal produto, que estamos desenvolvendo ativamente. Piloto testado e pronto para produção. Este é um robô para coletar bolas de golfe.
Desenvolvemos robôs personalizados e soluções derivadas. Às vezes, é um trabalho desde a especificação técnica e esboço até o produto acabado, às vezes faz parte do trabalho.

Na maioria dos casos, o robô precisa de rodas para interagir com o mundo exterior. Na maioria das vezes, são motores sem escova, devido à capacidade de controlar com precisão a velocidade e a posição.
Para pequenos robôs, as rodas de um giroscópio são frequentemente utilizadas, isso se justifica devido à produção em massa e ao preço desta solução. Qualquer pessoa que tenha visto a lista de preços dos motores russos entende a importância da produção em massa.

Quanto ao controlador, na maioria das vezes são os modelos esc, vesc, odrive, BLD-300B ou soluções próprias.
Para facilitar a criação de robôs reais e quebrar a maldição Gazebo, a maioria dos desenvolvedores precisa de uma baleia para uma entrada fácil. Muito no mundo real é diferente do ideal.
Às vezes acontecem coisas imprevisíveis, os sensores são barulhentos, em tempo real, estouros de buffer. Neste vídeo, o dispositivo que testamos anteriormente com um contator e um kilswitch remoto.
Oferecemos algo que nos ajudaria a poupar nervos em devido tempo, trata-se de um kit de montagem de maleta (paralelepípedo e cilindro), duas rodas motrizes, uma bateria, um carregador e um controlador de flash que dá odometria e funciona com nosso pacote ROS pronto para 19.000 fricção. É mais barato do que o corte por fresamento, o custo de material composto, fixadores e uma roda giratória almofadada.

Ligue para nós ou inscreva-se para uma plataforma de ROS online . Vamos fazer robôs juntos. Falaremos
mais sobre a plataforma no encontro do Robot Operating System em 5 de dezembro. As inscrições para participantes já estão abertas.
→ Registro para visualizadores