краткий ответ; нет, тебе действительно нужно делать что-то немного по-другому.
длинный неполный ответ; Позвольте мне дать вам некоторый код 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
одинаковы. Итак, как человек, если бы значение датчика превышало пороговое значение, что бы вы сделали? Идти по спирали или повернуть, чтобы отрегулировать линию?