sexta-feira, 2 de julho de 2010

Enviar comandos de teclado a uma aplicação através do terminal

Estou tentando treinar um controlador para aprender a dirigir em uma pista através de aprendizado não supervisionado. Estou rodando meu experimento no simulador TORCS, o que envolve reiniciar a corrida muitas vezes. O TORCS tem um bug que depois de re-iniciada a corrida centenas de vezes acaba gerando um segmentation fault. Ou seja, é um bug bastante chato de ser reproduzido e consequentemente bastante difícil de depurar e corrigir.

Para contornar este problema e ganhar tempo de simulação resolvi procurar uma solução para verificar se o TORCS estava rodando, em caso negativo (aconteceu o segfault) eu o reiniciaria, porém teria que mandar 4 enters para iniciar a simulação.

Após uma googleada encontrei a solução rapidamente. Utilizando o comando xsendkeycode é possível enviar sinais de teclados para a aplicação que está com foco. Com o comando ps e grep consegui verificar se o programa estava rodando.

No link http://www.anyexample.com/linux_bsd/bash/check_if_program_is_running_with_bash_shell_script.xml encontrei o script que verifica se um programa está rodando e nos links http://linux.die.net/man/8/xsendkeycode, http://www.linuxforums.org/forum/linux-programming-scripting/136576-simulating-pressed-keys-shell-script-3.html achei as peças para enviar os comandos enter.

No final criei o seguinte script:

#!/bin/bash
GAME='torcs'

OUT=$(ps ax | grep -v grep | grep $GAME)

if [ "x$OUT" != "x" ]
then
sleep 30
else
$GAME & sleep 2; xsendkeycode 36 1; xsendkeycode 36 0; xsendkeycode 36 1; xsendkeycode 36 0; xsendkeycode 36 1; xsendkeycode 36 0; xsendkeycode 36 1; xsendkeycode 36 0;
fi


E chamei-o com a seguinte linha para ficar em um loop infinito:

while [ 1 ]; do ./run_game.sh; done