Remapeando nomes
Sumário
Além de resolver nomes relativos e nomes provados, os nós ROS também suportam remapeamentos, que fornecem um nível mais preciso de controle para modificar os nomes usados pelos nossos nós. Remapeamentos são baseados na ideia de substituição: cada remapeamento fornece um nome original e um novo nome. Cada vez que um nó usa qualquer um dos nomes originais de seus remapeamentos, a biblioteca cliente ROS silenciosamente o substitui pelo novo nome daquele remapeamento.
Criando Remapeamentos
Existem duas maneiras de criar remapeamentos ao iniciar um nó.
- Para remapear um nome quando se inicia um nó a partir da linha de comando, forneça o nome original e o nome novo, separados por um
:=
, em algum lugar da linha de comando.
original-name:=new-name
Por exemplo, para executar uma instância turtlesim
que publica seus dados de pose em um tópico chamado /tim
em vez de /turtle1/pose
, use um comando como este:
rosrun turtlesim turtlesim_node turtle1/pose:=tim
- Para remapear nomes em um arquivo launch, use um elemento de remapeamente:
<remap from="original-name" to="new-name" />
Se isso aparecer no nível superior, como um filho do elemento launch
, esse remapeamento vai ser aplicado para todos os nós subsequentes. Esses elementos remap
também pode aparecer como um filho de um elemento nó
, como isso:
<node node-attributes >
<remap from="original-name" to="new-name" />
. . .
</node>
Neste caso, os remapeamentos fornecidos são aplicados apenas no único nó que os possui. Por exemplo, o comando de linha acima é essencialmente equivalente a essa construção de arquivo:
<node pkg="turtlesim" type="turtlesim_node"
name="turtlesim" >
<remap from="turtle1/pose" to="tim" />
</node>
Há uma coisa importante para relembrar sobre o modo como os remapeamentos são aplicados: todos os nomes, incluindo o nome original e os novos no próprio remapeamento, são resolvidos para nomes globais, antes do ROS aplicar qualquer remapeamento. Como resultado, nomes que aparecem em remapeamentos são frequentemente nomes relativos. Depois que a resolução do nome está completa, o remapeamento é feito por uma comparação direta de string, procurando por nomes usados por um nó que combina exatamente com o nome original resolvido em qualquer remapeamento.
Invertendo uma tartaruga
Para um exemplo concreto sobre como esses tipos de remapeamentos podem ser úteis, considere um cenário em que queremos usar o turtle_teleop_key
para dirigir o turtlesim
tartaruga, mas com o sentido das teclas de setas invertidos. Ou seja, suponha que queremos que as teclas de seta esquerda e direita rotacionem a tartaruga no sentido horário e anti-horário, respectivamente, e as setas para cima e para baixo movam a tartarura para trás e para frente, respectivamente. O exemplo pode parecer artificial, mas representa uma classe geral de problemas reais em que as mensagens publicadas por um nó devem ser “traduzidas” em um formato esperado por outro nó.
Uma opção, é claro, seria fazer uma copia do código-fonte turtle_teleop_key
e modificá-lo para refletir a mudança que queremos. Essa opção é bem insatisfatória, porque ela requer que entendêssemos e, pior ainda, que duplicassemos o código turtle_teleop_key
. Em vez disso, vamos ver como fazer isso composicionalmente, criando um novo programa que inverte os comandos de velocidade publicados pelo nó de teleoperação existente.
A Lista 6.4 mostra um pequeno programa que realiza a mudança que precisamos: Ele assina turtle1/cmd_vel
e, para cada mensagem que recebe, inverte tanto a velocidade linear quanto a angular, publica o resultado do comando de velocidade resultante em turtle1/cmd_vel_reversed
.
Lista 6.4
Um programa C++ reverse_cmd_vel
que inverte os comandos de velocidade do turtlesim.
1 // This program subscribes to turtle1/cmd_vel and
2 // republishes on turtle1/cmd_vel_reversed,
3 // with the signs inverted .
4 #include <ros/ros.h>
5 #include <geometry_msgs/Twist.h>
6
7 ros :: Publisher∗pubPtr;
8
9 void commandVelocityReceived(
10 const geometry_msgs :: Twist&msgIn
11 ) {
12 geometry_msgs : : Twist msgOut ;
13 msgOut.linear.x = −msgIn.linear.x ;
14 msgOut.angular.z = −msgIn.angular.z ;
15 pubPtr−>publish(msgOut) ;
16 }
17
18 int main (int argc, char ∗∗ argv){
19 ros :: init (argc, argv, " reverse_velocity") ;
20 ros :: NodeHandle nh ;
21
22 pubPtr = new ros :: Publisher(
23 nh.advertise <geometry_msgs :: Twist >(
24 " turtle1/cmd_vel_reversed",
25 1000));
26
27 ros :: Subscriber sub = nh.subscribe(
28 " turtle1/cmd_vel" , 1000,
29 &commandVelocityReceived) ;
30
31 ros :: spin() ;
32
33 delete pubPtr ;
34 }
A única compilação - e a razão deste exemplo pertencer a uma seção sobre remapeamentos - é que o simulador turtlesim
não assina de fato essas mensagens de velocidades invertida. Na verdade, iniciar os três nós relevantes com comandos simples rosrun
leva à estrutura de gráfico mostrada na Figura 6.2. Pelo gráfico fica claro que este sistema não teria o comportamento desejado. Como os comando de velocidade ainda vão diretamente do teleop_turtle
para turtlesim
, a tartaruga ainda responde de maneira usual e irreversível.
Figura 6.2: O gráfico ROS resultante do uso incorreto reverse_cmd_vel
para reverter uma tartatuga turtlesim
. .
Essa situação - na qual algum nó se inscreve no tópico “errado” = é precisamente o tipo de situação a qual remapeamentos são destinados. Nesse caso, podemos corrigir o problema enviando um remapeamento para o turtlesim
que substitui o turtle1/cmd_vel
por turtle1/cmd_vel_reversed
. A Lista 6.5 mostra um arquivo launch que inicializa todos os três nós, incluindo o remap
apropriado para o turtlesim_node
. A Figura 6.3 mostra o gráfico correteo deste resultado.
Figura 6.3: O gráfico correto resultante de code>reversed.launch</code>. O elemento remap
permite que os nós se conectem corretamente.
Lista 6.5
Um arquivo launch chamado de reverse.launch
que inicia um turtlesim
que pode ser teleoperado com direções invertidas
$ example.launch
<launch>
<node
pkg="turtlesim"
type="turtlesim_node"
name="turtlesim"
respawn="true"
/>
<node
pkg="turtlesim"
type="turtle_teleop_key"
name="teleop_key"
required="true"
launch−prefix="xterm −e"
/>
<node
pkg="agitr"
type="subpose "
name="pose_subscriber "
output="screen"
/>
</launch>