Criando arquivos de launch

Tendo visto como os arquivos de launch podem ser usados, estamos prontos para pensar como criá-los para nosso uso.

Sumário

  1. Onde colocar arquivos de launch
  2. Ingredientes Básicos
    1. Inserind o o elemento raíz
    2. Nós de launching
    3. Encontrando arquivos de log de um nó
    4. Direcionando saídas para o console
    5. Solicitando respawning
    6. Solicitando nós
    7. Executando nós nas suas próprias janelas

Onde colocar arquivos de launch

Assim como todos os outros arquivos ROS, cada arquivo de launch deve estar associado a um pacote específico. O esquema de nomeação serve para dar nomes aos arquivos de launch, terminando com .launch. O lugar mais simples para armazenar os arquivos de launch é diretamente no diretório de pacotes. Quando estiver procurando por arquivos de launch, o roslaunch também buscará por subdiretórios de cada diretório de pacote. Alguns pacotes, incluindo vários do núcleo de pacotes ROS, utilizam este recurso ao organizar os arquivos de launch dentro de um subdiretório próprio, usualmente chamado launch.

Ingredientes Básicos

Os arquivos de launch mais simples consistem de um elemento raíz contendo diversos elementos node.

Inserind o o elemento raíz

Arquivos de launch são documentos XML, e cada documento XML deve ter exatamente um elemento raíz. Para os arquivos de launch do ROS, cada elemento raíz é definido por um par de etiquetas launch:

<launch>
...
</launch>

Todos os outros elementos de cada arquivo de launch devem ser inclusos entre estas etiquetas.

Nós de launching

O coração de qualquer arquivo de launch é a coleção de elementos nós, que nomeia um único a ser executado. Um elemento nó se parece com:

<node
pkg="package-name"
type="executable-name"
name="node-name"
/>

⚠️ A barra final próxima ao fim da etiqueta do nó é importante e fácil de ser esquecida. Ela indica que nenhuma etiqueta de fechamento (“</node>”) está por vir, e que cada elemento node está completo. Parsers do tipo XML são necessários para sermos rigorosos com esse tipo de coisa. Se você omitir essa barra, esteja preparado para erros do tipo:

Invalid roslaunch XML syntax: mismatched tag

You can also also write the closing tag explicitly:

node pkg="..." type="..." name="..."></node>

Na verdade, esta etiqueta de fechamento é necessária se o nó tem filhos, tais como remap ou elementos param. Estes elementos são introduzidos nas seções 6.4 and 7.4, respectivamente.

Um elemento node tem três atributos necessários:

  • Os atributos pkg e type identificam qual programa ROS deve ser executado para iniciar este nó.
    Estes são os mesmos que os dois argumentos de linha de comando do rosrun, especificando o nome do pacote e o nome do executável, respectivamente.
  • O atributo name designa um nome para o nó. Isso sobrescreve qualquer nome que o nó normalmente atribuiria a si mesmo na sua chamada do ros::init.

⏩ Esse ato de sobrescrever elimina a informação quanto ao nome provida ao ros::init, incluindo qualquer outra requisição que o nó possa ter feito para um nome anônimo. (Veja a Section 5.4.) Para utilizar um nome anônimo de dentro de um arquivo launch, use uma substituição anon para o atributo do nome, do tipo:

name="$(anon base_name)"

Note, no entanto, que múltiplos usos do mesmo nome base gerarão o mesmo nome anônimo. Isto significa que (a) podemos nos referir àquele nome em outras partes do arquivo de launch, mas (b) devemos ser cuidadosos ao utilizar diferentes nomes base para cada nó que desejamos tornar anônimos.

Encontrando arquivos de log de um nó

Uma diferença importante entre o roslaunch e a execução individual de cada nó utilizando o rosrun é que, por padrão, as saídas padrão dos nós executados são redirecionadas para um arquivo de log, não aparecendo no console1. O nome do arquivo de log é:

∼/.ros/log/run_id/node_name-number-stdout.log

O run_id é um identificador único gerado quando o master é iniciado. Os números nestes arquivos são pequenos inteiros que numeram os nós. Por exemplo, executar o arquivo de launch na Lista 6.1 envia a saída padrão de dois dos seus nós para um arquivo de log com os seguintes nomes:

turtlesim-1-stdout.log
telep_key-3-stdout.log

Estes arquivos de log podem ser visualizados por meio de um editor de texto à sua escolha.

Direcionando saídas para o console

