Технический форум по робототехнике.
Scorpio » 22 ноя 2016, 05:24
Имеется в виду правильная организация программы на ПК на языке высокого уровня (но не каком-то специальном).
Конкретный пример: ПК управляет манипулятором через СОМ порт. Дает команду переместить манипулятор, дожидается от него подтверждения, что движение закончено, задает следующее движение (Взять деталь - перенести на новое место - повернуть - положить и т.д.) Также могут возникнуть дополнительные события (например нажата кнопка "отмена"), которые должны прервать текущее действие и перейти на другую ветку сценария. Например, при отмене действия, манипулятор должен свернуться в исходное положение. Но, если он уже успел взять деталь, то должен прежде вернуть ее на место.
Я всегда делал так:
- Циклические операции манипулятора помещал в функцию "сценарий", в которой был набор действий, выбираемых по
swich(Step){case 1: {} case 2: {}…..}
- При очередном событии (в основном приход данных в СОМ порт) менял номер шага Step и однократно выполнял эту функцию.
Когда это простая итерация, то все достаточно удобно и наглядно. Но, когда возникают события, требующее свернуть с прямого пути, появляется куча запутанной логики, в которой мне самому даже сложно разобраться, спустя время.
Как это делается вообще?
Dmitry__ » 22 ноя 2016, 06:12
Scorpio писал(а):Как это делается вообще?
Использовать то самое страшное слово - goto. Без вариантов
![Smile :)](http://roboforum.ru/images/smilies/smile.gif)
Для наглядности можно таблицей переходов. Еще можно делать как обработчик ошибок:
Пример на vb6:
On Local Error 'включить слежение
On Local Error Resume Next 'вернуться в код в место за возник. ошибкой
On Error GoTo 0 'выкл. слежение за ошибками
А называется это все - "мои программы стали сложнее, а я более асинхронным"
Добавлено спустя 3 минуты 25 секунд:Абзац: Обработка ошибок
https://habrahabr.ru/post/175947/
Scorpio » 22 ноя 2016, 07:30
Да, может быть. Работает, конечно, и так, как у меня. Но код трудночитаемый. Я тут достал из чулана своего манипулятора, который
в шашки играет. Да бы переписать его под ардуино (был на лего) и современную винду. А потом может продать по цене запчастей с исходниками, т.к. "роботы должны служить людям". Посмотрел свой код. Ни хрена не понять сразу. Сумбурно как-то куча флагов, блокировок в разных местах. Разобрался в конце концов, но кучу времени убил. Хочется красиво как-то написать, чтобы самому приятно смотреть было.
Dmitry__ » 22 ноя 2016, 15:46
Scorpio писал(а):Работает, конечно, и так, как у меня. Но код трудночитаемый.
Код всегда трудночитаемый, после длительной паузы. Про чужой код вообще молчу.
Scorpio писал(а):Хочется красиво как-то написать, чтобы самому приятно смотреть было.
Только обильное количество комментариев в коде. Не придумали еще такой язык, который было бы сразу красиво и понятно.
Можно попробовать разные парадигмы, например обьектно-ориентированный. Создаешь обьекты с определенными функциями/свойствами и управляешь только этими свойствами. Такой способ дробит сложность понимания на более мелкие изолированные. Но это все только пробы пера человечества. Мы находимся на самой низшей ступени программирования
![Smile :)](http://roboforum.ru/images/smilies/smile.gif)
Вспомни, еще 20 лет назад в обьяснялках на си был пункт - быстрое набивание кода, сокращенные символы, всякие !||={[* и ТОННЫ скобочек (((((((*)))))))) . Теперь про это не вспоминают, ибо любой редактор умеет копипастить.
Повторюсь - подробные комменты - лучший путеводитель по своему коду. Я например, иногда специально перестаю писать комменты - привязываю к себе клиента. Никакой бит секретности не нужен. Быдлокод - лучшая защита от не стрессоустойчивого хакера.
Scorpio » 22 ноя 2016, 19:03
Dmitry__ писал(а): Мы находимся на самой низшей ступени программирования
![Smile :)](http://roboforum.ru/images/smilies/smile.gif)
Во во. Но, если ты уже на низшей,то я еще выглядываю со дна подвала
![Smile :)](http://roboforum.ru/images/smilies/smile.gif)
И все же должна быть какая-то общая концепция написания сценариев асинхронного управления роботом. Для робота - шашиста это не столь актуально, т.к. он достаточно простой. Мало событий и ветвлений. У какого-нибудь сервисного робота их будет в сотни раз больше. Т.е. имеем в одной руке кучу событий, в другой - кучу действий. Теперь надо описать логические связи, чтобы глядя на код можно было бы представить весь процесс. Ну и коменты, конечно.
Dmitry__ » 22 ноя 2016, 20:10
Кста, в кьюте есть слоты, сигналы и коннекты: Можно делать связи между событиями и функциями. Как раз асинхронное программирование. Удобная штука, можно в графич. режиме соединять проводочки, можно описывать в текстовом файле:
- Код: Выделить всё • Развернуть
connect(spinBox_Test, SIGNAL(valueChanged(int)), horizScrollBar_Test, SLOT(setValue(int)));
connect(spinBox_Scaling, SIGNAL(valueChanged(int)), horizScrollBar_Scaling, SLOT(setValue(int)));
connect(spinBox_PositLimitMax, SIGNAL(valueChanged(int)), horizSlider_PositLimitMax, SLOT(setValue(int)));
https://habrahabr.ru/post/50812/
SkyStorm » 22 ноя 2016, 20:26
Есть такая штука как Конечные автоматы и Машина состояний.
В простейшем случае для Ардуино это может быть CASE.
Обычно у роботов - не так много состояний и они легко описываются.
Виктор Казаринов » 22 ноя 2016, 21:05
Да, SkyStorm прав, если робот имеет не очень большое количество внутренних состояний, то можно использовать автоматный стиль программирования:
https://en.wikipedia.org/wiki/Automata-based_programming
Dmitry__ » 22 ноя 2016, 22:18
Ну это совсем просто, думаю этот порог и был преодолен.
Scorpio » 22 ноя 2016, 22:21
Угу. "Существуют также предложения по использованию автоматного программирования в качестве универсального подхода к созданию компьютерных программ вне зависимости от предметной области."
В свое время, когда я развлекался с "Ванессой", я помню собирался придумать для нее собственный язык сценариев под ее API, основанный на следующих принципах:
- любые повторяющиеся действия описываются в виде "секвенций" - последовательностей шагов, которые могут включать в себя субсеквенции,
- каждая секвенция имеет набор условий для ее запуска, а каждый шаг - условия перехода на следующий шаг,
- единовременно может выполняться лишь одна секвенция.
- выполнение секвенции до ее окончания м.б. прервано при запуске другой секвенции, имеющей высший приоритет над выполняемой.
Потом решил не тратить на это время, и писать сценарии прямо в программе. Но,... получилось все совсем не так просто и красиво, как задумывалось.
Так вот. Описаный выше принцип последовательностей, предполагает, что в конце каждого шага, программа взводит некий флаг, и запускает бесконечный цикл ожидания. Сигнал (событие) сбрасывает флаг и разрешает идти дальше.
Другой подход, как я писал в первом посте, что программа не висит в цикле. А при возникновении события, сигнал запускает какой-либо шаг, в зависимости от условий. Что технически тоже самое, но первый способ смотрибельнее. Какой из них более правильный?
smur » 22 ноя 2016, 22:31
Делая робота удалённого присутствия Rasp+Ardu (в качестве хобби и за маленькой дочкой присматривать, когда она одна остаётся дома) стал путаться в логике построения программы (команды по WEB + автоматич. движение + коррекция итп) даже рисуя сначала алгоритмы (до этого делал маленьких роботов для поиска выхода из лабиринта и проч. несложных). В итоге отыскал на просторах интернета тему конечных автоматов (как цель - построение автоматизированных объектов управления). Сейчас изучаю и пытаюсь применить на практике. Этот подход позволяет подходить к проблеме уже осмысленно, тк есть серьёзная теоретическая база. Состояний может быть много. Но есть управляющие состояния (лучше мало) и вычислительные состояния (сколько угодно) дело в подходе и грамотной декомпозиции, см. материалы
http://is.ifmo.ru/works/tech_aut_progДля ознакомления советую прочитать на этом сайте:
Автоматное программирование и робототехника.pdf
Далее хороший материал:
Автоматное программирование.pdf
Санкт-Петербургский государственный университет
Информационных технологий, механики и оптики
Кафедра «Компьютерные технологии»
Н. И. Поликарпова, А. А. Шалыто
Dmitry__ » 23 ноя 2016, 00:49
Scorpio писал(а): А при возникновении события, сигнал запускает какой-либо шаг, в зависимости от условий. Что технически тоже самое, но первый способ смотрибельнее. Какой из них более правильный?
Естественно более правильный второй способ, сложные программы должны быть только событийными. Иначе будет как в ссылке на вики, одни блокировки while:
- Код: Выделить всё • Развернуть
do {
do
c = getchar();
while(c == ' ');
while(c != EOF && !isspace(c) && c != '\n') {
putchar(c);
c = getchar();
}
putchar('\n');
while(c != EOF && c != '\n')
c = getchar();
} while(c != EOF);
return 0;
Оно конечно красивее, но абсолютно нерабочее в сложной программе, т.к. такие блокировки не позволят написать код, адекватно реагирующий на внешние события. Будет как кино с заморозкой кадра для подгрузки буфера:)
Отсюда вырисовывается очередная парадигма - Событийно-ориентированное программирование.
Добавлено спустя 6 минут 56 секунд:Кста, когда пишется начальный код, часто используются всякие Wait, но когда программа начинает обретать функциональность, подключаются и настраиваются всякие аппаратные таймеры, то все эти Wait должны быть полностью исключены из кода. Концепция задержек полностью меняется, соотв. меняется и стиль программирования.
Вообще, любое зацикливание в коде - моветон, разрешено только ардуинщикам
![Smile :)](http://roboforum.ru/images/smilies/smile.gif)
Angel71 » 23 ноя 2016, 00:51
да никакой не правильней - вариантов море и всё зависит от того, что именно вам проще в реализации и понимании.
можно и на конечном автомате, совсем простенькое на кейсах или небольшую библиотеку написать/найти (много гуглится по "fsm arduino"). при необходимости события и "чёрная доска" для хранения данных вполне прикручиваемые.
сдались вам эти количества состояний, сами по себе они проблемы не представляют. с сотнями и более всё может быть просто и наглядно, а может уже и на паре десятков попытка реализации будет жуткой мукой с кучей костылей, а от мысли что нужно внести небольшие изменения в логику работы у вас волосы дыбом становится будут от ужаса. немного возможности языка, железо, на котором это работает и прочие мелочи. а сильно влияет, допустим связанность состояний - какая логика работы, т.е. как из каких состояний переключается в другие. сейчас вот эта переменная такая, а в этой такое значение, значит нам нужно сделать то-то и то-то (оно же может быть выделено в ещё одно состояние) и переключиться вот в такое состояние. для шахмат главное продумать реализацию и особых проблем с машиной состояний быть не должно, хотя в любом случае машину состояний использовать лучше или смешивая с другими подходами или когда совсем всё простенькое, иначе очень легко и быстро это может превратиться в жуткие костыли на костылях и неоправданно большие затраты на реализацию. если прям машина состояний и была реализована, нужно хорошенько подумать ещё раз над реализацией и может вы поймёте как всё переделать что бы стало проще и наглядней.
из простого ещё есть поведенческие деревья, с ними чуть больше возни с реализацией кода деревьев, зато потом чуть проще в реализации логики. последовательности действий делаются элементарно, можно даже с такими вещами, как случайный порядок выполнения последовательности. при реализации чуть проще будет, если в языке есть yield. как и с машиной состояний, к деревьям можно черную доску, события и прочие такие вещи делать. и не обязательно в чистом виде реализовывать, можно совмещать с другими подходами и/или немного расширять, допустим вводя параллельные ветки выполнения и прерыватели.
ещё есть goap и куча других подходов, но вроде о них пока рано.
с вэйтами эт просто не нужно в лоб в спячку мк отправлять или в цикле крутиться и будет всё хорошо. вообще есть подозрение, что вы всё в лоб реализуете. почитайте что такое yield, если в используемом языке его нет или он по каким-то причинам не подходит, что-то подобное можно на указателях делать.
SkyStorm » 23 ноя 2016, 01:24
Прочитал текст последнего сообщения - по результатам бан на сутки за многократное нарушение 5.1.8.
Scorpio » 23 ноя 2016, 01:26
Речь всеже идет о программе на ПК под винду, а не на дуне. Бесконечные циклы страшны лишь психологически, если они не вешают намертво свой процесс, а разрешают события. Любая программа - это бесконечный цикл. Если приложение вывело свое окно и ждет клика, то программа понятное дело не стоит, а продолжает крутиться. Даже в "большой" программе управления роботом с ПК не обойтись без пауз, которые по сути теже циклы. Зато, когда читаешь код, явно видишь: тут начало, тут мы ждем, тут идем дальше. Так что насчет событийного подхода - не уверен, хотя сам сейчас пользуюсь именно им.
Статья по ссылке smur понравилась. Видимо правильно придерживаться стиля автоматного программирования.
Т.к. я еще только учусь писать серьезные программы для роботов, хотелось бы научиться сразу правильно.