TORCS – Instalação e criação de um bot simples
Nesse tutorial, abordarei como criar um bot simples para você colocá-lo correr no TORCS com você, ou contra você :D. Aqui farei uma abordagem breve sobre a instalação do jogo e tentarei nortear quem já soube que é possível construirmos um bot para correr no jogo mas não sabe como começar. Boa leitura.
Parte 5: Detectando quando o carro fica preso em uma curva
Do jeito que nosso código está agora, se o seu carro rodar em uma curva e ficar de frente para o muro como na figura abaixo ele simplesmente vai ficar acelerando contra ele com as rodas viradas para a direção da pista. Se não tivermos uma forma de detectar isso ele provavelmente ficará assim pra sempre. Pra resolver esse problema implementaremos este pseudo-código:
Verifica se o carro está bloqueado();
Se o carro estiver bloqueado {
marcha ré e alinhe o carro;
} senão {
dirija normalmente;
}
A implementação desse código ficará assim (lembrando que esse código não fui eu quem fez, e sim Bernhard Wymann):
Substitua sua função drive inteira por todo esse código, compile, instale novamente seu carro e veja o que acontece agora quando ele se perde em uma curva e empaca. Vale lembrar também que esta função não é a mais completa e possui uma falha no código que o próprio autor coloca com uma fim didático. A função completa se encontra no capítulo 2 do site www. berniw.org e esse erro na função é demonstrado e corrigido.
Verifica se o carro está bloqueado();
Se o carro estiver bloqueado {
marcha ré e alinhe o carro;
} senão {
dirija normalmente;
}
A implementação desse código ficará assim (lembrando que esse código não fui eu quem fez, e sim Bernhard Wymann):
/* função que verifica se o carro está bloqueado a cada 0.02 segundos */
bool isStuck(tCarElt* car)
{
float angle = RtTrackSideTgAngleL(&(car->_trkPos)) - car->_yaw;
NORM_PI_PI(angle);
// angle é menor que 30 graus?
if (fabs(angle) < 30.0/180.0*PI) {
stuck = 0;
return false;
}
//Se o carro está bloqueado ela vai incrementando o contador stuck até que chegue a 100, quando isso acontece ela começa a retornar que o carro está bloqueado. Nesse momento seu carro engata a marcha ré, volta até alinhar e quando estiver alinhado volta a ir pra frente de novo. Quando o carro estiver desbloqueado
if (stuck < 100) {
stuck++;
return false;
} else {
return true;
}
}
/* Drive during race. */
static void
drive(int index, tCarElt* car, tSituation *s)
{
float angle;
const float SC = 1.0;
memset(&car->ctrl, 0, sizeof(tCarCtrl));
if (isStuck(car)) {
angle = -RtTrackSideTgAngleL(&(car->_trkPos)) + car->_yaw;
NORM_PI_PI(angle); // put the angle back in the range from -PI to PI
car->ctrl.steer = angle / car->_steerLock;
car->ctrl.gear = -1; // reverse gear
car->ctrl.accelCmd = 0.3; // 30% accelerator pedal
car->ctrl.brakeCmd = 0.0; // no brakes
} else {
angle = RtTrackSideTgAngleL(&(car->_trkPos)) - car->_yaw;
NORM_PI_PI(angle); // put the angle back in the range from -PI to PI
angle -= SC*car->_trkPos.toMiddle/car->_trkPos.seg->width;
car->ctrl.steer = angle / car->_steerLock;
car->ctrl.gear = 3; // first gear
car->ctrl.accelCmd = 1,0; // 100% accelerator pedal
car->ctrl.brakeCmd = 0.0; // no brakes
}
}
bool isStuck(tCarElt* car)
{
float angle = RtTrackSideTgAngleL(&(car->_trkPos)) - car->_yaw;
NORM_PI_PI(angle);
// angle é menor que 30 graus?
if (fabs(angle) < 30.0/180.0*PI) {
stuck = 0;
return false;
}
//Se o carro está bloqueado ela vai incrementando o contador stuck até que chegue a 100, quando isso acontece ela começa a retornar que o carro está bloqueado. Nesse momento seu carro engata a marcha ré, volta até alinhar e quando estiver alinhado volta a ir pra frente de novo. Quando o carro estiver desbloqueado
if (stuck < 100) {
stuck++;
return false;
} else {
return true;
}
}
/* Drive during race. */
static void
drive(int index, tCarElt* car, tSituation *s)
{
float angle;
const float SC = 1.0;
memset(&car->ctrl, 0, sizeof(tCarCtrl));
if (isStuck(car)) {
angle = -RtTrackSideTgAngleL(&(car->_trkPos)) + car->_yaw;
NORM_PI_PI(angle); // put the angle back in the range from -PI to PI
car->ctrl.steer = angle / car->_steerLock;
car->ctrl.gear = -1; // reverse gear
car->ctrl.accelCmd = 0.3; // 30% accelerator pedal
car->ctrl.brakeCmd = 0.0; // no brakes
} else {
angle = RtTrackSideTgAngleL(&(car->_trkPos)) - car->_yaw;
NORM_PI_PI(angle); // put the angle back in the range from -PI to PI
angle -= SC*car->_trkPos.toMiddle/car->_trkPos.seg->width;
car->ctrl.steer = angle / car->_steerLock;
car->ctrl.gear = 3; // first gear
car->ctrl.accelCmd = 1,0; // 100% accelerator pedal
car->ctrl.brakeCmd = 0.0; // no brakes
}
}
Substitua sua função drive inteira por todo esse código, compile, instale novamente seu carro e veja o que acontece agora quando ele se perde em uma curva e empaca. Vale lembrar também que esta função não é a mais completa e possui uma falha no código que o próprio autor coloca com uma fim didático. A função completa se encontra no capítulo 2 do site www. berniw.org e esse erro na função é demonstrado e corrigido.