Методическое пособие 366
.pdfтерфейс). Вместо многоточий должен стоять полный путь к рабочей папке, в которой лежат описываемые sce- и sci-файлы) q0=[0;0;0;0;0;0];
p0=[0;0;0;0;0;0];
(задаются начальные значения для решения задачи Коши. В данном случае q0 – вектор начальных значений обобщѐнных координат исследуемого тела (3 координаты центра масс тела и 3 угла поворота), а p0 – вектор из начальных значений производных указанных обобщѐнных координат).
scf(333);clf();
(создаѐтся пустое графическое окно с номером 333)
H=build_body();
(рисует в созданном графическом окне исследуемое тело, описание функции будет приведено ниже при разборе файла с функциями графического интерфейса)
ax=gca();
(создаѐтся дескриптор осей)
ax.axes_visible=["on" "on" "on"]; ax.grid=[1 1 1]; ax.x_label.text="X"; ax.y_label.text="Y"; ax.z_label.text="Z";
(задаются свойства осей: первая строчка отвечает за видимость осей: вектор из трѐх значений on означает, что все три оси будут видны в созданном графическом окне, вторая строчка означает, что по всем трѐм осям будет нанесена сетка, а последние три строчки вводят обозначения для каждой из осей). Результатом этих команд является изображение в графическом окне (рис. 5)
9
Рис. 5. Графический интерфейс
Способ получения тела и вертикальной линии будет описан при описании функции build_body. y=[q0(1);p0(1);q0(2);p0(2);q0(3);p0(3);q0(4);p0(4);q0(5);p0(5);q 0(6);p0(6)];
(формируется начальное значение вектора состояния решаемой системы 12 дифференциальных уравнений первого порядка) y0=y;y1=y;
(начальное значение вектора состояния системы помещается в промежуточные переменные, которые будут использоваться в дальнейшем)
init=%t;state_changed=%f;
(задаются начальные значения для двух логических переменных: переменная init отвечает за то, была ли произведена инициализация состояния системы: true, если была и false, если не была, соответственно в начальный момент времени, т.е. в момент инициализации она полагается равной true; переменная state_changed показывает, поменялись ли компоненты вектора
10
состояния системы или нет: если нет, то false, если да, то true; в начальный момент, когда состояние ещѐ не менялось, она рав-
на true)
global y0 y1 state_changed init
(поскольку вышеуказанные 4 переменные будут использоваться в дальнейшем, они объявляются глобальными)
Файл model.sci (этот файл содержит функции, описывающие динамику исследуемого тела):
function qpdot=body_dyn(t, qp)
(на вход функции подаѐтся время начала интервала интегрирования системы дифференциальных уравнений (переменная t) и значение вектора состояния интегрируемой системы на момент t; на выходе функции правая часть системы уравнений на момент времени t (переменная qpdot))
q1=qp(1);
q2=qp(3);
q3=qp(5);
q4=qp(7);
q5=qp(9);
q6=qp(11);
(6 обобщѐнных координат в момент времени t) p1=qp(2);
p2=qp(4);
p3=qp(6);
p4=qp(8);
p5=qp(10);
p6=qp(12);
(6 производных обобщѐнных координат в момент времени t) a21=0.1; a22=100; a23=6*10^(-3)*sin(2*%pi*t); a24=9.815*4*10^(-5)*sin(2*%pi*t); a43=4.4*10^(-3)*sin(2*%pi*t); a44=9.815*2*10^(- 5)*sin(2*%pi*t);
11
a61=a21; a62=100; a63=2.6*10^(-3)*sin(2*%pi*t); a64=a43*a44/9.815; a65=a23*a24/9.815; a66=- 16*%pi*%pi*10^(-5)*sin(2*%pi*t); a67=-8*%pi*%pi*10^(- 5)*sin(2*%pi*t); a68=16*%pi*10^(-5)*cos(2*%pi*t); %pi*10^(-5)*cos(2*%pi*t); a610=7.64*10^2; a611=1.27*10^4; a612=2*10^3;
a81=0.1; a82=400; a123=-12*%pi*%pi*10^(-5)*sin(2*%pi*t);
(записываются численные значения коэффициентов правой части системы)
qpdot=[p1; -a21*p1-a22*q1-a23+a24; p2; -a21*p2-a22*q2-a43+a44; p3;
-a61*p3-a62*q3-a63+a64-a65+a66*q1-a67*q2+a68*p1-a69*p2- a610*q3*q3-a611*(q1*q1+q2*q2)-a612*(q4*q4+q5*q5);
p4; -a81*p4-a82*q4-a67; p5; -a81*p5-a82*q5-a66; p6; -a81*p6-a82*q6-a123];
(записывается правая часть системы) endfunction
function R=euler(psi, theta, phi)
(функция, на вход которой подаются три угла Эйлера, на выходе матрица ориентации двух трѐхгранников, записанная через углы Эйлера)
cpsi=cos(psi);spsi=sin(psi); ct=cos(theta);st=sin(theta); cphi=cos(phi);sphi=sin(phi);
R=[cpsi*ct*cphi-spsi*sphi,-cpsi*ct*sphi-spsi*cphi, cpsi*st; spsi*ct*cphi+cpsi*sphi,-spsi*ct*sphi+cpsi*cphi, spsi*st;
12
-st*cphi ,st*sphi, ct] endfunction
function R=eulerm1(psi, theta, phi)
(всѐ то же самой, только на выходе получается матрица, транспонированная к матрице, полученной при выполнении предыдущей функции)
cpsi=cos(psi);spsi=sin(psi); ct=cos(theta);st=sin(theta); cphi=cos(phi);sphi=sin(phi);
R=[cpsi*cphi*ct-spsi*sphi, cpsi*sphi+spsi*cphi*ct, -cphi*st; -spsi*cphi-cpsi*sphi*ct, cpsi*cphi-spsi*sphi*ct, sphi*st;
cpsi*st, |
spsi*st, |
ct ]; |
endfunction |
|
|
Файл model_gui.sci (этот файл содержит функции, отвечающие за графический интерфейс):
function [H]=build_body()
(функция, при помощи которой исследуемое тело появляется в графическом окне; возвращает дескриптор графического объекта, коим в данном случае выступает поверхность, изображающая исследуемое тело)
n=21;
[X,Y,Z]=body_facets(body_profile,n)
(в результате действия этой функции, которая будет описана ниже, получаются 3 матрицы. Эти матрицы используются в дальнейшем в функции plot3d, которая изображает тело. Изображение получается путѐм объединения множества элементов поверхности. Каждый элемент представляет собой многоугольник; координаты вершин каждого из многоугольников и являются элементами трѐх матриц X, Y, Z. Число вершин каждого из многоугольников есть число строк каждой из матриц; число столбцов каждой из матриц есть число элементов, составляющих поверхность. Переменная n представляет собой число точек, которые составляют «скелет» тела, в каждой из горизонтальных плоскостей, проходящих через тело; число
13
этих плоскостей представлено ниже и обозначено переменной np, причѐм 2 из этих плоскостей проходят через нижнюю и верхнюю точки тела соответственно)
N=n-1; np=1+size(X,2)/N drawlater()
(N обозначает число элементов поверхности, которые получены разбиением тела вертикальными плоскостями, проходящими через точки, образующие «скелет» тела) f=gcf();f.color_map=graycolormap(N);
(после этого каждый из элементов поверхности, полученный разбиением вертикальными плоскостями, будет иметь свой цвет, цвета соседних элементов меняются линейно от белого до серого)
s=[((N/2)):(N-1),N:-1:((N/2)+1)];
(это вектор, значения компонент которого – это номер цвета каждого из многоугольников, которые составляют поверхность)
clf(),plot3d(X,Y,list(Z,ones(1,np-1).*.s))
(строится исследуемое тело, элемент поверхности с вершинами X(:,i), Y(:,i), Z(:,i) имеет свой цвет, числовой эквивалент которого равен s(i))
H=gce();
(дескриптор графического объекта – поверхности)
H.hiddencolor=-1;
(внутренность тела раскрашена так же, как и внешняя сторона)
H.color_mode = -1;
(отрицательное значение этого параметра означает, что границы элементов, составляющих поверхность, не изображаются)
H.clip_state = 'off';
(изображение поверхности не обрезается при выходе за какуюлибо область рисунка)
H.user_data=[0 0 0 0 0 0];
14
(в этом поле сохраняются обобщѐнные координаты тела) x=-2.5:0.05:2.5;
param3d(zeros(x),zeros(x),x);
(рисуется вертикальная линия от z = -2.5 до z = 2.5) e=gce();e.thickness=2;
(увеличивается толщина линии для лучшего визуального эффекта)
a=gca();
(дескриптор осей)
a.data_bounds=[-1.5 -1.5 -1.5;1.5 1.5 1.5];
(это поле обозначает границы значений на осях, первые 3 значения – нижние границы значений, на осях X, Y, Z соответственно, вторые 3 значения – верхние границы) a.axes_bounds=[0 0 0.8 1];
(положение осей: первые 2 числа – положение левого верхнего угла рисунка, вторые 2 числа – ширина и высота рисунка в отношении к его максимальному размеру. Все 4 числа должны лежать в промежутке [0,1])
a.box='off';
(куб, образованный тремя осями, не изображается) a.isoview="on";
(включается изометрический вид осей) a.rotation_angles=[76 45];
(обозначает сферические координаты воображаемой точки, с которой наблюдатель смотрит на рисунок)
drawnow() endfunction
function [zp, ro]=body_profile()
(на выходе функции массивы из координат точек, расположенных на сечении тела вертикальной плоскостью, проходящей через центр тела (в данном случае тело – сфера, значит сечение - окружность): zp – массив с Z-координатами точек, ro – массив с расстояниями от каждой из точек до вертикальной прямой, проходящей через центр тела)
15
ttheta = linspace(0, %pi, 35); ro = (0.45*sin(ttheta))';
zp = (0.45*cos(ttheta))'; endfunction
таким образом, получается 35 точек. function [X, Y, Z]=body_facets(prof, n)
(на входе – данные, полученные от предыдущей функции и число точек, составляющих «скелет» тела в каждой из горизонтальных плоскостей, проходящих через каждую из 35 точек, полученных в предыдущей функции, на выходе – матрицы X, Y, Z, используемые в функции build_body)
[zp,ro]=prof(); np=size(ro,'*'); t=linspace(0,2*%pi,n); x=ro*cos(t); y=ro*sin(t); z=zp*ones(t);
(в итоге x, y, z содержат матрицы с координатами точек, составляющих «скелет» сферы, т.е. они представляют собой мат-
рицы 35*n, где n=21 (см. описание build_body))
После этого образовываются искомые матрицы X, Y, Z с координатами вершин элементов поверхности:
Iz=([0;0;1;1]*ones(1,np-1)+ones(4,1)*(1:(np-1))).*.ones(1,n-1); It=ones(1,np-1).*.([0;1;1;0]*ones(1,n-1)+ones(4,1)*(0:(n-2))); I=matrix(Iz+np*It,-1,1);
X=matrix(x(I),4,-1);
Y=matrix(y(I),4,-1);
Z=matrix(z(I),4,-1); endfunction
(размер матриц 4х680, т.е. нарисованная поверхность будет составлена из 680 криволинейных четырѐхугольников (у тех элементов, которые содержат полюса сферы, 2 вершины совпадают))
function body_gui()
16
(функция, которая создаѐт графический интерфейс) global body_controls
fig=gcf(); w=fig.axes_size;
(массив из двух элементов – ширина и высота графического окна)
m=20; lslider=150;h=20; lv=40;
xs=w(1)+lslider+lv+m+10; xv=xs+lslider+10; yx=w(2)-(m+h);
(переменные, определяющие местоположение элементов графического интерфейса, их размеры и интервалы между ними)
Xplane_title = uicontrol( ...
"parent" |
, fig,... |
"style" |
, "text",... |
"string" |
, "Xplane",... |
"units" |
, "pixels",... |
"position" |
, [xs yx+h lslider h],... |
"fontunits" |
, "points",... |
"fontsize" |
, 9,... |
"horizontalalignment" , "center", ... |
|
"background" |
, [1 1 1], ... |
"tag" |
, "XplaneTitle" ... ); |
После выполнения этой функции в указанном месте (определяется значением, казанном в поле position) созданного графического окна (дескриптор созданного окна fig указан в поле parent) появляется текст (что указано в поле style); сама надпись указывается в поле string, размер текста и единицы измерения указаны в полях fontsize и fontunits соответственно. В поле position первые 2 элемента – это левый нижний угол блока, внутри которого располагается текст, а вторые 2 числа – ширина
17
блока и его высота, единицы измерения этих чисел указаны в поле units; в поле background - цвет фона в блоке (в данном случае белый), а в поле horizontalalignment – способ выравнивания текста внутри блока (влево, вправо или по центру)
Slider_Xplane=uicontrol("parent",fig,.. "style","slider",..
"Min",0,..
"Max",100,.. "Value",0,.. "units","pixels",..
"position" |
, [xs yx lslider h],... |
"tag" |
, "Xplane", ... |
"callback" |
, "update_xplane()" ... |
); |
|
После выполнения этой функции появится ползунок (что указано в поле style), задаются максимальное и минимальное значения (в данном случае 0 и 100), его значение в настоящий момент времени (поле Value). При движении ползунка вызывается функция update_xplane, что отображено в поле callback.
Ползунок расположится под надписью Xplane, что достигается путѐм задания соответствующих значений координат в поле position
Value_Xplane = uicontrol("parent",fig,.. "Position" , [xv yx lv h],...
"Style" , "text",...
"String" , "0",...
"BackgroundColor",[1 1 1]);
После этого справа от ползунка появится текст 0, который в процессе работы программы в дальнейшем будет изменяться, показывая, таким образом, значение параметра, который визуализируется при помощи ползунка.
Таким образом, после выполнения этих действий в графическом окне появится элемент, который наглядно показывает, как меняется одна из обобщѐнных координат рассматриваемого тела (X-координата центра масс тела). Далее, такие же дей-
18