krótka odpowiedź; nie, naprawdę musisz robić rzeczy całkiem inaczej.
długa niepełna odpowiedź; Pozwól, że dam ci kod psuedo odpowiedni dla robota C, który stawia cię na lepszej ścieżce. Po pierwsze, nie używaj zadań - nie do tego służą zadania robotC. Można je zmusić do pracy, a może nie (i trzeba sporo zmian, aby spróbować).
// 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();
}
}
jest tu kilka rzeczy; priorytet staje się nieistotny. Choć wydaje się, że zadania w robocie C mają priorytety, wydaje się, że z mojego doświadczenia nie są dobrym wyborem do wdrożenia subskrypcji. Z powodów takich jak priorytety nie zawsze są honorowane, zadania nie mogą być przerywane (czasami), więc gdy wystąpi zdarzenie o wyższym priorytecie, nie zareaguje tak, jak się spodziewasz, robotC dopiero niedawno ponownie wszedł, więc rzeczy takie jak dostęp do czujnika od więcej niż jednego zadania może być ryzykowne (problemy z synchronizacją I2C), aw niektórych przypadkach nie jest (automatycznie odpytywane czujniki).
Możesz dodać własną implementację priorytetu do powyższej pętli, gdy zaczniesz działać, ale tak naprawdę nie jest potrzebna na początku.
Twój komentarz „// zakreśl przeszkodę” opisuje zachowanie balistyczne. Te są nieco trudne do wdrożenia przy użyciu wielozadaniowości. Prosta pętla, którą zastosowałem, sprawia, że jest to znacznie łatwiejsze i lepsze dla początkujących / uczących się.
Inną rzeczą, którą ci zostawiam, jest to, że zaspakajanie, chociaż jest schludne i odpowiednie dla wielu rzeczy, nie jest dobrym sposobem na wdrożenie tego, co lepiej zrobić tradycyjnie. Rzeczywiście część „unikania” może być dobrym kandydatem do subskrypcji, ale szczerze mówiąc, twoje inne zadanie powinno nazywać się „GoOnAboutYourBusiness”. Mówię to, ponieważ prawdopodobnie nie chcesz zmieniać z wyszukiwania na podążanie za subskrypcją. Obsługuj te z tradycyjnymi pętlami programowania. Za pomocą jednego czujnika - czy światło jest ciemniejsze lub jaśniejsze niż w ostatniej pętli? jeśli zrobiło się ciemniej (zakładając czarną linię), kontynuuj skręcanie w tym samym kierunku, jeśli stało się jaśniejsze, obróć w drugą stronę, jeśli pozostało to samo, idź prosto. Prawdopodobnie trzeba dodać PID i użyć krzywej sterowania zamiast po prostu skręcać w lewo i prawo, aby być płynniejszym.
I tak, wiele czujników pomaga. http://www.mindsensors.com/ - tak, to ja w filmie obecnie (11/10/2012)
Aktualizacja: aktualny kod
Wypróbuję to za chwilę, ale kompiluje i ilustruje to, co napisałem powyżej:
#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ą priorytetem zadania? Czy 9 będzie najwyższym priorytetem? W takim przypadku nie powinnofind
mieć większego priorytetu niżtrack
? W rzeczywistości stanfind
ielse
stantrack
są takie same. Więc jako człowiek, jeśli wartość czujnika jest większa niż próg, co byś zrobił? Iść spiralnie lub obrócić, aby ustawić linię?