Использование автоматного програмирования на примере Quantum Leaps. Вступление.


Года три назад устроился я програмистом микроконтроллеров на одну фирму, и там мне мой руководитель предложил разобраться с так называемым автоматным программированием. Но не просто с методом, а поставил задачу освоить framework Quantum Leaps.
С данной задачей я справился, но этот фреймворк мне настолько понравился, что я решил поделится своим опытом использования с общественностью.
Итак, что же такое Quantum Leaps. Это набор из трёх фреймворков с открытым исходным кодом, позволяющий быстро написать готовый продукт. Почему набор? Потому как есть реализация на С (QP/C), на С++ (QP/C++), и отдельная очень компактная реализация на С(QP-nano). Каждый из этих фреймворков представляет из себя платформо-компиляторо-независимый код, так называемый QP™ Baseline Code.
Для адаптации под конкретную архитектуру и компилятор используются различные QP™ Development Kits(QDK). На этой страничке доступны для скачивания как базовый код всех трёх вариантов фреймворка, так и большой набор Development Kits под различные архитектуры и компиляторы.
На этой же страничке можно скачать QP Modeler(QM), очень полезная програмка! Я ждал её с тех пор, как разобрался с QP. Позволяет графически нарисовать диаграмму состояний и по ней сгенерировать код, это если кратко.
Ну и отдельный плюс данного фреймворка — это большая книга по автоматному программированию на C/C++ на примере QP от его создателя, доступная для скачивания здесь(.pdf 4МБ).
Приятной особеностью QP является возможность работать поверх любой операционки, от Windows до какой-то экзотики для AVR. Но этот вопрос оставим на потом, когда будем с QP на «ты».
Итак, с чего же начать. А начнём пожалуй с попытки объяснить как это всё работает.
Скажу сразу, так как я в основном пишу на С++, то и все примеры я буду приводить на «плюсах».
Как и любая реализация многозадачности QP имеет в своём составе диспетчер задач, либо вытесняющий(QK) либо нет(Vanilla). По своей сути это бесконечный цикл, в котором проверяется наличие событий для определённого автомата, которые ему необходимо обработать. Если событий нет, можно уйти в спячку до возникновения оного.
Событие(QEvent) и конечный автомат — это ключевые понятия в QP.
QP поддерживат два типа конечных автоматов — простой(QFSm) и иерархический(QHSm). Любой из этих типов автоматов — это набор определённых состояний(QState), в которых автомат можен находится и набор правил, по которым автомат может изменять своё состояние. Различие между ними состоит в том, что состояние автомата типа QHSm, фактичеки может содержать в себе ещё один автомат хоть QFSm, хоть QHSm типа. Уровень вложености настраиватся и по умолчанию равен 10.
Событие.
struct QEvent{
QSignal sig;
uint8_t dynamic_;
}
Это основной механизм взаимодействия автоматов с внешним миром и между собой. Событие обязательно состоит из сигнала(QSignal sig) и поля служебной информации(uint8_t dynamic_), а так же может содержать не обязательные поля определяемые пользователем. Именно реакция на сигналы описана в состояниях.
Существуют динамические и статические события. Статические события — это не изменяемые события, которые существуют всегда. У статических событий поле dynamic_ всегда равно нулю.
Динамические события — это события, которые создаются в области динамической памяти, и существуют до тех пор, пока не будут обработаны всеми автоматами, которым они предназначены.
Сигналы.
enum QSignal{Q_EMPTY_SIG = 0, Q_ENTRY_SIG, Q_INIT_SIG, Q_EXIT_SIG, Q_USER_SIG};
enum QSignal{Q_EMPTY_SIG = 0, Q_ENTRY_SIG, Q_INIT_SIG, Q_EXIT_SIG, Q_TOUT_SIG, Q_USER_SIG};// для QP-nano
В QP есть 4 сигнала зарезирвированых системой Q_EMPTY_SIG, Q_ENTRY_SIG, Q_INIT_SIG и Q_EXIT_SIG а в QP-nano ещё и Q_TOUT_SIG об их назначении поговоримпозже.
Состояние(QState) — по своей сути это функция, которая должна обработать событие. Результатом работы данной функции является либо переход в другое состояние, либо какое-то действие без смены состояния.
Для наглядности рассмотрим абстрактную функцию-состояние:
QState AbstractState(QFSm * me, QEvent const * e){
switch(e->sig){
case Q_ENTRY_SIG:{
return Q_HANDLED();
}
case Q_INIT_SIG:{
return Q_HANDLED();
}
case Q_USER_SIG:{
return Q_TRAN(&AnotheAbstractState);
}
case Q_EXIT_SIG:{
return Q_HANDLED();
}
}
return Q_SUPER(QFSm::top);
}
Как видим возможны 3 варианта «ответа» обработано — Q_HANDLED(), перейти в другое состояние — Q_TRAN(), и «что делать не знаю, спросите выше» — Q_SUPER(). Для QFSm — Q_SUPER() равносильно Q_HANDLED(), хотя если поковыряться в исходниках мы увидим, что там реально Q_IGNORED(), но идейный смысл тот же.
Теперь пройдёмся по сигналам, которые обрабатывает данное состояние.
Q_ENTRY — этот сигнал framework автоматически дает на обработку состоянию каждый раз, когда в него входят.
Q_INIT — очень актуально для QHSm — тоже генерируется автоматически, когда состояние является конечной точкой назначения перехода.
Q_EXIT — автоматически генерируется при выходе из состояния.
Обработка этих трёх сигналов должна присутствовать в каждом состоянии.
На этом пока всё, если у уважаемого сообщества будет интерес к данной теме — с удовольствием продолжу.
З.Ы. Извините за орфографию и некоторую сумбурность изложения, русский язык не изучал, да и статья эта первая в моей жизни. Буду рад конструктивной критике.
UPD: Прикрепил полную версию книги
- +2
- 04 октября 2011, 23:21
- kovz
- 1
Файлы в топике:
practical-uml-statecharts-in-c-c-second-.pdf
… а какие есть аналоги этой программы и чем они хуже/лучше?
PS… ваша фирма купила этот софт или пока триалите?
PPS… однако прихватили они доменчик www.state-machine.com
PS… ваша фирма купила этот софт или пока триалите?
PPS… однако прихватили они доменчик www.state-machine.com
Очень хороший, продуманный и оптимизированный framework. Действительно помогает структуировать и систематизировать собственный код. Кроме того занимет мало места при достаточно большом наборе возможностей. Я пока использовал только QP-nano. О нем у меня только положительные впечатления. С появлением QM процесс разработки автомата очень сильно упростился. Появилась возможность быстро вносить изменения в структуру автомата, причем довольно значительные изменения вносятся путем простого перетаскивания объектов.
Единственное, что не очень понравилось, это, с моей точки зрения, несколько сумбурное повествование в книге по framework. Читается довольно тяжело, но полезной информации содержит в себе много.
столько лет прошло, но помним я и ты…
А можно продолжение запилить? Там уже автогенерация кода появилась по слухам :)
А можно продолжение запилить? Там уже автогенерация кода появилась по слухам :)
- DeusExMachina
- 05 ноября 2015, 12:00
- ↓
Слухи правильные! :) Появилась и давно! State machine делается в визуальном редакторе QM, который уже генерирует код. На данный момент уже используется 3 версия этого редектора.
К сожалению поддержка некоторых старых микроконтроллеров прекращена, на практически все новые типы поддержка есть. Даже на Arduino можно использовать, что довольно таки сильно расширяет возможности последней. :)
К сожалению поддержка некоторых старых микроконтроллеров прекращена, на практически все новые типы поддержка есть. Даже на Arduino можно использовать, что довольно таки сильно расширяет возможности последней. :)
Поглядел по-диагонали, имхо оверкил… Имею опыт работы с visualSTATE, Matlab Stateflow, как-то поинтуитивнее выходит. Я хочу просто автомат нарисовать, сгенерировать код и вставить в проект, а тут подсадить хотят полностью на qp
- DeusExMachina
- 06 ноября 2015, 21:25
- ↑
- ↓
автомат нарисовать, сгенерировать код и вставить в проектТак код-то тоже генерируется по каким-то правилам! Эти правила устанавливает тот кто пишет софт. Вот и «Quantum Leaps» тоже генерирует код по своим «правилам». :) И тоже просто рисуется автомат, генерируется код по этому автомату и вставляется в проект. Только вдобавок можно ещё воспользоваться их же ядром для обработки этого кода. А вообще каждый выбирает инструменты по себе, для своей конкретной задачи. :)
Комментарии (19)
RSS свернуть / развернуть