краткий ответ; нет, тебе действительно нужно делать что-то немного по-другому.
длинный неполный ответ; Позвольте мне дать вам некоторый код psuedo, подходящий для robotC, который поможет вам выбрать лучший путь. Во-первых, не используйте задачи - это НЕ то, для чего предназначены задачи robotC. Их можно заставить работать, а может, и нет (и вам нужно немало изменений, чтобы даже попробовать).
// 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();
}
}
здесь есть пара вещей; приоритет становится неактуальным. Как бы хорошо ни казалось, что у robotC есть задачи с приоритетами, они, по моему опыту, не являются хорошим выбором для реализации подгруппы. По таким причинам, как приоритеты не всегда соблюдаются, задачи не могут быть прерваны (иногда), поэтому, когда происходит событие с более высоким приоритетом, оно не будет реагировать так, как вы ожидаете, robotC только недавно стал повторно входящим, поэтому такие вещи, как доступ к датчику от более чем одной задачи может быть рискованно (проблемы синхронизации I2C), а в некоторых случаях это не так (датчики автоматически опрашиваются).
Вы можете добавить свою собственную реализацию приоритетов в вышеупомянутый цикл, как только все заработает, но это действительно не нужно для запуска.
Ваш комментарий "// помечаю препятствие" описывает баллистическое поведение. Это немного сложно реализовать с помощью многозадачности. Простой цикл, который я использовал, делает его намного проще и лучше для начинающих / обучения.
Еще одна вещь, с которой я вас оставлю, - это то, что потребление, будучи аккуратным и подходящим для многих вещей, не является хорошим способом реализовать то, что лучше сделать традиционно. В самом деле, часть «уклониться» может быть хорошим кандидатом для включения в категорию, но, честно говоря, ваша другая задача должна называться «GoOnAboutYourBusiness». Я говорю это потому, что вы, вероятно, не хотите переходить от поиска к следующему с подпоправкой. Обработайте их с помощью традиционных циклов программирования. С одним датчиком, - воспринимается ли свет темнее или светлее, чем это было в прошлом цикле? если он стал темнее (предполагается черная линия), продолжайте поворачивать в том же направлении, если он стал светлее, поверните в другую сторону, если он остался прежним, идите прямо. Вам, вероятно, нужно добавить PID и использовать кривую поворота вместо того, чтобы просто поворачивать влево и вправо, чтобы быть более плавным.
И да, несколько датчиков помогают. http://www.mindsensors.com/ - да, это я в фильме в настоящее время (10/10/2012)
Обновление: актуальный код
Я попробую это через некоторое время, но это компилирует и иллюстрирует то, что я написал выше:
#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, являются ли они приоритетом задачи? 9 будет наивысшим приоритетом? В таком случае не должноfindбыть больше приоритета, чемtrack? На самом деле, состояниеfindиelseсостояниеtrackодинаковы. Итак, как человек, если бы значение датчика превышало пороговое значение, что бы вы сделали? Идти по спирали или повернуть, чтобы отрегулировать линию?