Сегодня мы решим еще две задачки из нашего онлайн-задачника . Мы подготовили инструкцию по сборке робота , способного выполнить предложенные задания и публикуем исходные тексты программ для каждой из задач .
В первой задаче наш робот будет объезжать препятствия на линии и возвращаться на нее для продолжения движения.
Решение задачи на языке NXC:
float x,d,speed,es,D1,D2,e,u,PD,Pk;
task main()
{
// инициализация датчиков
SetSensorLight(IN_2);
SetSensorLight(IN_3);
SetSensorLowspeed(IN_4);
// размер колеи
x = 180;
// диаметр колес
d = 43.2;
// средняя скорость
speed = 30;
// "старая" ошибка Д-регулятора
es = 0;
// пропорциональный коэф-т
Pk = 2;
// дифференциальный коэф-т
PD = 4;
// сбрасываем энкодеры
ResetRotationCount(OUT_BС);
while(true)
{
// движемся по линии пока не обнаружим препятствие
while(SensorUS(IN_4) > 28)
{
// показания датчиков линии
D1 = Sensor(IN_2);
D2 = Sensor(IN_3);
// ошибка регулятора
e = D2-D1;
// управляющее воздействие
u = e*Pk+PD*(e-es);
// подаем его на моторы
OnFwd(OUT_B,u+speed);
OnFwd(OUT_C,-u+speed);
// сохраняем ошибка для Д-регулятора
es = e;
}
// моторы - стоп
Off(OUT_BC);
// поворот в сторону внутреннего изгиба трассы
if (MotorRotationCount(OUT_B)>MotorRotationCount(OUT_C))
{
RotateMotorEx(OUT_BC, speed, x/d*52, -100, true, true);
}
else
{
RotateMotorEx(OUT_BC, speed, x/d*52, 100, true, true);
}
Wait(500);
// съезжаем с линии
RotateMotorEx(OUT_BC, speed, 1000, 0, true, true);
// поворот в сторону линии
if (MotorRotationCount(OUT_B)<MotorRotationCount(OUT_C))
{
RotateMotorEx(OUT_BC, speed, x/d*52, -100, true, true);
OnRev(OUT_B,-18);
OnRev(OUT_C,-15);
}
else
{
RotateMotorEx(OUT_BC, speed, x/d*52, 100, true, true);
OnRev(OUT_B,-15);
OnRev(OUT_C,-18);
}
Wait(500);
// едем до линии
while(Sensor(IN_3) >= 46 && Sensor(IN_2) >= 44)
{
if (Sensor(IN_3)<=46)
{
Off(OUT_C);
}
if(Sensor(IN_2)<=44)
{
Off(OUT_B);
}
}
Off(OUT_BC);
Wait(1000);
// пересекаем линию
RotateMotorEx(OUT_BC, 25, 200, 0, true, true);
Wait(1000);
// разворот для продолжения движения по линии
if (MotorRotationCount(OUT_B)>MotorRotationCount(OUT_C))
{
RotateMotorEx(OUT_BC, 25, x/d*90, -100, true, true);
}
else
{
RotateMotorEx(OUT_BC, 25, x/d*30, 100, true, true);
}
}
}
Во второй задаче у нас будет целых два робота. Первый будет двигаться по линии постоянно изменяя скорость своего движения. Второй робот будет его догонять, стараясь двигаться с одинаковой с ним скоростью. Два раза в минуту роботы меняются ролями.
float speed,es,D1,D2,e,u,PD,Pk,speednew1,speednew2;
long time1,time2,time3;
float es1,PD1,PD2,D,es2,e2,e1,u1,u2,Pk1,Pk2;x,d;y;
bool t,r;
int robot;
task main()
{
// инициализация дальномера
SetSensorLowspeed(IN_4);
// направление синхронного разворота
r = true;
// номер робота 1 или 2
robot = 1;
// у нас в роботах разные датчики, поэтому разная инициализация
if(robot == 2)
{
SetSensorLight(IN_2);
SetSensorLight(IN_3);
// один робот будет убегать
t = true;
}
else
{
SetSensorColorRed(IN_2);
SetSensorColorRed(IN_3);
// другой робот будет догонять
t = false;
}
while(true)
{
// размер колеи
x = 180;
// диаметр колес, мм
d = 43.2;
if (t == true)
{
// таймер для синхронного разворота
time2 = CurrentTick();
// таймер для периодической смены скорости
time1 = CurrentTick();
// первые 2 секунды робот равняется, вперед не едет
speed = 0;
// "старая" ошибка Д-регулятора
es = 0;
// пропорциональный коэф-т
Pk = 2;
// дифференциальный коэф-т
PD = 4;
// таймер для 2-секундного выравнивания перед началом движения
time3 = CurrentTick();
// запоминаем, было ли уже выравнивание
y = 0;
// фактическая средняя скорость
speednew1 = 0;
while(true)
{
// через две секунды начинаем движение после выравнивания
if(CurrentTick() > time3+2000 && y == 0)
{
speednew1 = speed + Random(80);
y = 1;
}
// смена ролей между роботами каждые 29 секунд
if(CurrentTick() > time2+29000)
{
break;
}
// каждые 5 секунд смена скорости
if(CurrentTick() > time1+5000)
{
speednew1 = speed + Random(80);
time1 = CurrentTick();
}
// показания датчиков
D1 = Sensor(IN_3);
D2 = Sensor(IN_2);
// ошибка регулятора
e = D2-D1;
// управляющее воздействие ПД-регулятора
u = e*Pk+PD*(e-es);
// подаем его на моторы
OnFwd(OUT_B,u+speednew1);
OnFwd(OUT_C,-u+speednew1);
// запоминаем ошибку для Д-регулятора
es = e;
}
// моторы - стоп
Off(OUT_BC);
Wait(1000);
// смена ролей - разворот
if (r == true) RotateMotorEx(OUT_BC, 30, x/d*150, 100, true, true);
else RotateMotorEx(OUT_BC, 30, x/d*150, -100, true, true);
Wait(1000);
t = !t;
r = !r;
}
else
{
time2 = CurrentTick();
time3 = CurrentTick();
speed = 0;
es1 = 0;
PD1 = 0;
Pk1 = 2.5;
es2 = 0;
Pk2 = 2;
PD2 = 6;
y = 0;
while(true)
{
if(CurrentTick()> time3+2000 && y == 0)
{
speed = 50;
y = 1;
}
if(CurrentTick() > time2+29000)
{
break;
}
D = SensorUS(IN_4);
D2 = Sensor(IN_2);
D1 = Sensor(IN_3);
// ограничиваем зону видимости робота - 60 см
if (D > 60)
{
D = 60;
}
// здесь у нас целых два регулятора
// один ведет по линии
// второй - подстраивает скорость движения
e2 = D2 - D1;
e1 = D - 40;
u2 = e2*Pk2+PD2*(e2-es2);
u1 = e1*Pk1+PD1*(e1-es1);
OnFwd(OUT_B,speed+u1+u2);
OnFwd(OUT_C,speed+u1-u2);
es1 = e1;
es2 = e2;
}
Off(OUT_BC);
Wait(1000);
// смена ролей - разворот
if (r == true) RotateMotorEx(OUT_BC, 30, x/d*150, 100, true, true);
else RotateMotorEx(OUT_BC, 30, x/d*150, -100, true, true);
Wait(1000);
t = !t;
r = !r;
}
}
}
На видео можно посмотреть как роботы решают эти задачи:
VIDEO