respuesta corta; no, realmente necesitas hacer las cosas de manera bastante diferente.
respuesta larga e incompleta; Permíteme darte un código de psuedo apropiado para robotC, que te coloca en un mejor camino. Primero, no use tareas, esto NO es para lo que son las tareas robotC. Podrían hacer que funcionen, tal vez, tal vez no (y necesita bastantes cambios para intentarlo).
// 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();
}
}
hay un par de cosas aquí; La prioridad se vuelve irrelevante. Por agradable que parezca tener tareas en robotC con prioridades, en mi experiencia no son una buena opción para la implementación de subsunción. Por razones como, las prioridades no siempre se cumplen, las tareas no se pueden interrumpir (a veces), por lo que cuando se produce un evento de mayor prioridad, no va a reaccionar como se esperaba, robotC se volvió a ingresar recientemente, por lo que cosas como acceder a un sensor de más de 1 tarea puede ser arriesgado (problemas de sincronización I2C), y en algunos casos no lo es (sensores sondeados automáticamente).
Puede agregar su propia implementación prioritaria al bucle anterior a medida que las cosas funcionan, pero realmente no es necesario para comenzar.
Su comentario "// recuadro la obstrucción" describe un comportamiento balístico. Es un poco complicado implementarlo mediante la multitarea. El bucle simple que utilicé lo hace mucho más fácil y mejor para principiantes / aprendizaje.
La otra cosa con la que te dejaré es que la subsunción, aunque es ordenada y apropiada para muchas cosas, no es una buena manera de implementar lo que se hace mejor tradicionalmente. De hecho, la parte 'evadir' puede ser un buen candidato para la subsunción, pero, sinceramente, su otra tarea debería llamarse 'GoOnAboutYourBusiness'. Digo esto porque probablemente no quieras cambiar de búsqueda a seguimiento con subsunción. Manejar aquellos con bucles de programación tradicionales. Con un solo sensor, ¿la luz se siente más oscura o más clara que el último bucle? si se oscureció (suponiendo una línea negra) siga girando en la misma dirección, si se aclara, gire hacia el otro lado, si se mantuvo igual, siga recto. Probablemente necesite agregar algo de PID y usar una curva de dirección en lugar de simplemente girar a izquierda y derecha para ser más suave.
Y sí, múltiples sensores ayudan. http://www.mindsensors.com/ - sí, ese soy yo en la película actualmente (10/11/2012)
Actualización: código real
Probaré esto dentro de poco, pero compila e ilustra lo que escribí arriba:
#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
, ¿son la prioridad de la tarea? ¿9 va a ser la máxima prioridad? En ese caso, ¿no deberíafind
tener más prioridad quetrack
? De hecho, la condiciónfind
y laelse
condición detrack
son las mismas. Entonces, como humano, si el valor del sensor es mayor que el umbral, ¿qué harías? ¿Ir en espiral o girar para ajustar la línea?