resposta curta; não, você realmente precisa fazer as coisas de maneira um pouco diferente.
resposta longa e incompleta; Deixe-me fornecer um código psuedo apropriado para robotC, que coloca você em um caminho melhor. Primeiro, não use tarefas - NÃO é para isso que servem as tarefas robotC. Eles podem ser feitos para funcionar, talvez, talvez não (e você precisa de algumas alterações para tentar).
// global variables
int distance;
int light;
main() {
while (true) {
distance = read_distance;
light = read_light;
if (task1_wantsToRun())
task1_run();
if (task2_wantsToRun())
task2_run();
}
}
há algumas coisas aqui; prioridade se torna irrelevante. Por mais agradável que pareça ter tarefas no robotC com prioridades, elas não são uma boa opção para implementação de subsunção na minha experiência. Por razões como, as prioridades nem sempre são respeitadas, as tarefas não podem ser interrompidas (às vezes); portanto, quando ocorrer um evento de prioridade mais alta, ele não reagirá como o esperado, o robotC só recentemente se tornou reentrante, portanto, coisas como acessar um sensor de mais de uma tarefa pode ser arriscada (problemas de tempo de I2C) e, em alguns casos, não é (sensores pesquisados automaticamente).
Você pode adicionar sua própria implementação de prioridade ao loop acima à medida que as coisas funcionam, mas isso realmente não é necessário para iniciar.
O seu comentário "// box the obstruction" descreve um comportamento balístico. Isso é um pouco complicado de implementar usando o multitarefa. O loop simples que usei torna muito mais fácil e melhor para iniciantes / aprendizado.
A outra coisa com que vou deixar você é que a subsunção, apesar de organizada e apropriada para muitas coisas, não é uma boa maneira de implementar o que é melhor feito tradicionalmente. De fato, a parte 'evade' pode ser um bom candidato à subsunção, mas honestamente sua outra tarefa deve ser chamada 'GoOnAboutYourBusiness'. Digo isso porque você provavelmente não deseja mudar de pesquisar para seguir com subsunção. Lidar com aqueles com loops de programação tradicionais. Com um único sensor, - a luz é mais escura ou mais clara do que era no último loop? se ficar mais escuro (assumindo a linha preta), continue girando na mesma direção; se ficar mais claro, vire para o outro lado; se permaneceu o mesmo, siga em frente. Você provavelmente precisará adicionar um PID e usar uma curva de direção em vez de virar à esquerda e à direita para ficar mais suave.
E sim, vários sensores ajudam. http://www.mindsensors.com/ - sim, atualmente sou eu no filme (11/10/2012)
Atualização: código real
Vou tentar isso daqui a pouco, mas ele compila e ilustra o que escrevi acima:
#pragma config(Sensor, S1, S_LIGHT, sensorLightActive)
#pragma config(Sensor, S2, S_DISTANCE, sensorSONAR)
#pragma config(Motor, motorB, LEFT, tmotorNXT, PIDControl, encoder)
#pragma config(Motor, motorC, RIGHT, tmotorNXT, PIDControl, encoder)
//*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
int distance_value, light_value;
bool evade_wantsToRun()
{
return distance_value < 30;
}
void evade_task()
{
// full stop
motor[LEFT] = 0;
// evade the object ballistically (ie in full control)
// turn left, drive
nSyncedTurnRatio = 0;
motor[LEFT] = -20;
Sleep(500);
nSyncedTurnRatio = 100;
Sleep(1000);
// turn right, drive
nSyncedTurnRatio = 0;
motor[LEFT] = 20;
Sleep(500);
nSyncedTurnRatio = 100;
Sleep(1000);
// turn right, drive
nSyncedTurnRatio = 0;
motor[LEFT] = 20;
Sleep(500);
nSyncedTurnRatio = 100;
Sleep(1000);
// turn left, resume
nSyncedTurnRatio = 0;
motor[LEFT] = 20;
Sleep(500);
motor[LEFT] = 0;
}
///////////////////////////////
void TurnBySteer(int d)
{
// normalize -100 100 to 0 200
nSyncedTurnRatio = d + 100;
}
///////////////////////////////
typedef enum programPhase { starting, searching, following, finished };
programPhase phase = starting;
// these 'tasks' are called from a loop, thus do not need to loop themselves
void initialize()
{
nSyncedTurnRatio = 50;
nSyncedMotors = synchBC;
motor[LEFT] = 30; // start a spiral drive
phase = searching;
}
void search()
{
if (light_value < 24)
{
nSyncedTurnRatio = 100;
phase = following;
}
}
int lastLight = -1;
int currentSteer = 0;
void follow()
{
// if it is solid white we have lost the line and must stop
// if lightSensors detects dark, we are on line
// if it got lighter, we are going more off line
// if it got darker we are headed in a good direction, slow down turn in anticipation
// +++PID will be even smoother
if (light_value > 64)
{
motor[LEFT] = 0;
phase = finished;
return;
}
if (light_value < 24)
currentSteer = 0;
else if (light_value > lastLight)
currentSteer += sgn(currentSteer) * 1;
else // implied (light_value < lastLight)
currentSteer -= sgn(currentSteer) * 1;
TurnBySteer(currentSteer);
}
bool regularProcessing_wantsToRun()
{
return phase != finished;
}
void regularProcessing_task()
{
switch (phase)
{
case starting:
initialize();
break;
case searching:
search();
break;
case following:
follow();
}
}
task main()
{
// subsumption tasks in priority oder
while (true)
{
// read sensors once per loop
distance_value = SensorValue[S_DISTANCE];
light_value = SensorValue[S_LIGHT];
if (evade_wantsToRun())
evade_task();
if (regularProcessing_wantsToRun())
regularProcessing_task();
else
StopAllTasks();
EndTimeSlice(); // give others a chance, but make it as short as possible
}
}
StartTask
, são a prioridade da tarefa? 9 será a maior prioridade? Nesse caso, não deveriafind
ter mais prioridade do quetrack
? De fato, a condição defind
e aelse
condição detrack
são as mesmas. Então, como humano, se o valor do sensor for maior que o limite, o que você faria? Vá em espiral ou gire para ajustar a linha?