risposta breve; no, devi davvero fare le cose in modo leggermente diverso.
lunga risposta incompleta; Lascia che ti dia un codice psuedo appropriato per robotC, che ti mette su una strada migliore. Innanzitutto, non utilizzare le attività: questo NON è lo scopo delle attività robotC. Potrebbero essere fatti funzionare, forse, forse no (e hai bisogno di alcune modifiche anche solo per provare).
// 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();
}
}
ci sono un paio di cose qui; la priorità diventa irrilevante. Per quanto sembri avere compiti in robotC con priorità, non sono una buona scelta per l'implementazione di sussidi nella mia esperienza. Per motivi come, le priorità non sono sempre rispettate, le attività non possono essere interrotte (a volte), quindi quando si verifica un evento con priorità più elevata, non reagirà come previsto, robotC solo di recente è rientrato, quindi cose come l'accesso a un sensore da più di 1 attività può essere rischiosa (problemi di temporizzazione I2C) e in alcuni casi non lo è (sensori con polling automatico).
Puoi aggiungere la tua implementazione prioritaria al ciclo sopra mentre fai funzionare le cose, ma in realtà non è necessario per iniziare.
Il tuo commento "// inscatola l'ostruzione" descrive un comportamento balistico. Questi sono un po 'difficili da implementare utilizzando il multi-tasking. Il semplice ciclo che ho usato lo rende molto più semplice e migliore per i principianti / l'apprendimento.
L'altra cosa che ti lascerò, è che la sussunzione, pur essendo ordinata e appropriata per molte cose, non è un buon modo per attuare ciò che è meglio fare tradizionalmente. In effetti, la parte "eludere" può essere un buon candidato per l'assunzione, ma onestamente l'altro tuo compito dovrebbe essere chiamato "GoOnAboutYourBusiness". Dico questo perché probabilmente non vuoi cambiare dalla ricerca al seguire con la sussunzione. Gestisci quelli con i tradizionali loop di programmazione. Con un singolo sensore, - la luce rilevata è più scura o più chiara dell'ultimo ciclo? se è diventato più scuro (supponendo che la linea nera) continui a girare nella stessa direzione, se è diventato più chiaro, gira dall'altra parte, se è rimasto lo stesso, vai dritto. Probabilmente devi aggiungere un po 'di PID e usare una curva di sterzo invece di girare a sinistra e a destra per essere più fluido.
E sì, più sensori aiutano. http://www.mindsensors.com/ - sì, sono io nel film attualmente (11/10/2012)
Aggiornamento: codice attuale
Lo proverò tra poco, ma compila e illustra ciò che ho scritto sopra:
#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
, sono la priorità dell'attività? 9 avrà la massima priorità? In tal caso, non dovrebbefind
avere più priorità ditrack
? In effetti, la condizionefind
e laelse
condizione ditrack
sono le stesse. Quindi, come essere umano, se il valore del sensore è maggiore della soglia, cosa faresti? Vai a spirale o gira per regolare la linea?