Outros elementos de arquivos launch

Sumário

  1. Incluindo outros arquivos
  2. Argumentos launch
    1. Declarando argumentos
    2. Atribuindo valores a argumentos
    3. Acessando valores de argumento
    4. Enviando valores de argumento para arquivos launch incluídos
  3. Criando grupos

Essa seção introduz algumas construções roslaunch adicionais. Para ilustrar essas características, nós vamos nos referir ao arquivo launch em Lista 6.6. Esse arquivo começa com ou duas ou três simulações turtlesim, dependendo de como foi gerado.

Lista 6.6

Um arquivo do tipo launch chamado triplesim.launch que ilustra os argumentos group, include, arg.
$ triplesim.launch
<launch>
  <include
    file ="$(findagitr)/double sim.launch "
  />
  <arg
  name="use_sim3 "
  default="0"
  />

  <group ns="sim3 " if ="$ (arg use_sim3) " >
    <node
      name="turtlesim_node "
      pkg="turtlesim"
      type="turtlesim_node "
    />
    <node
      pkg="turtlesim "
      type="turtle_teleop_key"
      name="teleop_key "
      required="true"
      launch−prefix="xterm−e "
    />
  </group>
</launch>

Incluindo outros arquivos

Para incluir o conteúdo de outro arquivo launch, incluido todos os seus nodes e parâmetros, utilize um elemento include:

<include file="path-to-launch-file" />

O atributo do arquivo espera o caminho inteiro para o arquivo que se quer incluir. Porque pode ser incômodo e irritante colocar essa informação diretamente, a maioria dos elementos do tipo include utilizam uma substituição do tipo find para procurar um pacote, no lugar de nomear o diretório explicitamente:

<include file="$(find package-name)/launch-file-name" />

O argumento find é expandido, via uma string de substituição, para o caminho do pacote. Logo, o arquivo launch específico é muito mais fácil de se nomear. Um exemplo utiliza essa técnica para incluir nosso exemplo anterior doublesim.launch.

⚠️ Não esqueça que roslaunch irá procurar dentro do subdiretório de um pacote quando for procurar um arquivo de tipo launch dado na linha de comando. De outro modo, elementos do tipo include devem nomear caminhos específicos para o arquivo que querem, e não podem contar com a procura de subdiretórios. Essa diferença explica como o elemento include pode gerar erros, mesmo se a chamada de roslaunch, com o mesmo nome do pacote e no arquivo tenha sucesso.

O elemento include também suporta o atributo ns para empurrar o seu conteúdo para um namespace:

<include file=". . . " ns="namespace" />

Esse setup ocorre comumente, especialmente quando o arquivo launch incluído faz parte de um outro pacote, e deveria operar independente de outros nodes.

Argumentos launch

Para ajudar a tornar arquivos launch configuráveis, roslaunch suporta argumentos launch, também chamados de argumentos ou de args, que funcionam de forma parecida com variáveis locais em um programa executável. A vantagem é que você pode evitar duplicação de código escrevendo arquivos launch que usam argumentos para o número pequeno de detalhes que podem mudar a cada utilização. Para ilustrar essa ideia, o exemplo utiliza um argumento, chamado use_sim3, para determinar se a turtlesim é iniciada com três cópias ou com duas.

⚠️ Apesar dos termos argumento e parâmetro serem utilizados de forma intercambiável em muitos contextos, seus significados são bem diferentes em ROS. Parâmetros são valores utilizados por um sistema ROS em andamento, guardados no servidor do parâmetro e acessíveis para nodes ativos via funções do tipo ros::param::get e para usários via rosparam. (ver Capítulo 7). Em contraste, argumentos fazem sentido apenas dentro de arquivos do tipo launch, seus valores não são diretamente disponíveis para os nós.

Declarando argumentos

Para declarar a existência de um argumento, utilize um elemento arg:

<arg name="arg-name" />

Declarações como essa não são estritamente necessárias (a não ser que você queira atribuir default ou um valor — veja abaixo), mas são uma boa ideia porque eles tornam mais claro para um leitor o que os argumentos de um arquivo launch esperam.

Atribuindo valores a argumentos

Todos os argumentos utilizados em um arquivo launch devem ter um valor atribuído. Existem algumas formas de fazer isso. Você pode atribuir o valor via a linha de comando de roslaunch:

roslaunch package-name launch-file-name arg-name:=arg-value

De outra forma, você pode atribuir um valor como parte da declaração de um arg, utilizando uma dessas duas síntaxes:

<arg name="arg-name" default="arg-value" />
<arg name="arg-name" value="arg-value" />

