kurze Antwort; Nein, Sie müssen die Dinge wirklich ganz anders machen.
lange unvollständige Antwort; Lassen Sie mich Ihnen einen für robotC geeigneten Pseudocode geben, der Sie auf einen besseren Weg bringt. Verwenden Sie zunächst keine Aufgaben - dies ist NICHT der Zweck von robotC-Aufgaben. Sie könnten zum Funktionieren gebracht werden, vielleicht, vielleicht auch nicht (und Sie müssen einige Änderungen vornehmen, um es überhaupt zu versuchen).
// 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();
}
}
hier gibt es ein paar Dinge; Priorität wird irrelevant. So schön es scheint, Aufgaben in robotC mit Prioritäten zu haben, sie sind meiner Erfahrung nach keine gute Wahl für die Implementierung von Subsumtionen. Aus Gründen wie Prioritäten werden Prioritäten nicht immer eingehalten, Aufgaben können (manchmal) nicht unterbrochen werden. Wenn also ein Ereignis mit höherer Priorität eintritt, reagiert es nicht wie erwartet. RobotC wurde erst kürzlich wieder eingeführt, sodass beispielsweise auf einen Sensor zugegriffen werden kann von mehr als einer Aufgabe kann riskant sein (I2C-Timing-Probleme), und in einigen Fällen ist dies nicht der Fall (automatisch abgefragte Sensoren).
Sie können der obigen Schleife Ihre eigene Prioritätsimplementierung hinzufügen, wenn die Dinge funktionieren, aber sie wird für Starts wirklich nicht benötigt.
Ihr Kommentar "// Box the Obstruction" beschreibt ein ballistisches Verhalten. Diese sind mit Multitasking etwas schwierig zu implementieren. Die einfache Schleife, die ich verwendet habe, macht es viel einfacher und besser für Anfänger / Lernen.
Die andere Sache, die ich Ihnen überlassen werde, ist, dass die Subsumtion, obwohl sie ordentlich und für viele Dinge angemessen ist, kein guter Weg ist, um das umzusetzen, was traditionell besser gemacht wird. In der Tat mag der Teil "Ausweichen" ein guter Kandidat für die Subsumtion sein, aber ehrlich gesagt sollte Ihre andere Aufgabe "GoOnAboutYourBusiness" heißen. Ich sage das, weil Sie wahrscheinlich nicht von der Suche zur Verfolgung mit Subsumtion wechseln möchten. Behandeln Sie diese mit herkömmlichen Programmierschleifen. - Wird bei einem einzelnen Sensor das Licht dunkler oder heller wahrgenommen als bei der letzten Schleife? Wenn es dunkler wird (unter der Annahme einer schwarzen Linie), drehen Sie weiter in die gleiche Richtung. Wenn es heller wird, drehen Sie sich in die andere Richtung. Wenn es gleich bleibt, fahren Sie geradeaus. Sie müssen wahrscheinlich etwas PID hinzufügen und eine Lenkkurve verwenden, anstatt nur nach links und rechts zu drehen, um glatter zu sein.
Und ja, mehrere Sensoren helfen. http://www.mindsensors.com/ - Ja, das bin ich derzeit im Film (10.11.2012)
Update: aktueller Code
Ich werde dies in Kürze ausprobieren, aber es kompiliert und illustriert, was ich oben geschrieben habe:
#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
, die Priorität der Aufgabe? Wird 9 die höchste Priorität haben? Sollte in diesem Fall nichtfind
mehr Priorität haben alstrack
? In der Tat sind der Zustand vonfind
und derelse
Zustand vontrack
gleich. Was würden Sie als Mensch tun, wenn der Sensorwert größer als der Schwellenwert ist? Auf Spirale gehen oder drehen, um die Linie anzupassen?