réponse courte; non, vous devez vraiment faire les choses un peu différemment.
réponse longue et incomplète; Permettez-moi de vous donner un code pseudo approprié pour robotC, qui vous met sur une meilleure voie. Tout d'abord, n'utilisez pas de tâches - ce n'est PAS à cela que servent les tâches robotC. Ils pourraient être faits pour fonctionner, peut-être, peut-être pas (et vous avez besoin de quelques changements pour même essayer).
// 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();
}
}
il y a deux ou trois choses ici; la priorité devient inutile. Aussi agréable qu'il semble avoir des tâches dans robotC avec des priorités, elles ne sont pas un bon choix pour la mise en œuvre de subsomption selon mon expérience. Pour des raisons comme, les priorités ne sont pas toujours respectées, les tâches ne peuvent pas être interrompues (parfois), donc lorsqu'un événement de priorité plus élevée se produit, il ne réagira pas comme vous vous y attendez, robotC n'est que récemment rentré, donc des choses comme l'accès à un capteur de plus d'une tâche peut être risqué (problèmes de synchronisation I2C), et dans certains cas, ce n'est pas le cas (capteurs interrogés automatiquement).
Vous pouvez ajouter votre propre implémentation prioritaire à la boucle ci-dessus au fur et à mesure que les choses fonctionnent, mais elle n'est vraiment pas nécessaire pour les démarrages.
Votre commentaire "// box the obstruction" décrit un comportement balistique. Celles-ci sont un peu délicates à mettre en œuvre en utilisant le multitâche. La boucle simple que j'ai utilisée le rend beaucoup plus facile et meilleur pour les débutants / l'apprentissage.
L'autre chose que je vais vous laisser, c'est que la subsomption tout en étant soignée et appropriée pour beaucoup de choses, n'est pas un bon moyen de mettre en œuvre ce qui est mieux fait traditionnellement. En effet, la partie «éluder» peut être un bon candidat pour la subsomption, mais honnêtement, votre autre tâche devrait être appelée «GoOnAboutYourBusiness». Je dis cela parce que vous ne voulez probablement pas passer de la recherche au suivi avec subsomption. Gérez ceux avec des boucles de programmation traditionnelles. Avec un seul capteur, - la lumière est-elle plus sombre ou plus claire que la dernière boucle? s'il est devenu plus sombre (en supposant une ligne noire) continuez à tourner dans la même direction, s'il est devenu plus clair, tournez dans le sens inverse, s'il est resté le même, continuez tout droit. Vous devrez probablement ajouter un PID et utiliser une courbe de direction au lieu de simplement tourner à gauche et à droite pour être plus fluide.
Et oui, plusieurs capteurs aident. http://www.mindsensors.com/ - ouais, c'est moi dans le film actuellement (11/10/2012)
Mise à jour: code réel
Je vais essayer cela dans un petit moment, mais il compile et illustre ce que j'ai écrit ci-dessus:
#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
sont-ils la priorité de la tâche? Est-ce que 9 va être la plus haute priorité? Dans ce cas, ne devrait pasfind
avoir plus de priorité quetrack
? En fait, la condition defind
et laelse
condition detrack
sont les mêmes. Donc, en tant qu'être humain, si la valeur du capteur est supérieure au seuil, que feriez-vous? Aller en spirale ou tourner pour ajuster la ligne?