Carrinho de caminhão ROS. Parte 7. Localização do robô: gmapping, AMCL, pontos de referência no mapa da sala

Posts da série:
8. Nós controlamos a partir do telefone-ROS Control, GPS-node
7. Localização do robô: gmapping, AMCL, pontos de referência no mapa da sala
6. Odometria com codificadores de roda, mapa da sala, lidar
5. Trabalhamos em rviz e gazebo: xacro, novos sensores.
4. Crie uma simulação de robô usando os editores rviz e gazebo.
3. Acelere, troque a câmera, conserte a marcha
2. Software
1. Ferro

Na última vez, depois de instalar o orçamento lidar RPlidar-A1, conseguimos construir um mapa da sala, trabalhar com odometria. No entanto, o robô, apesar de possuir um cartão e ajustar a odometria dos sensores ópticos, ainda se sente inseguro no ambiente.
Em vez disso, ele não a vê. E ele percorre o mapa acabado por toda parte, obstáculos não são para ele. Isso é agradável e angustiante ao mesmo tempo. Por um lado, não se preocupe com obstáculos e viaje para onde seu coração desejar; por outro lado, é improvável que você vá para outro quarto ou para a cozinha. Portanto, falaremos sobre a localização do robô no espaço usando os algoritmos que o ROS fornece, bem como o conjunto de lidar e codificadores de nossos cavalheiros. Mas antes de irmos diretamente para a localização, vamos falar sobre outro pacote ROS, que também permite criar mapas em 2D da sala e, às vezes, funciona melhor para ele do que o pacote ROS da postagem anterior. Conheça o gmapping.

Rm clã gmapping


Não seremos originais e usaremos os desenvolvimentos do artigo já existente da Habr sobre o tema, mas expandiremos, atualizaremos e aprofundaremos as informações nele contidas. O artigo chama-se Criando um mapa e localizando um robô móvel no ROS sem odômetro usando Laser_scan_matcher .

Parte das manipulações (aplicativos altamente carregados - rviz) será realizada no computador (fora do robô), o restante (driver de movimento, nó de inicialização do lidar) - no robô.

Instale o laser_scan_matcher para ROS-cinetic no computador no cenário do artigo acima primeiro (o artigo era índigo):

sudo apt-get install ros-kinetic-laser-scan-matcher 

Agora corra.

Assente com um lidar no robô:

 roslaunch rplidar_ros rplidar.launch 

Em um computador:

 roslaunch laser_scan_matcher demo.launch 

* Não há necessidade de executar o roscore, pois o nó principal inicia toda vez que o robô é carregado.

No rviz inicial, os contornos da sala e o lixo nela serão visíveis:

imagem

precisaremos de laser_scan_matcher para trabalhar com o pacote ROS do gmapping. Não é necessário instalar o próprio gmapping, ele já está na máquina virtual como parte do ROS Kinetic. Verifique o pacote no sistema:



Agora vamos criar um arquivo de inicialização usando o gmapping no computador (não no robô), como no artigo acima:

 roscd roscd rosbots_description/launch nano my_gmapping_launch.launch     

código
 <?xml version="1.0"?> <launch> <node pkg="tf" type="static_transform_publisher" name="base_link_to_laser" args="0.0 0.0 0.0 0.0 0.0 0.0 /base_link /laser 40" /> <node pkg="laser_scan_matcher" type="laser_scan_matcher_node" name="laser_scan_matcher_node" output="screen"> <param name="fixed_frame" value = "odom"/> <param name="use_odom" value="true"/> <param name="publish_odom" value = "true"/> <param name="use_alpha_beta" value="true"/> <param name="max_iterations" value="10"/> </node> <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen"> <param name="map_udpate_interval" value="1.0"/> <param name="delta" value="0.02"/> </node> </launch> 


Como você pode ver no código, o autor inicia 3 nós: tf, laser_scan_matcher e gmapping.

Vamos executar o lidar no robô novamente:

 roslaunch rplidar_ros rplidar.launch 

No computador, o arquivo de inicialização recém-instalado e o editor rviz:

 roslaunch rosbots_description my_gmapping_launch.launch 

 rosrun rviz rviz 

Em rviz, temos uma imagem semelhante à que foi obtida ao construir o mapa em nosso post anterior sobre o carrinho de robô. Somente desta vez o pacote gmapping funciona.

