NXC: повороты - практика программирования моторов



При задании сложных траекторий движения робота развороты и повороты - неотъемлемая часть программы. В этой статье будут рассматриваться способы, как программируются эти элементы движения с помощью функций и команд языка Not eXactly C рассмотренных ранее.

Пример 1. Поворот одним двигателем
На самом деле в этом примере рассматриваются два способа поворота одним двигателем.
В качестве входных данных для обоих способов, задается необходимость выполнения разворота вправо.

Итак, первый способ.
Поворот одним двигателем вправо. Ось вращения - правое колесо.

taskmain() { /* Робот крутится вправо до тех пор, пока расстояние до препятствия не станет меньше 20 см. Вращение происходит за счет того, что правый мотор (OUT_A) не двигается, а левый мотор (OUT_B) двигается вперед. Поэтому робот, как бы крутится вокруг правого колеса. */ SetSensorLowspeed(S1); Wait(100); //Вместо двух моторов, указываем только один. OnFwd(OUT_B, 50); until(SensorUS(S1) < 20); Off(OUT_AB);}

Второй способ –
Поворот вправо "задним ходом". Вращение вокруг левого колеса.

taskmain() { /* Робот крутится вправо до тех пор, пока расстояние до препятствия не станет меньше 20 см. Вращение происходит за счет движения правого мотора (OUT_А) назад, в то время как левый мотор (OUT_B) остается неподвижным. Поэтому робот, как бы пятится назад вокруг левого колеса. */ SetSensorLowspeed(S1); Wait(100); //Вместо двух моторов, указываем только один. //Мотор двигается назад. OnRev(OUT_A, 50); until(SensorUS(S1) < 20); Off(OUT_AB);}

Пример 2. Поворот двумя двигателями
Основной недостаток поворота одним двигателем - небольшая скорость: усилия одного двигателя направлены и на перемещение тележки и на преодоление силы сопротивления оказываемой неподвижным колесом. Поэтому, популярностью пользуется быстрый поворот вокруг своей оси (точнее ось вращения проходит между колесами).
В данном примере рассматривается поворот робота двумя двигателями влево.

taskmain() { /* Робот крутится влево до тех пор, пока расстояние до преграды не станет меньше 20 см. Вращение происходит за счет движения обеими моторами –     правый мотор двигается вперед, левый мотор двигается назад. За такое распределение движения между моторами отвечает третий параметр в     OnFwdSync(). */ SetSensorLowspeed(S1); Wait(100); //   Двигатели //      | мощность //      | | распределение нагрузки между моторами //      | | | OnFwdSync(OUT_AB, 50, -100); until(SensorUS(S1) < 20); Off(OUT_AB);}

Пример 3. Распределение мощности при управлении двумя двигателями
В прошлом примере вместе с функцией OnFwdSync() использовался параметр "распределение нагрузки между моторами". Этот параметр имеет смысл только тогда, когда происходит управление двумя двигателями. Он позволяет в одном числе выразить не только, насколько быстро будет крутиться один мотор относительно другого, но также и направление вращения.

taskmain() { SetSensorLowspeed(S1); Wait(100); /* Первым действием робот вращается влево, правое колесо крутится медленней левого. */ //     Двигатели //        | мощность //        | | угол поворота оси мотора в градусах //        | | | распределение движения между моторами //        | | | | синхронизация моторов //        |     | | | | включать торможение после //        | | | | | | окончания движения или //        | | | | | | останавливаться своим ходом RotateMotorEx(OUT_AB, 50, 360, -60, true, true); Wait(1000); /* Сейчас, робот вращается влево, правый мотор стоит, левый мотор двигается назад. */ RotateMotorEx(OUT_AB, 50, -360, -50, true, true); Wait(1000); /* Робот вращается влево двигаясь, правый мотор двигается быстрее левого. */ RotateMotorEx(OUT_AB, 50, 360, -25, true, true); Wait(1000); /* Робот двигается без поворотов, оба колеса двигаются одинаково назад. */ RotateMotorEx(OUT_AB, 50, -360, 0, true, true);}

Пример 4. Альтернативный поворот двумя двигателями
Предыдущий пример показал, что движение при использовании параметра "распределение нагрузки между моторами" по сути – работа двух двигателей с разной скоростью и разным направлением. Следовательно, его можно запрограммировать и без использования этого параметра.

taskmain() { /* Робот крутится влево до тех пор, пока расстояние до преграды не станет меньше 20 см. Вращение вокруг своей оси происходит без использования команд, которые принимают парамерт распределения движения между моторами. Заместо этого, используется знание того, что команды OnFwd/OnRev отдают управление следующим командам сразу после запуска моторов. Таким образом, сначала запускается один двигатель, потом сразу же запускается второй двигатель. Направление движения каждого двигателя и мощность, подаваемая на каждый из них, задают направление и форму поворота. */ SetSensorLowspeed(S1); Wait(100); //Правый мотор двигается вперед OnFwd(OUT_A, 50); //Левый мотор двигается назад с такой же мощностью как и правый. OnRev(OUT_B, 50); until(SensorUS(S1) < 20); Off(OUT_AB);}

Сортировка данных на NXT

   

В начале этой неделе я опубликовал вопрос: как в произвольном тексте найти 10 наиболее часто используемых слов? В программах для NXT обработка кучи данных с сенсоров является обыденным делом, но что если тебе надо узнать только 10 самых больших или маленьких значений? Как ты будешь решать этот вопрос? В языке RobotC нет специальных функций для сортировки; в NXC есть единственная ArraySort функция, упорядочивающая численные массивы по возрастанию. Поэтому в данной статье я решил провести небольшое исследование различных алгоритмов сортировки. Я помню эту классную демонстрацию работы алгоритмов, которая наглядно показывает различия в принципах сортировки. Я подумал, что будет реально здорово, если я сделаю тоже самое на NXC. И я сделал это.

 

Пузырьковая сортировка


Это первый алгоритм, который я реализовал, потому что я подумал, что он выглядит круто. Так как же он работает? Представьте себе кучу неупорядоченных данных и самый большой элемент "всплывает" наверх, подобно пузырьку воздуха в кипящей воде. Ты можешь сделать это, сравнивая попарно каждый элемент с последующим и меняя их местами, если они расположены в неправильной последовательности. Таким образом, за один "проход" массива наибольший элемент окажется в начале списка - первый "пузырек" всплыл. Эта процедура повторяется до тех пор, пока не "всплывут" все оставшиеся пузырьки - все элементы не будут отсортированы.
Код этого алгоритма довольно простой:

for(int i = 0; i < MAX_NUMBERS; i++){ for(int j = 0; j < (MAX_NUMBERS - 1); j++) { if (arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } }}

 

№ итерации            
Исходный массив 10 5 2 7 1 9
1 5 10 2 7 1 9
2 5 2 10 7 1 9
3 5 2 7 10 1 9
4 5 2 7 1 10 9
5 5 2 7 1 9 10
6 2 5 7 1 9 10
7 2 5 1 7 9 10
8 2 1 5 7 9 10
9 1 2 5 7 9 10

 

Единственным его недостатком является то, что он достаточно медленный. Его вычислительная сложность равна O(n2). Это означает, что при увеличении массива время работы алгоритма будет расти экспоненциально. Например, массив из 11 показаний сенсоров будет отсортирован на 20% медленнее, чем массив из 10 элементов, а обработка 50 замеров потребуют в 25 раз больше времени.

Сортировка вставками


Этот алгоритм сначала он сортирует два первых элемента массива. Затем алгоритм вставляет третий элемент в соответствующую порядку позицию по отношению к первым двум элементам. После этого он вставляет четвертый элемент в список из трех элементов. Таким образом, на каждом шаге новый элемент вставляется в нужную позицию в уже отсортированной части массива. Этот процесс повторяется до тех пор, пока не будут вставлены все элементы.

for (i = 1 ; i < MAX_NUMBERS ; i++ ){ for (j = 0 ; j < i ; j++ ) { if ( arr[j] > arr[i] ) { temp = arr[j] ; arr[j] = arr[i] ;       for (k = i ; k > j ; k-- ) {   arr[k] = arr[k - 1] ; } arr[k + 1] = temp ; } }}


В таблице ниже кроме самих итераций алгоритма я покажу, чему равнялась переменная temp.

№ итерации             temp
Исходный массив 10 5 2 7 1 9 -
1 5 5 2 7 1 9 10
2 5 10 2 7 1 9 -
3 2 10 10 7 1 9 5
4 2 2 10 7 1 9 5
5 2 5 10 7 1 9 -
6 2 5 7 7 1 9 10
7 2 5 7 10 1 9 -
8 1 5 7 10 10 9 2
9 1 5 7 7 10 9 2
10 1 5 5 7 10 9 2
11 1 1 5 7 10 9 2
12 1 2 5 7 10 9 -
13 1 2 5 7 9 9 10
14 1 2 5 7 9 10  

Сортировка Шелла


Сортировка Шелла является модификацией алгоритма сортировки вставками. Разница вот в чем: вместо того, чтобы сравнивать соседние элементы, как в сортировке пузырьком, сортировка Шелла несколько раз сравнивает элементы, находящиеся на определенном расстоянии друг от друга (зададим расстояние буквой m). Это расстояние равняется половине размера входного массива и на каждой последующей итерации m уменьшается вдвое.

В нашем примере сначала будут сортироваться между собой элементы, отстоящие друг от друга на расстоянии 3 элемента (6 / 2 = 3), а затем на расстоянии 1-го элемента (3 / 2 = 1 - целочисленное деление).

 

for(m = MAX_NUMBERS/2 ; m > 0; m /= 2){ for(j = m; j < MAX_NUMBERS; j++) { for(i = j - m; i >= 0; i -= m) { if(arr[i + m] >= arr[i])   break; else {   mid = arr[i];   arr[i] = arr[i + m];   arr[i + m] = mid; } } }}


В таблице ниже вы можете увидеть, как это работает:

№ итерации            
Исходный массив 10 5 2 7 1 9
1 7 5 2 10 1 9
2 7 1 2 10 5 9
3 1 7 2 10 5 9
4 1 2 7 10 5 9
5 1 2 7 5 10 9
6 1 2 5 7 10 9
7 1 2 5 7 9 10

 


Дата добавления: 2018-05-12; просмотров: 362; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!