A única diferença entre elas é que um argumento via linha de comando pode sobrepor um default, mas não um valor. No exemplo, use_sim3 possui um valor default de 0, mas isso pode ser mudado vinha linha de comando, dessa forma:

roslaunch agitr triplesim.launch use_sim3:=1

Se fôssemos modificar um arquivo launch, substituindo um default com um valor, então esse comando teria como resultado um erro, pois valores de argumentos modificador por valor não podem ser mudados.

Acessando valores de argumento

Uma vez que um argumento é declado e um valor é atribuído a ele, você pode utilizar esse valor por meio de uma substituição arg, dessa forma:

$(arg arg-name)

Em qualquer lugar que essa substituição aparece, roslaunch irá substituir com o valor do argumento dado. No exemplo, nós utilizamos use_sim3 como argumento uma vez, dentro do atributo if de um elemento de grupo. (Nós iremos introduzir if e grupo em breve.)

Enviando valores de argumento para arquivos launch incluídos

Uma limitação na técnica de configurar argumentos apresentada até agora é que não é fornecida uma forma de passar o argumento para um arquivo launch subordinado que é importado utilizando os elementos include. Isso é importante pois, similar a (lexical) variáveis locais, argumentos são definidos apenas para o arquivo launch que os declara. Argumentos não são “herdados” por arquivos launch incluídos. A solução é inserir elementos arg como criançãs de um elemento include, dessa forma:

  <include file="path-to-launch-file">
    <arg name="arg-name" value="arg-value"/>
  . . .
  </include>

Note que essa utilização de elemento arg difere da declaração arg que nós vimos até agora. Os argumentos mencionados entre as tags de include são argumentos para o arquivo incluído e não para o arquivo launch em que eles aparecerem. Pois o propósito é estabelecer valores para os argumentos necessários do arquivo include, o atributo valor é necessário nesse contexto.

Um cenário comum é que os dois arquivos launch — o incluído e o que inclui — tem alguns argumentos em comum. Nesses casos, nós talvez queiramos passar esses valores sem mudá-los. Um elemento como este, utilizando o mesmo argumento nos dois lugares, faz o seguinte:

<arg name="arg-name" value="$(arg arg-name)" />

Nesta instância, a primeira aparição do nome do argumento refere-se, usualmente, ao nome do argumento incluído no arquivo launch. A segunda refere-se ao arquivo launch que inclui. O resultado é que o argumento terá o mesmo valor em ambos os arquivos launch.

Criando grupos

Uma característica final é o elemento grupo, que provém uma maneira conveniente de organizar nodes em um arquivo launch grande. O elemento grupo pode servir a dois propósitos:

  • Grupos podem empurrar diversos nodes para um mesmo namespace.
<group ns="namespace">
 . . .
</group>
  • Todo node dentro do grupo começa com o namespace default.

⏩ Se um node agrupado tem seu próprio atributo ns e o nome é (como provavelmente deveria ser) um nome relativo, então o node resultante será iniciado com um namespace default que aninha o último namespace com o artual. Essas regras, que correspondem a algo que alguém deveria esperar para resolver nomes relativos, também se aplicam para grupos aninhados.

  • Groupos podem condionalmente habilar ou desabilitar nodes.
<group if="0-or-1">
 . . .
</group>

Se o valor do atributo if for 1, então os elementos são incluídos normalmente. Se o atributo tem valor 0, então os elementos são ignorados. O atributo unless opera de forma semelhante, mas com o seu significado reverso:

<group unless="1-or-0">
 . . .
</group>

Naturalmente, é incomum escrever diretamente 0 ou 1 para esses atributos. Combinando com a técnica de substituição de arg, entretanto, formam uma forma potente de tornar seus arquivos launch configuráveis.

⚠️ Note que 0 e 1 são os únicos valores legítimos para esses atributos. Em particular, as operações na forma usual booleana AND e OR que você talvez espere não são disponíveis diretamente.

O exemplo tem um grupo único que combina esses dois propósitos. O grupo tem tanto o atributo ns (para empurar os dois nodes do grupo para o namespace sim3) e o atributo if (para implementar a habilitação ou desabilitação da terceira simulação baseada no argumento use_sim3).

⚠️ Note que o grupo não é estritamente necessário. Sempre é possível escrever os argumentos ns, if, e unless manualmente para cada elemento que talvez seja incluído em um grupo. Contudo, grupos podem reduzir duplicação — os namespaces e as condições aparecem uma única vez — e tornam a organização do arquivo launch mais fácil de se ler.

⏩ Infelizmente, apenas esses três atributos podem ser passados via grupo. Por exemplo, não importa o quanto nós queiramos, output="screen" não pode ser configurada para um elemento de grupo, e deve ser dada diretamente para cada node em que é necessário aplicá-lo.