E devo admitir que não funciona mal. Se hector_slam deixou numerosos artefatos no mapa quando o lidar girou em torno de seu eixo, desta vez quase não há artefatos:



Após viagens pela sala, o mapa construído também é salvo:
rosrun map_server map_saver -f map-1 , em que map-1 é o nome do mapa a ser salvo.

Localização com amcl


O algoritmo usado para determinar a localização do robô no mapa é chamado AMCL. A AMCL usa um filtro de múltiplas partículas para rastrear a posição do robô no mapa. Em nosso robô, usamos o pacote ROS (http://wiki.ros.org/amcl) para implementar a AMCL.

Execute AMCL para o nosso robô.

Para fazer isso, no computador na pasta do projeto, crie outro arquivo de inicialização.

Vamos chamá-lo

amcl-2.launch
 <launch> <param name="/use_sim_time" value="false"/> <node pkg="tf" type="static_transform_publisher" name="base_link_to_laser" args="0.0 0.0 0.0 0.0 0.0 0.0 /base_link /laser 40" /> <node pkg="laser_scan_matcher" type="laser_scan_matcher_node" name="laser_scan_matcher_node" output="screen"> <param name="fixed_frame" value = "odom"/> <param name="use_alpha_beta" value="true"/> <param name="max_iterations" value="10"/> </node> <node name="map_server" pkg="map_server" type="map_server" args="/home/pi/catkin_ws/src/rosbots_description/maps/map-3.yaml"/> <node pkg="amcl" type="amcl" name="amcl" output="screen" > <!-- Publish scans from best pose at a max of 10 Hz --> <param name="odom_model_type" value="diff"/> <param name="odom_alpha5" value="0.1"/> <param name="transform_tolerance" value="0.2" /> <param name="gui_publish_rate" value="10.0"/> <param name="laser_max_beams" value="30"/> <param name="min_particles" value="500"/> <param name="max_particles" value="5000"/> <param name="kld_err" value="0.05"/> <param name="kld_z" value="0.99"/> <param name="odom_alpha1" value="0.2"/> <param name="odom_alpha2" value="0.2"/> <!-- laser, translation std dev, m --> <param name="laser_min_range" value="-1"/> <param name="laser_max_range" value="-1"/> <param name="odom_alpha3" value="0.8"/> <param name="odom_alpha4" value="0.2"/> <param name="laser_z_hit" value="0.5"/> <param name="laser_z_short" value="0.05"/> <param name="laser_z_max" value="0.05"/> <param name="laser_z_rand" value="0.5"/> <param name="laser_sigma_hit" value="0.2"/> <param name="laser_lambda_short" value="0.1"/> <param name="laser_lambda_short" value="0.1"/> <param name="laser_model_type" value="likelihood_field"/> <!-- <param name="laser_model_type" value="beam"/> --> <param name="laser_likelihood_max_dist" value="2.0"/> <param name="update_min_d" value="0.2"/> <param name="update_min_a" value="0.5"/> <param name="odom_frame_id" value="odom"/> <param name="base_frame_id" type="str" value="base_link" /> <param name="global_frame_id" type="str" value="map" /> <param name="resample_interval" value="1"/> <param name="transform_tolerance" value="0.1"/> <param name="recovery_alpha_slow" value="0.0"/> <param name="recovery_alpha_fast" value="0.0"/> <param name="use_map_topic" value="true" /> <param name="first_map_only" value="true" /> </node> </launch> 


O código é completamente idêntico ao artigo já mencionado, com exceção de:
- excluiu o nó que inicia o hokuyo lidar (ele roda no robô)
- o caminho e o nome do mapa do quarto são diferentes (map-3.yaml)
O código executa 4 nós:
- tf
- map_server
- laser_scan_matcher
- amcl
O nó amcl usa o mapa que map_server publica para a localização subsequente do robô.

Execute os arquivos de inicialização e observe o resultado.

Mas para o Robot:

 roslaunch rplidar_ros rplidar.launch 

Em um computador:
1º terminal: roslaunch rosbots_description amcl-2.launch
2o terminal: roslaunch rosbots_description rviz.launch

Após o início do rviz, as próximas etapas deste editor serão as seguintes:
- adicione exibições ao rviz:
• LaserScan
• mapa
• PoseArray


- localize o robô no estágio inicial, pois ao iniciar o amcl não se sabe onde o robô começou e onde está. Precisa de "inicialização inicial".
Para isso, no rviz, é necessário selecionar “Estimativa de pose 2D” e usar a seta verde à direita na janela onde o robô é mostrado para indicar sua posição:



Esta operação deve ser feita selecionando o Frame "map" no rviz:



No terminal, obtemos as coordenadas (pose) do robô:

 [ INFO] [1572374324.454855505]: Setting pose (1572374324.454806): -0.014 -0.012 0.655 

Você pode definir a posição do robô no mapa usando a seta verde no mapa repetidamente.
É desejável que os dados do lidar (borda vermelha) no mapa coincidam ou estejam perto da localização real das paredes da sala:



Na janela de visualização do rviz, encontramos as setas vermelhas características ao redor do robô *:



* como robô, temos um eixo de clareza (todo o modelo rviz pintado ainda está oculto).
** Se as setas não aparecerem, tente remover e verificar novamente a tela PoseArray adicionada ao rviz.

Apesar de termos indicado diretamente no mapa onde o robô está localizado, o sistema ainda pressupõe que ele pode estar naqueles locais onde as setas vermelhas são desenhadas. Esta é a provável localização do robô no mapa. Um grande número de setas e sua dispersão no mapa indica que o sistema ainda não sabe a localização exata do robô. No entanto, o local em que o atirador é mais denso, o robô é mais provável.

Para que o sistema entenda com mais precisão exatamente onde está o robô, é necessário montar em um mapa com nós em execução que determinam a localização do robô. Temos deste conjunto: lidar e codificadores.
Mas viajamos no mapa apenas com o lidar lançado, ao mesmo tempo em que descobrimos se é possível localizar o robô de maneira confiável apenas com a ajuda do (lidar).
-
montar um robô em um mapa
No robô:

 rosrun rosbots_driver part2_cmr.py 

Em um computador:

 rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/part2_cmr/cmd_vel 


Durante a viagem, a amcl começará a ler os tópicos / scan, / map, / tf e publicará a localização do robô nos tópicos / amcl_pose e / particlecloud.

À medida que você viaja, pode observar que o número de setas diminui e elas são cada vez mais condensadas em um ponto com a localização real do robô:


A figura mostra como o modelo viaja (na forma de uma árvore de conexões). E também é visto que o lidar não lida com precisão o suficiente com a localização em limites ambíguos da sala.

O que significam os outros parâmetros no código do nó amcl?


Convencionalmente, eles são divididos em básico (geral), parâmetros de filtro (filtro), parâmetros de laser (lidar) (parâmetros de laser).

Parâmetros principais:
  • odom_model_type (padrão: "diff"): determina qual modelo de odometria usar. Temos diff, o que significa diferencial. Pode ser alterado para "omni", "correção corrigida" ou "omni corrigida".
  • odom_frame_id (padrão: "odom"): define o quadro (leia o tópico) ao qual a odometria será associada. Geralmente é publicado no tópico odom.
  • base_frame_id (padrão: "base_link"): quadro para a base do robô.
  • global_frame_id (padrão: "map"): quadro do mapa, como regra, o servidor de mapa o publica no mapa de tópicos
  • use_map_topic (padrão: false): determina se o mapa será carregado através do tópico ou chamando o serviço (lembramos que, além dos tópicos no ROS, também existem serviços e ações.


Parâmetros de filtro
Essas opções permitem personalizar o funcionamento do filtro de partículas.

  • min_particles (padrão: 100): define o número mínimo de partículas para o filtro. Nós temos 500.
  • max_particles (padrão: 5000): define o número máximo de partículas para o filtro.
  • kld_err (padrão: 0,01): define o erro máximo permitido entre a distribuição verdadeira e a distribuição calculada. Temos 0,05
  • update_min_d (padrão: 0.2): define a distância linear (em metros) que o robô deve percorrer para atualizar o filtro.
  • update_min_a (padrão: pi / 6.0): define a distância angular (em radianos) que o robô deve mover para atualizar o filtro. Temos 0,5
  • resample_interval (padrão: 2): define o número de atualizações de filtro necessárias antes de buscar novamente. Nós temos 1.
  • transform_tolerance (padrão: 0.1): O tempo (em segundos) durante o qual a transformação publicada deve ser datada para indicar que essa transformação é válida no futuro.
  • gui_publish_rate (padrão: -1.0): a velocidade máxima (em Hz) na qual as varreduras e caminhos são publicados para visualização. Se este valor for -1,0, esta função está desativada. Nós temos 10.


Parâmetros do laser (lidar) (Parâmetros do laser)
Esses parâmetros permitem configurar como o amcl interage com o lidar laser.

  • laser_min_range (padrão: -1.0): o intervalo mínimo de varredura a ser considerado; -1,0 utilizará o intervalo mínimo especificado no relatório do laser.
  • laser_max_range (padrão: -1.0): O intervalo máximo de digitalização a ser considerado; -1,0 usará o alcance máximo do laser.
  • laser_max_beams (padrão: 30): quantos feixes distribuídos uniformemente em cada varredura serão usados ​​ao atualizar o filtro.
  • laser_z_hit (padrão: 0,95): os pesos do componente z_hit do modelo do robô.
  • laser_z_short (padrão: 0.1): os pesos do componente z_short do modelo do robô.
  • laser_z_max (padrão: 0,05): o peso do componente z_max do modelo do robô.
  • laser_z_rand (padrão: 0.05): os pesos do componente z_rand do modelo do robô.


Vamos ver o que os parâmetros min_particles e max_particles afetam. Se você reduzir seus valores, quando iniciar o arquivo de inicialização, o número de partículas no editor visual será claramente menor.

Todos os parâmetros carregam uma carga semântica, mas é difícil analisar o efeito de alterar cada um deles na estrutura do artigo.

Pontos de referência no mapa do quarto


O nome é cativante e implica a posição do robô no mapa nesse momento específico.

Para que eles servem? Para entender que o robô veio do ponto A na sala até o ponto B na cozinha.

Dados sobre a posição (pose) do robô podem ser obtidos com o nó de trabalho amcl (o que foi iniciado no artigo acima).

E veja o tópico / amcl_pose:

 rostopic echo -n1 /amcl_pose 

* tecla n1 - para "consertar" o fluxo de mensagens no tópico.



Vamos criar um serviço que, quando chamado, abrirá a posição (coordenadas) do robô, para que cada vez que ele não analise o tópico.

1.Crie um novo pacote de ros.

 cd catkin_ws/src catkin_create_pkg get_pose rospy cd get_pose/src 

2. Na pasta, crie o arquivo:

get_pose_service.py
 #! /usr/bin/env python import rospy from std_srvs.srv import Empty, EmptyResponse # Import the service message python classes generated from Empty.srv. from geometry_msgs.msg import PoseWithCovarianceStamped, Pose robot_pose = Pose() def service_callback(request): print "Robot Pose:" print robot_pose return EmptyResponse() # the service Response class, in this case EmptyResponse def sub_callback(msg): global robot_pose robot_pose = msg.pose.pose rospy.init_node('service_server') my_service = rospy.Service('/get_pose_service', Empty , service_callback) # create the Service called get_pose_service with the defined callback sub_pose = rospy.Subscriber('/amcl_pose', PoseWithCovarianceStamped, sub_callback) rospy.spin() # mantain the service open. 


* Não se esqueça de torná-lo executável chmod + x get_pose_service.py
3. Vamos criar o lançamento do arquivo com o código do nó:

 cd .. mkdir launch && cd launch 

nano

get_pose_service.launch
 <launch> <node pkg="get_pose" type="get_pose_service.py" name="service_server" output="screen"> </node> </launch> 


4.Não se esqueça de reconstruir o amentilho:

 cd catkin_ws catkin_make 

Agora reiniciaremos tudo, incluindo o novo arquivo de inicialização.

Mas para o Robot:

 roslaunch rplidar_ros rplidar.launch 

Em um computador:

 1- : roslaunch rosbots_description amcl-2.launch 2- : roslaunch rosbots_description rviz.launch 3- : roslaunch get_pose get_pose_service.launch 

Passamos ao novo serviço, que deve nos dar a posição atual do robô no mapa (chamaremos o serviço ROS):

 rosservice call /get_pose_service 

No terminal executando o lançamento get_pose, obteremos as coordenadas do robô no mapa:



Possíveis erros.

[rviz.launch] não é um arquivo de inicialização no pacote [rosbots_description] nem [rosbots_description] é um nome de arquivo de inicialização
solução:

 cd catkin_ws source devel/setup.bash 

Source: https://habr.com/ru/post/pt472984/


All Articles