Para sobrescrever esse comportamento para um único nó, use o atributo output no seu elemento node:

output="screen"

Nós iniciados com esse atributo exibirão a sua saída padrão em tela ao invés de exibir nos arquivos de log discutidos acima. Esse exemplo usa o esse atributo para o nó subpose, o que explica porque as mensagens INFO desse nó aparecem no console. Isso também explica porque esse nó não está presente na lista de arquivos de log acima.

Além do atributo output, que afeta somente um único nó, nós podemos forçar o roslaunch mostrar a saída de todos os seus nós, utilizando a opção de linha de comando --screen:

roslaunch --screen package-name launch-file-name

⚠️ Se um programa, quando iniciado a partir do roslaunch, não produz a saída que você espera, deve-se verificar se aquele nó tem o atributo output="screen" habilitado.

Solicitando respawning

Após iniciar todos os nós requisitados, o roslaunch monitora cada um deles, rastreando aqueles que permanecem ativos. Para cada nó, podemos solicitar o roslaunch que reinicie quando estiver finalizado, ao utilizar o atributo respawn:

respawn="true"

Isso pode ser útil, por exemplo, para nós que podem finalizar prematuramente, devido a falhas de software, problemas de hardware, ou outras razões.

O atributo respawn não é realmente necessário no nosso exemplo—Todos os três programas são bastante confiáveis—mas nós incluímos para o turtlesim_node de modo a ilustrar como o respawning funciona. Se você fechar a janela do turtlesim, o nó correspondente será finalizado. O ROS rapidamente nota isso e, já que aquele nó está marcado como um nó de respawn, um novo nó turtlesim, com sua janela correspondente, aparece para substituir o anterior.

Solicitando nós

Uma alternativa ao respawn é declarar que um nó é required:

required="true"

Quando um nó do tipo required termina, o roslaunch responde finalizando todos os outros nós ativos, finalizando ele mesmo. Este tipo de comportamento pode ser útil, por exemplo, para nós que (a) são tão importantes que, se falharem, a sessão por completo deve ser abandonada, e (b) não podem ser normalmente reiniciados pelo atributo respawn.

O exemplo usa o atributo requerido para o nó turtle_teleop_key. Se você fechar a janela na qual o nó de teleoperação está rodando, o roslaunch finalizará os outros dois nós e sairá.

⚠️ Devido ao conflito entre os significados entre eles, o roslaunch reclamará se você definir ambos os atributos respawn e required para um único nó.

Executando nós nas suas próprias janelas

Uma desvantagem em potencial ao utilizar o roslaunch, comparado à nossa técnica original de utilizar o rosrun em um terminal em separado para cada nó, é que todos os nós compartilham o mesmo terminal. Isto é administrável (e muitas vezes útil) para nós que simplesmente geram mensagens de log, e não aceitam entradas do console. Para nós que dependem de entradas do console, como é o caso do turtle_teleop_key, pode ser preferível manter os terminais separados.

Felizmente, o roslaunch provê uma maneira limpa de obter isso, utilizando o atributo launchprefix de um elemento de nó:

launch-prefix="command-prefix"

A ideia é que o roslaunch inserirá o dado pré-fixo no começo da linha de comando que ele constrói internamente na execução do nó em questão. No example.launch, utilizamos este atributo para o nó de teleoperação:

launch-prefix="xterm -e"

Por conta deste atributo, esse elemento de nó é aproximadamente equivalemnte a este comando:

xterm -e rosrun turtlesim turtle_teleop_key

Como você deve saber, o comando xterm inicia uma simples janela terminal. O argumento -e diz ao xterm para executar o restante da sua linha de comando (nesse caso, rosrun turtlesim turtle_teleop_key) dentro de si mesmo, no lugar de um novo shell interativo. O resultado é que o turtle_teleop_key, um programa estritamente baseado em texto, aparece dentro de uma janela gráfica.

⏩ O atributo launch-prefix, naturalmente, não é limitao ao xterm. Ele também pode ser útil na
depuração (via gdb ou valgrind), ou para diminuir o nível de prioridade de um processo (via nice).


1 Na versão atual do roslaunch, saídas de erros padrão—notavelmente incluindo as saídas de console de ERROR- e FATAL-level mensagens de log—aparecem no console, ao invés de estarem presentes nos arquivos de log. Entretanto, um comentário no código fonte do roslaunch enfatiza que este comportamento pode ser modificado no futuro.