ВВЕДЕНИЕ
МАТЛАБ (MATLAB) – система компьютерной математики, которая в настоящее время широко применяется исследователями для решения прикладных и теоретических задач на ЭВМ. Название МАТЛАБ происходит от словосочетания “матричная лаборатория" (matrix laboratory), что первоначально соответствовало основному назначению системы – матричным вычислениям. Впоследствии, с развитием системы, в неё были добавлены функции и вычислительные алгоритмы из многих других областей математики. Но основной подход к элементарным операциям, когда число рассматривается как частный случай матрицы, сохранился. В настоящее время МАТЛАБ представляет собой развитую систему, включающую в себя в качестве составных частей инструменты для решения задач из разных областей математики, таких как линейная алгебра, численные методы, динамические системы и т. д.
Пользователю предлагается несколько вариантов использования системы. Основным режимом является режим командной строки, при котором команды, набираемые пользователем на клавиатуре в ответ на приглашение системы, выполняются в диалоговом режиме с немедленной выдачей результата. В этом режиме легко получить решение таких задач, как вычисление определителей, обращение и перемножение матриц, решение систем линейных алгебраических уравнений и др. Для выполнения этих и других операций необходимо вызвать соответствующую функцию системы, передав ей входные параметры и, возможно, сохранить результат для последующего использования.
Ядро МАТЛАБ содержит более тысячи функций. Помимо них доступно большое количество внешних функций, описанных в расширениях системы. В добавление к ним пользователь может создавать свои собственные функции, используя для этого специально предусмотренный язык программирования. Таким образом, МАТЛАБ является расширяемой системой, и это одно из важных её достоинств.
Помимо режима командной строки, являющегося основным режимом работы, некоторые расширения МАТЛАБ предлагают собственные диалоговые средства. Примером такого расширения является PDE Tool – графический интерфейс, предназначенный для решения дифференциальных уравнений в частных производных. Помимо функций, доступных из командной строки, он также предоставляет пользователю графическую среду, работающую в отдельном окне.
Выше упоминалось о том, что в МАТЛАБ имеется язык программирования. С его помощью можно создавать и реализовывать собственные алгоритмы, используя все доступные функции системы и все основные приёмы программирования, имеющиеся в других языках, такие как подпрограммы, циклы, ветвления, рекурсии и другие. Запись алгоритма на языке программирования МАТЛАБ сохраняется в файле в текстовом формате, либо в специальном внутреннем представлении.
МАТЛАБ обладает развитой графикой. Графическая подсистема МАТЛАБ является объектно-ориентированной. Графики выводятся на экран в отдельных окнах, причём как сами окна, так и составные части графиков (оси, разметка, надписи, линии) являются элементами иерархического дерева объектов.
Для построения графиков в МАТЛАБ имеется большой набор функций, позволяющих создавать множество различных типов двумерных и трёхмерных графиков, диаграмм, гистограмм и т. д., причём элементами графического окна можно управлять программно.
Как графические объекты рассматриваются также такие элементы, как кнопки, текстовые надписи, поля ввода, полосы прокрутки и т. п. Свойства и методы этих объектов доступны пользователю, что даёт возможность создавать в МАТЛАБ Windows-приложения. Для проектирования форм имеется редактор, вызываемый по команде GUIDE.
Вдобавок к развитым графическим средствам МАТЛАБ в качестве одного из своих расширений предоставляет пользователю Virtual Reality Toolbox - пакет для разработки и отображения сцен виртуальной реальности, для которых доступны средства анимации. Это позволяет не только моделировать динамические процессы в Simulink (Simulink – расширение МАТЛАБ, предназначенное для моделирования динамических процессов), но и, подключив потоки выходных данных к входам спроектированной пользователем виртуальной сцены, наблюдать на мониторе анимированную динамику процесса.
Современные версии МАТЛАБ имеют развитые средства интеграции с другими языками программирования. Непосредственно из МАТЛАБ-программы можно создавать и использовать объекты Java; для написания S-функций (системных функций МАТЛАБ-Simulink) можно использовать языки высокого уровня C, C++, Ada, Fortran; кроме того функции системы МАТЛАБ можно экспортировать в dll и вызывать из других программ. Также можно использовать вычислительные возможности системы, передавая запросы удалённому компьютеру по сети.
МАТЛАБ поддерживает некоторые виды символьных вычислений. Среди них арифметические операции над числами с произвольным количеством разрядов, преобразование выражений, символьное дифференцирование, аналитическое вычисление пределов, интегралов, вычисление сумм рядов.
В МАТЛАБ реализованы численные методы решения ряда вычислительных задач, таких как нахождение корней полиномов, решение задачи Коши для систем ОДУ, вычисление определённого интеграла, решение нелинейных уравнений.
Список возможностей МАТЛАБ не ограничивается тем, что было перечислено выше, и меняется с выходом каждой следующей версии пакета. На сегодняшний день система МАТЛАБ считается одной из наиболее мощных и развитых систем компьютерной математики.
ОСНОВНЫЕ ФУНКЦИИ
Как уже говорилось, основным режимом работы в системе МАТЛАБ является режим командной строки, при котором команды набираются пользователем на клавиатуре в ответ на приглашение системы и немедленно обрабатываются. Примером команды может служить инструкция присваивания какой-либо переменной (переменным) результата выражения, например:
>>x=2+2
x = 4
В этом примере “>>” – это приглашение системы, x – переменная рабочей области, которой будет присвоен результат. Последняя строка примера – это ответ системы на команду пользователя.
Выражение может формироваться из вызовов функций, арифметических и логических операций, операндами которых могут быть числовые, строковые и логические константы и массивы, переменные, вызовы функций и другие выражения. Большинство операций и функций реализовано таким образом, что их аргументами могут быть как скалярные величины, так и матрицы. При этом результат выполнения операции также будет скалярным или матричным, в зависимости от аргумента. Матрицы в МАТЛАБ записываются перечислением своих элементов внутри квадратных скобок по строкам, строки при этом разделяются точками с запятой. Рассмотрим пример – сложение двух матриц, которое выполняется по аналогии со сложением двух скалярных величин:
>>A=[1 2; 3 4];
>>B=[8 7; 6 5];
>>C=A+B
C=
9 9
9 9
Знак “+” означает матричное сложение, то есть аргументы складываются по правилам матричной алгебры. То же самое касается операций вычитания, умножения и деления – эти операции выполняются по правилам матричной алгебры, которые в случае скалярных аргументов совпадают с правилами обычных арифметических вычислений. Размеры матриц аргументов при этом должны быть согласованы по правилам линейной алгебры. Для выполнения операции над матричными аргументами поэлементно следует использовать поэлементные операции: “.+”, “.-“, “.*”, “./”. Результатом поэлементной операции будет матрица, все элементы которой являются результатом этой операции над соответствующими элементами аргументов. Для операций сложения и вычитания матричные операции совпадают с поэлементными операциями, но для умножения, деления и возведения в степень (которое записывается как x^n) это уже не так:
>>A=[1 2; 3 4];
>>B=[8 7; 6 5];
>>C=A*B
C=
20 17
48 41
>>D=A.*B
D =
8 14
18 20
Матричное деление матрицы A на матрицу B в МАТЛАБ понимается как нахождение такой матрицы C=A/B, чтобы матрица C*B-A была бы наиболее близка к нулевой матрице в смысле некоторой нормы.
Ещё одна матричная операция, а именно транспонирование, записывается в МАТЛАБ так:
>>A.’
Если в этой записи точку перед апострофом не ставить, то вдобавок к транспонированию все элементы матрицы будут взяты с комплексным сопряжением. Здесь заметим, что комплексные числа используются в системе МАТЛАБ, и над ними можно производить все определённые для них вычисления. Комплексное число представляется как сумма действительной и мнимой части, формируемой при помощи специальной константы – мнимой единицы, которая после начала работы системы помещается одновременно в две ячейки – переменные i и j. Присваивать другие значения этим переменным можно, но не рекомендуется.
Простейшая операция над комплексными числами – выделение действительной и мнимой части – показана на примере, дополнительно иллюстрирующем, что многие функции в МАТЛАБ могут принимать и возвращать как скалярные, так и матричные значения.
>>A=[2+3*i 1-7*j -4*i];
>>Re=real(A)
Re=
[2 1 0]
>>Im=imag(A)
Im=
[3 -7 -4]
Ещё одно полезное качество системы МАТЛАБ – возможность возвращать несколько результатов из одного вызова функции. Причём пользователь может сам определять, нужно ли ему получать все результаты или нет. Например, функции min и max могут возвращать не только минимальный или максимальный элемент вектора, но и его индекс (номер позиции в векторе):
>>a=[4 3 2 75 2];
>>max(a)
ans=
75
>>[m idx]=min(a)
m=
2
idx=
3
Обсуждая этот пример, отметим, что если вызов функции производится без присваивания какой-либо переменной, то ответ помещается в специальную переменную ans, при этом она получает значение только первого из возвращаемых параметров. Чтобы получить значения остальных выходных параметров, необходимо в операторе присваивания зарезервировать под них переменные, как это показано в примере. Полученное значение индекса наименьшего элемента можно использовать для выбора соответствующего элемента из вектора. В общем случае запись A(m,n) означает выбор одного из элементов прямоугольной матрицы, стоящего на пересечении строки m и столбца n, а запись A(k) – выбор элемента, находящегося на позиции k из вектора, полученного записыванием по очереди всех столбцов матрицы в один вектор. Если же необходимо вычленить из матрицы A подматрицу, находящуюся на пересечении строк с i0 по i1 и столбцов с j0 по j1, то это можно сделать так: A(i0:i1, j0:j1). Запись i0:i1 означает вектор целых чисел от i0 до i1. Имеет место следующее обобщение: запись a0:a1:a2 в МАТЛАБ означает упорядоченный набор чисел, начинающийся с числа a0, образующих арифметическую прогрессию с шагом a1 и не превосходящих величину a2 (с нужной стороны, в зависимости от знака a1).
Ещё одно замечание – по умолчанию любая команда в системе МАТЛАБ приводит к отображению результата. Чтобы результат не выводился, достаточно завершить ввод команды точкой с запятой:
>>a=[1 2; 3 4]
a=
1 2
3 4
>>a;
>>b=[1 2; 3 4];
>>b
b=
1 2
3 4
Это полезно при создании пользователем функций в режиме программирования, когда в процессе расчёта по программе необходимо избежать вывода результатов промежуточных вычислений.
Теперь перечислим некоторые элементарные математические функции.
cos
cot
csc
sec
sin
tan
acos
acot
acsc
asec
asin
atan
atan2
cosh
coth
csch
sech
sinh
tanh
acosh
acoth
acsch
asech
asinh
atanh
exp
log
log2
log10
sqrt
ceil
fix
floor
round
gcd
lcm
abs
sign
mod
rem
mean
median
min
max
std
var
|
косинус
котангенс
косеканс
секанс
синус
тангенс
арккосинус
арккотангенс
арккосеканс
арксеканс
арксинус
арктангенс
модификация арктангенса
гиперболический косинус
гиперболический котангенс
гиперболический косеканс
гиперболический секанс
гиперболический синус
гиперболический тангенс
гиперболический арккосинус
гиперболический арккотангенс
гиперболический арккосеканс
гиперболический арксеканс
гиперболический арксинус
гиперболический арктангенс
экспонента
натуральный логарифм
двоичный логарифм
десятичный логарифм
квадратный корень
округление до целого в большую сторону
отбрасывание дробной части
округление до целого в меньшую сторону
округление до ближайшего целого
наибольший общий делитель
наименьшее общее кратное
модуль (абсолютная величина) числа
знак числа
остаток от деления с учётом знака делимого
остаток от деления
среднее
медиана
минимальное значение
максимальное значение
среднеквадратичное отклонение
дисперсия
|
Зная имя функции, способ её использования можно уточнить в справочной системе МАТЛАБ.
Остановимся вкратце на основных функциях линейной (матричной) алгебры.
inv
pinv
det
rank
trace
norm
size
jordan
poly
eig
cond
null
|
обращение матрицы (нахождение обратной)
псевдообратная матрица
определитель матрицы
ранг матрицы
след матрицы
норма матрицы
размер матрицы
приведение к форме Жордана
характеристический полином матрицы
собственные векторы и собственные значения матрицы
число обусловленности матрицы
базис ядра матрицы
|
Опять-таки, подробности использования функций не представляет труда уточнить в справочной системе МАТЛАБ.
Заметим, что если имеется система линейных алгебраических уравнений с квадратной невырожденной матрицей Ax=b, то её решение можно получить как x=inv(A)*b или x=A\b. Последнее выражение также даёт некоторое частное решение неоднородной системы в случае, если матрица A вырождена и имеется бесконечно много решений. В этом случае для построения общего решения необходимо найти общее решение однородной системы, которое совпадает с ядром матрицы и может быть найдено с помощью функции null. В случае если система не имеет решений, нормальное псевдорешение может быть получено так: x=pinv(A)*b.
ЧИСЛЕННЫЕ МЕТОДЫ
Одним из математических объектов, поддерживаемых в МАТЛАБ, является полином. Он представляется в системе вектором своих коэффициентов, начиная с коэффициента при старшей степени:
>>p=[2 4 -3 1];
Это запись полинома 2x3 + 4x2 – 3x +1. Для полиномов реализовано большое количество функций, некоторые из которых приведены ниже:
polyval
poly
roots
conv
deconv
polyder
residue
|
значение полинома в точке
восстановление полинома по корням
корни полинома
свёртка (умножение) полиномов
деление полиномов
производная полинома
разложение отношения полиномов в сумму простых дробей
|
Далее приведём функции, применяемые при численном дифференцировании, интегрировании и решении дифференциальных уравнений:
diff
gradient
del2
trapz
quad
ode45
ode23
ode113
ode15s
ode23s
ode23t
ode23tb
bvp4c
fzero
fsolve
fminbnd
fminsearch
|
конечные разности произвольного порядка
аналог градиента
оператор Лапласа
вычисление определённого интеграла методом трапеций
вычисление определённого интеграла методом парабол
здесь и ниже: решатели задачи Коши для систем ОДУ
---//---
---//---
---//---
---//---
---//---
---//---
решатель краевой задачи для систем ОДУ
поиск корня нелинейного уравнения
решение систем нелинейных уравнений
поиск минимума
многомерная минимизация
|
Для решения задачи Коши предлагается сразу несколько решателей, реализующих различные численные методы: методы Рунге-Кутта различных порядков, методы Адамса, различные линейные многошаговые методы и т. д.
Проектирование и моделирование систем управления.
Пакет Control System Toolbox
Пакет предназначен для моделирования, анализа и проектирования непрерывных и дискретных систем автоматического управления и регулирования. Функции пакета способны производить вычисления с передаточными функциями, описанием объектов в пространстве состояний, отображать на графиках частотные и временные характеристики, нули и полюсы систем.
В пакете реализованы следующие возможности:
- обширный набор средств анализа одномерных и многомерных непрерывных и дискретных систем и объектов;
- построение основных характеристик систем: импульсной, передаточной и переходной, реакция на произвольное воздействие;
- построение частотных характеристик: диаграмм Боде, Найквиста, Николса и др.;
- разработка замкнутых систем регулирования;
- проектирование регуляторов;
- определение характеристик моделей: управляемости, наблюдаемости, понижение порядка моделей;
- доступны вычислительные операции для систем с запаздыванием;
Основными объектами вычислений являются:
- объект верхнего уровня LTI (Linear Time-Invariant System –линейная стационарная система)
- потомки объекта LTI для следующих типов моделей:
- в tf-форме – задание числителя и знаменателя передаточной функции (tf – transfer function)
- в форме zpk (задание нулей, полюсов и коэффициента усиления передаточной функции)
- в ss-форме (задание системы в пространстве состояний, путём указания матриц коэффициентов дифференциальных уравнений)
- в frd-форме (задание вектора частот и соответствующих значений комплексного коэффициента передачи)
В состав пакета Control System входит более ста функций. Для вывода полного набора средств пакета предназначена команда help control. Приведём некоторые:
tf
zpk
ss
dss
frd
tfdata
zpkdata
ssdata
frdata
parallel
series
feedback
append
ltiview
bode
nyquist
nichols
place
kalman
ctrb
obsv
canon
step
impulse
initial
lsim
|
задание системы числителем и знаменателем передаточной функцией
задание системы нулями и полюсами передаточной функции
задание непрерывной системы в переменных состояния
задание дискретной системы в переменных состояния
задание системы вектором частот и откликов
получение числителя и знаменателя передаточной функции
получение нулей и полюсов передаточной функции
получение матриц пространства состояний
получение частот и откликов
параллельное соединение подсистем
последовательное соединение подсистем
соединений подсистем обратной связью
объединение подсистем
графический интерфейс анализа систем
диаграмма Боде
диаграмма Найквиста
диаграмма Николса
построение вектора обратной связи для заданных полюсов
наблюдатель Калмана
матрица управляемости
матрица наблюдаемости
каноническое представление в пространстве состояний
переходная характеристика
импульсная характеристика
отклик системы на начальные условия
отклик системы на заданное воздействие
|
После того, как создан объект LTI (модель задана одной из функций ss, zpk, tf, frd), для его преобразования в другое представление можно использовать соответствующую из этих функций.
>> num=[1 0];
>> den=[1 2 10];
>> sys=tf(num, den)
Transfer function:
s
--------------
s^2 + 2 s + 10
>> sys=ss(sys)
a =
x1 x2
x1 -2 -5
x2 2 0
b =
u1
x1 1
x2 0
c =
x1 x2
y1 1 0
d =
u1
y1 1
Здесь a, b, c и d – матрицы системы дифференциальных уравнений (в пространстве состояний):
Далее можно вычислить матрицы управляемости и наблюдаемости для системы:
>> ctrb(sys)
ans =
1 -2
0 2
>> obsv(sys)
ans =
1 0
-2 -5
Наконец, найдём такой вектор обратной связи, чтобы замкнутая система имела спектр в точках -10 и -11:
>> k=place(sys.a,sys.b,[-10,-11])
k =
-23.0000 50.0000
Для аналитического конструирования регуляторов служит группа функций. В частности, функция lqr осуществляет синтез оптимального регулятора для непрерывной системы:
>>[K, S, e]=lqr(A,B,Q,R,N)
Функция возвращает матрицу K обратных связей такую, что закон управления u=-Kx минимизирует квадратичный критерий качества:
для непрерывной ss-модели. Возвращаемый параметр e представляет собой собственные значения замкнутой системы (матрицы A-BK). Аналогичные функций есть для некоторых других критериев оптимизации, а также как для непрерывных, так и для дискретных систем.
Анимация встроенными средствами МАТЛАБ
Построение визуальной статической модели системы в редакторе виртуальных миров.
Система МАТЛАБ предоставляет среду создания и редактирования файлов в формате VRML (Virtual Reality Modeling Language), принятом стандарте описания трёхмерных сцен, сформированных из отдельных графических примитивов (элементарных геометрических тел). Редактор V-Realm Builder, поставляемый вместе с МАТЛАБ, позволяет в интерактивном режиме создавать виртуальные сцены и сохранять их в формате VRML. Графические примитивы (сферы, параллелепипеды, конусы и др.) при этом организовываются в иерархические структуры, управляя параметрами которых можно менять размер, форму, положение, условия видимости и другие характеристики представленных объектов, влияющие на отображаемую картину. При этом изменение какого-то параметра в процессе отображения в соответствии с некоторым законом делает картину динамической, то есть пользователь видит движущуюся сцену. Для организации такого взаимодействия в МАТЛАБ-Simulink есть встроенные средства (блок VR-Sink). Приведём пример виртуальной трёхмерной сцены, построенной и сохранённой в формате VRML при помощи V-Realm Builder. Сцена представляет собой стилизованное изображение двух перевёрнутых вертикальных маятников, закреплённых нижними концами на горизонтальной платформе так, что они могут вращаться вокруг точки закрепления в вертикальной плоскости.
#VRML V2.0 utf8
#Created with V-Realm Builder v2.0
#Integrated Data Systems Inc.
#www.ids-net.com
Background {
groundAngle [ 0.9, 1.5, 1.57 ]
groundColor [ 0 0.8 0,
0.174249 0.82 0.187362,
0.467223 0.82 0.445801,
0.621997 0.67 0.600279 ]
skyAngle [ 0.1, 1.2, 1.57 ]
skyColor [ 0.76238 0.8 0.1427,
0.277798 0.219779 0.7,
0.222549 0.390234 0.7,
0.60094 0.662637 0.69 ]
}
DEF Pend2 Transform {
translation 1 1 0
center 0 -1.5 0
children DEF Sh1 Shape {
appearance Appearance {
material Material {
}
}
geometry DEF Cyl1 Cylinder {
height 2
radius 0.1
}
}
}
DEF Pend1 Transform {
translation -1 1.5 0
center 0 -1.5 0
children DEF Sh2 Shape {
appearance Appearance {
material Material {
}
}
geometry DEF Cyl2 Cylinder {
height 3
radius 0.1
}
}
}
DEF Platform Transform {
translation 0 0 0
children Shape {
appearance Appearance {
material Material {
}
}
geometry Box {
size 4 0.1 1
}
}
}
Вот как выглядит окно редактора в момент создания сцены:
Построение математической модели в Simulink с учётом внутренней динамики
Для решения задачи стабилизации двух вертикальных перевёрнутых маятников на горизонтальной движущейся платформе одним управлением используется расширение системы МАТЛАБ для моделирования динамических систем – Simulink. Модель включает в себя несколько блоков, соединённых между собой так, что реализуется обратная связь, стабилизирующая маятники в вертикальном положении одновременно одним управлением. Одна из подсистем реализует наблюдатель состояния, вторая – стабилизацию по оценке состояния при помощи обратной связи.
Изменяемыми параметрами модели являются массы и длины маятников, масса тележки, ускорение свободного падения, а также целевой спектр устойчивой системы. Параметры задаются в рабочем пространстве МАТЛАБ при помощи m-файла, который представлен ниже.
m1=1 % Масса первого маятника
m2=3 % Масса второго маятника
M=5 % Масса тележки
l1=2 % Длина первого маятника
l2=4 % Длина второго маятника
g=9.81 % Ускорение свободного падения
Расчётные матрицы получаются из уравнений движения, записанных приближённо для случая малых углов отклонения маятников. В качестве неизвестных компонент вектора состояния взяты соответственно координата и скорость тележки, угол отклонения и скорость его изменения для первого маятника, и то же самое для второго маятника – итого 6 переменных:
Далее формируются расчётные матрицы:
A=[0 1 0 0 0 0; 0 0 -m1*g/M 0 -m2*g/M 0; 0 0 0 1 0 0; 0 0 g/l1*(1+m1/M) 0 g/l1*m2/M 0; 0 0 0 0 0 1;0 0 m1/l2*g/M 0 g/l2*(1+m2/M) 0]
B=[0;1/M;0;-1/l1/M;0;-1/l2/M]
C=[1 0 0 0 0 0] % Наблюдаем только координату тележки
D=zeros(6,1)
IC=[0 0 0.1 0 0.05 0] % начальные условия
LAMBDA=[-0.61 -0.62 -0.63 -0.64 -0.65 -0.66] % целевой спектр устойчивой системы
Диаграмма динамической модели, построенной в Simulink
В качестве параметров L и K используются векторы, вычисляемые при помощи функции place по известным значениям матриц и целевого спектра. Коричневой рамкой выделена подсистема, являющаяся наблюдателем.
Графики, полученные в результате расчёта
Скорость тележки
Положение тележки
Угол отклонения первого маятника
Скорость изменения угла отклонения первого маятника
Угол отклонения второго маятника
Скорость изменения угла отклонения второго маятника
Подключение визуальной модели к точкам входа Simulink для получения анимационной картинки
Simulink располагает средствами (библиотечный блок VR-Sink), позволяющими подключить любой сигнал, распространяющийся во время моделирования между блоками модели, к входу одного из параметров виртуальной трёхмерной сцены, представленной в формате VRML, таким образом управляя движением определённых фрагментов сцены. Соответствующий блок VR-Sink в качестве параметра принимает имя VRML-файла, в котором хранится сцена, и имеет столько входов, сколько именованных узлов создал пользователь в иерархическом дереве сцены во время её проектирования. На каждый такой вход можно подать сигнал Simulink-модели, что приведёт виртуальную сцену в движение во время моделирования в соответствии с изменением сигнала.
Использование внешних интерфейсов МАТЛАБ.
Построение внешней S-функции на языке C++ с использованием библиотеки OpenGL для отображения параметризованной картинки
S-функции применяются в МАТЛАБ-Simulink для конструирования новых блоков, реализующих функции, недоступные в библиотечных блоках. S-функция представляет собой алгоритм преобразования входного сигнала (входных сигналов) в выходной (выходные). Наряду с собственным языком системы МАТЛАБ, S-функции можно писать и на ряде других языков программирования при условии соблюдения определённых правил. Это дает возможность использовать графические средства других языков для выдачи на экран анимационной картинки. В частности, опробована возможность создания S-функции на языке C++ с использованием популярной графической библиотеки OpenGL. Подаваемые на вход S-функции характеристики модели в текущий момент времени используются для формирования средствами C++/OpenGL в отдельном окне картинки, а зрительный эффект движущегося изображения получается за счёт того, что статическая картинка перерисовывается многократно с большой частотой для меняющихся значений параметров. Заключительным этапом построения работающей S-функции является её преобразование из исходного кода в объектный, представляющий из себя библиотеку dll. Это можно сделать из командной строки МАТЛАБ при помощи утилиты mex, производящей сборку кода на C/C++ в dll. Ниже приводится исходный код S-функции, записанный на языке C++, командная строка для сборки dll, а также один из кадров движущейся сцены.
Объединение модели Simulink с S-функцией.
Подача выходов модели на входы S-функции
На этом этапе сигналы, отвечающие физическим характеристикам модели, влияющим на её положение в пространстве (положение тележки и маятников), соединяются с входами S-функции, которая способна их обрабатывать, то есть отобразить картинку в нужном месте экрана в зависимости от их значений. Сама внешняя S-функция встраивается в модель при помощи стандартного блока S-Function, который принимает в качестве параметра имя внешней S-функции.
Реализация анимирующей S-функции и кадр из анимационной сцены
Здесь в качестве примера рассматривается другая задача – аналогичная предыдущей. Необходимо стабилизировать в вертикальном положении маятник, свободным концом шарнирно прикреплённый к тележке.
Кадр из анимационной сцены
Исходный код S-функции, написанной на языке C++ с использованием библиотеки OpenGL для отображения анимационной картинки перемещения маятника на движущейся тележке
#include
#include
#include
#include
#include
#define S_FUNCTION_NAME test_vis
#define S_FUNCTION_LEVEL 2
#define IN_0_FRAME_BASED FRAME_NO
#define OUT_0_FRAME_BASED FRAME_NO
#define SAMPLE_TIME_0 INHERITED_SAMPLE_TIME
#define SFUNWIZ_GENERATE_TLC 1
#define SOURCEFILES ""
#define PANELINDEX 6
#define SFUNWIZ_REVISION 2.0
#include "simstruc.h"
static double x1 = 0,
x2 = 0,
x1_ = 0,
x2_ = 0,
X = 0;
static double l1,l2;
static int glInited = 0;
static HWND hGlWindow = NULL;
static HDC hDC = NULL;
static HGLRC hRC = NULL;
#define GL_CLASS_NAME "gl_class_name"
void CALLBACK resize ( int width, int height )
{
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,float(width)/height,(l1+l2),5*(l1+l2));
}
#define Pi 3.1415
void CALLBACK display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(X,0,-2*(l1+l2));
//glRotated(90,1,0,0);
glBegin(GL_QUADS);
glColor3f(1,1,1);
glVertex3d(-l1,-l1/15,-l1/5);
glVertex3d( l1,-l1/15,-l1/5);
glVertex3d( l1, l1/15,-l1/5);
glVertex3d(-l1, l1/15,-l1/5);
glVertex3d(-l1, l1/15, 0);
glVertex3d(-l1,-l1/15, 0);
glVertex3d( l1,-l1/15, 0);
glVertex3d( l1, l1/15, 0);
glVertex3d( l1,-l1/15,-l1/5);
glVertex3d( l1,-l1/15, 0);
glVertex3d( l1, l1/15, 0);
glVertex3d( l1, l1/15,-l1/5);
glVertex3d(-l1,-l1/15,-l1/5);
glVertex3d(-l1,-l1/15, 0);
glVertex3d(-l1, l1/15, 0);
glVertex3d(-l1, l1/15,-l1/5);
glColor3f(0.8,0.1,0);
glVertex3d(-l1, l1/15,-l1/5);
glVertex3d(-l1, l1/15, 0);
glVertex3d( l1, l1/15, 0);
glVertex3d( l1, l1/15,-l1/5);
glVertex3d(-l1,-l1/15,-l1/5);
glVertex3d(-l1,-l1/15, 0);
glVertex3d( l1,-l1/15, 0);
glVertex3d( l1,-l1/15,-l1/5);
glEnd();
glTranslated(0,l1/7,-l1/10);
glRotated(180*x1/Pi,0,0,1);
GLUquadricObj *qObj = gluNewQuadric();
glPushMatrix();
glRotated(-90,1,0,0);
glColor3f(1,0,0);
gluCylinder(qObj,l1/10,l1/10,2*l1/3,15,3);
gluSphere(qObj,l1/10,15,15);
glPushMatrix();
glTranslated(-l1/15,0,2*l1/3);
gluSphere(qObj,l1/7,15,15);
glPopMatrix();
glTranslated(l1/15,0,2*l1/3);
gluSphere(qObj,l1/7,15,15);
glPopMatrix();
gluDeleteQuadric(qObj);
SwapBuffers ( hDC );
}
static int getBitDepth ()
{
HDC hDC = GetDC ( NULL );
HBITMAP hBmp = CreateCompatibleBitmap ( hDC, 1, 1 );
BITMAPINFO * bmi = (LPBITMAPINFO) malloc ( sizeof (BITMAPINFOHEADER) + 4 * sizeof (RGBQUAD) );
int res, bitCount;
bmi -> bmiHeader.biBitCount = (WORD) GetDeviceCaps ( hDC, BITSPIXEL );
bmi -> bmiHeader.biCompression = BI_BITFIELDS;
bmi -> bmiHeader.biSize = sizeof ( BITMAPINFOHEADER );
bmi -> bmiHeader.biWidth = 1;
bmi -> bmiHeader.biHeight = 1;
bmi -> bmiHeader.biClrUsed = 0;
bmi -> bmiHeader.biPlanes = 1;
res = GetDIBits ( hDC, hBmp, 0, 1, NULL, bmi, DIB_RGB_COLORS );
bitCount = bmi->bmiHeader.biBitCount;
DeleteObject ( hBmp );
ReleaseDC ( NULL, hDC );
DeleteObject ( hBmp );
free ( bmi );
return bitCount;
}
static int createOpenGlWindow ( int x, int y, int width, int height, int depthBits )
{
PIXELFORMATDESCRIPTOR pfd =
{
sizeof (PIXELFORMATDESCRIPTOR), // size of this Pixel Format Descriptor
1, // version number
PFD_DRAW_TO_WINDOW | // format must support Window
PFD_SUPPORT_OPENGL | // format must support OpenGL
PFD_DOUBLEBUFFER, // must support double buffering
PFD_TYPE_RGBA, // request an RGBA format
0, // select color depth
0, 0, 0, 0, 0, 0, // color bits
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation cuffer
0, 0, 0, 0, // accumulation bits ignored
0, // Z-Buffer depth
8, // 8-bit stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main drawing layer
0, // reserved
0, 0, 0 // layer masks ignored
};
GLuint pixelFormat; // will hold the selected pixel format
DWORD windowStyle = WS_OVERLAPPEDWINDOW; // set window style
DWORD windowExtendedStyle = WS_EX_APPWINDOW; // set window extended style
RECT windowRect; // define window coordinates
int bpp;
windowRect.left = x;
windowRect.top = y;
windowRect.right = x+width;
windowRect.bottom = y+height;
pfd.cColorBits = getBitDepth();
pfd.cDepthBits = depthBits;
windowExtendedStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // window xxtended style
windowStyle = WS_OVERLAPPEDWINDOW; // window style
// adjust window, Account for window worders
AdjustWindowRectEx ( &windowRect, windowStyle, 0, windowExtendedStyle );
// create the OpenGL window
hGlWindow = CreateWindowEx ( windowExtendedStyle, // extended style
GL_CLASS_NAME, // class name
"Test", // window title
windowStyle, // window style
windowRect.left, // window (X,Y) position
windowRect.top,
windowRect.right - windowRect.left, // window width
windowRect.bottom - windowRect.top, // window height
HWND_DESKTOP, // desktop is window's parent
0, // no nenu
GetModuleHandle ( NULL ), // pass the window instance
NULL );
if ( hGlWindow == NULL ) // was window creation a success?
return 0; // if not then return false
hDC = GetDC ( hGlWindow ); // get device context for this window
if ( hDC == NULL ) // did we get a device context?
return 0; //done ();
bpp = getBitDepth (); // bit depth
pixelFormat = ChoosePixelFormat ( hDC, &pfd ); // find a compatible pixel format
if ( pixelFormat == 0 ) // did we find a compatible format?
return 0; // failed
if ( SetPixelFormat ( hDC, pixelFormat, &pfd ) == FALSE ) // try to set pixel format
return 0; // failed
hRC = wglCreateContext ( hDC ); // try to get a rendering context
if ( hRC == NULL ) // did we get a rendering context?
return 0; // failed
// make the rendering context our current rendering context
if ( wglMakeCurrent ( hDC, hRC ) == FALSE )
return 0; // failed
resize ( width, height ); // reshape our GL window
ShowWindow ( hGlWindow, SW_SHOW );
return 1; // window creating was successful
// further initialization will be done in WM_CREATE
}
static int destroyOpenGlWindow ()
{
wglMakeCurrent ( NULL, NULL );
if ( hRC != NULL )
wglDeleteContext ( hRC ); // delete The Rendering Context
if ( hDC != NULL )
ReleaseDC ( hGlWindow, hDC ); // release Our Device Context
if ( hGlWindow != NULL )
DestroyWindow ( hGlWindow ); // destroy the window
hGlWindow = NULL; // zero the window handle
hDC = NULL; // zero the device context
hRC = NULL; // zero the rendering context
return 1;
}
static LRESULT CALLBACK windowProc ( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch ( msg ) // evaluate window message
{
case WM_SIZE: // resizing action has taken place
resize (LOWORD (lParam), HIWORD (lParam)); // resize window
if (glInited) display ();
return 0;
}
return DefWindowProc ( hWnd, msg, wParam, lParam ); // pass nnhandled messages to DefWindowProc
}
static void initGL ()
{
float pos[4] = {1,1,0,1};
float dir[3] = {-1,-1,1};
GLfloat mat_specular[] = {1,1,1,1};
// create window class
WNDCLASSEX windowClass;
ZeroMemory ( &windowClass, sizeof (WNDCLASSEX) ); // clear the memory
windowClass.cbSize = sizeof (WNDCLASSEX); // size of the windowClass structure
windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // redraws the window on any movement / resizing
windowClass.lpfnWndProc = (WNDPROC) windowProc; // windowProc Handles Messages
windowClass.hInstance = GetModuleHandle ( NULL ); // set the instance
windowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE; // class background brush color
windowClass.hCursor = LoadCursor ( NULL, IDC_ARROW ); // load the arrow pointer
windowClass.lpszClassName = GL_CLASS_NAME; // sets the classname
windowClass.hIcon = NULL;
if ( RegisterClassEx ( &windowClass ) == 0 )
return;
createOpenGlWindow ( 50, 10, 500, 500, 32 );
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);
float amb[4] = {0.5,0.5,0.5,1};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,amb);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, 128.0);
}
static void mdlInitializeSizes(SimStruct *S)
{
char buf[100];
l1 = mxGetString(ssGetSFcnParam(S,0),buf,100);
sscanf(buf,"%lf",&l1);
l2 = mxGetString(ssGetSFcnParam(S,1),buf,100);
sscanf(buf,"%lf",&l2);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortVectorDimension(S, 0, 3);
ssSetInputPortRequiredContiguous(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S, 1)) return;
ssSetOutputPortVectorDimension(S, 0, 3);
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
ssSetNumSFcnParams(S, 2);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
ssSetOptions(S, (SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_USE_TLC_WITH_ACCELERATOR |
SS_OPTION_WORKS_WITH_CODE_REUSE));
if (!glInited)
{
initGL();
glInited = 1;
}
}
static void mdlStart(SimStruct *S)
{
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, FIXED_IN_MINOR_STEP_OFFSET);
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
const double *u = (const double*)ssGetInputPortSignal(S,0);
double *y = (double*)ssGetOutputPortRealSignal(S,0);
l1 = 0;
char buf[100];
l1 = mxGetScalar(ssGetSFcnParam(S,0));
l2 = 0;
l2 = mxGetScalar(ssGetSFcnParam(S,1));
x1 = u[0];
x1_ = u[1];
X = u[2];
y[0] = u[0];
y[1] = u[1];
y[2] = u[2];
display();
Sleep(30);
}
static void mdlTerminate(SimStruct *S)
{
destroyOpenGlWindow ();
if (UnregisterClass(GL_CLASS_NAME, GetModuleHandle(NULL))!=0)
glInited = 0;
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
Пример командной строки МАТЛАБ для преобразования исходного кода C/C++ в объектный
mex -g test_vis.cpp user32.lib gdi32.lib glu32.lib opengl32.lib
Достарыңызбен бөлісу: |