Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Методическое пособие 366

.pdf
Скачиваний:
5
Добавлен:
30.04.2022
Размер:
1.03 Mб
Скачать

else state_changed=%t;

end

(в противном случае, признак изменения принимает значение 1, а за изменение положения тела на рисунке будет отвечать другая функция, см. функцию show)

endfunction

Следом идут 6 функций, вызываемых движением ползунка (по числу обобщѐнных координат). Входным аргументом служит значение соответствующей обобщѐнной координаты.

function update_xplane(xplane) global body_controls

(глобальная переменная, которая была определена в функции body_gui и содержащая в себе переменные, управляющие ползунком и текстом справа от ползунка, показывающим значение соответствующей обобщѐнной координаты)

Slider_Xplane=body_controls(1,1)

Value_Xplane=body_controls(1,2)

(первая из этих переменных отвечает за ползунок, а вторая – за текст)

if argn(2)==1 then Slider_Xplane.Value=xplane*100/0.2;

(если у функции один аргумент, xplane, то это значение передаѐтся переменной, управляющей ползунком, и ползунок перемещается на соответствующую позицию. Множитель 100/0.2 определяет, какому значению координаты соответствует положение ползунка, иными словами, это масштабный коэффициент. Так, в данном случае крайнему левому положению ползунка будет соответствовать значение координаты, равное 0, а крайнему правому – значение 0.2; шаг ползунка составляет

0.002) else

xplane=Slider_Xplane.Value xplane=xplane*0.2/100;

29

end

(есть второй вариант, когда у этой функции нет входных аргументов. Такая ситуация возникает, когда ползунок при инициализации передвигается вручную. В этом случае по значению, определяющему местоположение ползунка, определяется значение соответствующей координаты путѐм умножения на множитель, обратный тому, который был описан выше)

Value_Xplane.String=msprintf("%.3f",xplane)

(переменной, управляющей текстом, передаѐтся значение координаты, которое преобразовывается в текст)

update_state(1,xplane) endfunction

Таким образом, у этой функции возможны 2 варианта вызова: при ручном управлении ползунком она вызывается без аргументов и по значению, определяющему положение ползунка, определяется координата, которая, в свою очередь, передаѐтся в функцию update_state, которая в этом случае отображает тело на рисунке, учитывая произведѐнные изменения координат. Во втором случае на вход функции подаѐтся значение координаты, и в этом случае уже функция управляет ползунком. Аналогичным образом определяются остальные 5 функций, с тем лишь различием, что в функциях, отвечающих за угловые координаты, другой масштабный коэффициент.

function update_yplane(yplane) global body_controls Slider_Yplane=body_controls(2,1) Value_Yplane=body_controls(2,2) if argn(2)==1 then

Slider_Yplane.Value=yplane*100/0.2; else

yplane=Slider_Yplane.Value yplane=yplane*0.2/100

end Value_Yplane.String=msprintf("%.3f",yplane)

30

update_state(2,yplane) endfunction

function update_height(h) global body_controls

Slider_Height=body_controls(3,1) Value_Height=body_controls(3,2) if argn(2)==1 then

Slider_Height.Value=h*100/0.2; else

h=Slider_Height.Value h=h*0.2/100

end Value_Height.String=msprintf("%.3f",h) update_state(3,h)

endfunction

function update_theta(t) global body_controls

Slider_Theta=body_controls(4,1) Value_Theta=body_controls(4,2) if argn(2)==1 then

Slider_Theta.Value=t*10000/360; else

t=Slider_Theta.Value t=t*360/10000;

end Value_Theta.String=msprintf("%.3f",t) update_state(4,t)

endfunction

function update_phi(p) global body_controls

Slider_Phi=body_controls(5,1)

Value_Phi=body_controls(5,2) if argn(2)==1 then

Slider_Phi.Value=p*10000/360;

31

else p=Slider_Phi.Value p=360*p/10000

end Value_Phi.String=msprintf("%.3f",p) update_state(5,p)

endfunction

function update_psi(p) global body_controls

Slider_Psi=body_controls(6,1) Value_Psi=body_controls(6,2) if argn(2)==1 then

Slider_Psi.Value=p*10000/360; else

p=Slider_Psi.Value p=360*p/10000

end Value_Psi.String=msprintf("%.3f",p) update_state(6,p)

endfunction

Далее идут шесть функций, вызываемых посредством нажатия на соответствующие кнопки.

function body_start()

(функция вызывается путѐм нажатия на кнопку Start) global Stop;Stop=%f;

(при нажатии на кнопку Start признак остановки Stop принимает значение 0)

show();

(вызывается функция, основным назначением которой является решение системы дифференциальных уравнений и построение графического изображения тела с новыми координатами, описание см. ниже)

endfunction

32

function body_stop() global Stop;Stop=%t

endfunction

(функция вызывается путѐм нажатия на кнопку Stop. Признак остановки принимает значение 1 и тело останавливается) function body_reinit()

(функция, вызывающаяся нажатием кнопки Reinit. Возвращает тело в исходное положение)

global y0 y1 Stop Stop=%t

(после вызова функции Stop принимает значение 1 и тело останавливается)

y1=y0

(значению текущего вектора состояния присваивается значение начального вектора состояния)

update_xplane(0) update_yplane(0) update_height(0) update_theta(0) update_phi(0) update_psi(0)

(изображение тела возвращается в начальное положение. Аргументами этих функций являются начальные значения обобщѐнных координат)

endfunction

Далее идут 6 функций, отвечающих за графическое построение зависимости обобщѐнных координат от времени:

function plot_Xplane()

(вызывается путѐм нажатия на кнопку Xplot. Строит график зависимости координаты Xplane от времени)

global Stop XPLANE

(переменная XPLANE – массив, содержащий значения координаты X центра масс тела в каждый момент времени, в который

33

происходит интегрирование системы дифференциальных уравнений. Массив заполняется в функции show, см. ниже)

if (Stop == %t) then scf(666); clf(); b=gca();

(функция вызывается только после остановки тела; если признак остановки равен 1, то создаѐтся новое графическое окно и дескриптор осей)

nn = size(XPLANE, '*');

(запоминается размер массива с координатами центра масс тела в каждый момент времени)

b.x_label.text="Time"; b.y_label.text="X";

(подписываются оси: под осью абсцисс будет стоять надпись Time, а слева от оси ординат – надпись X)

pp = 0.05:0.05:nn/20; plot(pp, XPLANE);

(переменная pp – массив, содержащий время интегрирования дифференциальных уравнений движения в секундах. Интегрирование происходит каждые 0.05 секунд. После этого строится график зависимости переменной XPLANE от времени)

end endfunction

Аналогичным образом строятся функции для построения графиков зависимости остальных обобщѐнных координат от времени.

function plot_Yplane() global Stop YPLANE if (Stop == %t) then

scf(666); clf(); b=gca(); nn = size(YPLANE, '*'); b.x_label.text="Time"; b.y_label.text="Y";

pp = 0.05:0.05:nn/20; plot(pp, YPLANE);

end

34

endfunction

function plot_Height() global Stop HEIGHT if (Stop == %t) then

scf(666); clf(); b=gca(); nn = size(HEIGHT, '*'); b.x_label.text="Time"; b.y_label.text="Height"; pp = 0.05:0.05:nn/20; plot(pp, HEIGHT);

end endfunction

function plot_Theta() global Stop THETA if (Stop == %t) then

scf(666); clf(); b=gca(); nn = size(THETA, '*'); b.x_label.text="Time"; b.y_label.text="Theta"; pp = 0.05:0.05:nn/20; plot(pp, THETA);

end endfunction function plot_Psi()

global Stop PSI

if (Stop == %t) then scf(666); clf(); b=gca(); nn = size(PSI, '*'); b.x_label.text="Time"; b.y_label.text="Psi"; pp = 0.05:0.05:nn/20; plot(pp, PSI);

end endfunction

35

function plot_Phi() global Stop PHI

if (Stop == %t) then scf(666); clf(); b=gca(); nn = size(PHI, '*'); b.x_label.text="Time"; b.y_label.text="Phi"; pp = 0.05:0.05:nn/20; plot(pp, PHI);

end endfunction

И, наконец, последняя функция, основными задачами которой являются решение системы уравнений движения и анимация. Эта функция вызывается внутри функции body_start (т.е. она вызывается после нажатия кнопки Start)

function show()

global y1 state_changed init Stop XPLANE YPLANE HEIGHT PSI PHI THETA

(глобальные переменные – текущий вектор состояния системы, признаки изменения состояния, инициализации и остановки, а также массивы с обобщѐнными координатами)

y=y1;

(текущий вектор состояния помещается в промежуточную переменную)

init=%f; dt=0.05

(задаются признак инициализации – 0, т.к. нажата кнопка Start и шаг интегрирования дифференциальных уравнений)

[y,w,iw]=ode(y,0,dt,body_dyn); y1=y;

(первый шаг интегрирования: аргументы – вектор с начальными условиями для решения задачи Коши, последующие 2 аргумента – начало и конец временного интервала интегрирования, четвѐртый аргумент – вектор из правых частей уравнений системы, выходные аргументы – вектор решения и 2 вектора с

36

параметрами интегрирования. После интегрирования в текущий вектор состояния помещается вектор решения)

realtimeinit(dt)

(задаются временные единицы; это нужно для регулировки скорости анимации – чем меньше параметр, тем быстрее будет двигаться тело на рисунке; в данном случае за временную единицу взят шаг интегрирования)

t0=dt

(осуществляется переход к второму шагу интегрирования – задаѐтся начало временного интервала второго шага интегрирования)

k=1

(количество шагов интегрирования, прошедших с момента нажатия кнопки Start)

while %t

(запускается бесконечный цикл, из которого можно выйти только с помощью команды break)

if state_changed then

[y,w,iw]=ode(y1,t0,t0+dt,body_dyn);y1=y; else

[y,w,iw]=ode(y,t0,t0+dt,body_dyn,w,iw);y1=y; end

(если состояние не поменялось, то интегрирование производится с теми же параметрами, что и на прошлом шаге (переменные w,iw в числе аргументов функции ode) и после интегрирования в текущий вектор состояния помещается вектор решения; если состояние поменялось, то эти переменные в качестве аргументов не используются. Таким образом, после выполнения этого условного оператора в переменной y1 хранится текущий вектор состояния системы после интегрирования)

if Stop then init=%t,break,end

if ~is_handle_valid(H) then break; end

(выход из цикла происходит только в тех случаях, если нажать на кнопку Stop или когда дескриптор графического объекта

37

становится недействительным (например, при закрытии графического окна))

set_body(H,y);

(изображается тело в положении, соответствующем текущему вектору состояния)

XPLANE(k)=y(1); YPLANE(k)=y(3); HEIGHT(k)=y(5); THETA(k)=y(7)*180/%pi; PHI(k)=modulo(y(9)*180/%pi,360); PSI(k)=modulo(y(11)*180/%pi,360);

(заполняются массивы с обобщѐнными координатами в каждый момент времени: в последних трѐх случаях производится перевод из радиан в градусы, к тому же в последних двух случаях значения берутся по модулю 360; это сделано на тот случай, если соответствующие углы меняются настолько, что их значения выходят за пределы 360 градусов)

if %t then update_xplane(y(1)) update_yplane(y(3)) update_height(y(5)) update_theta(y(7)*180/%pi)

update_phi(modulo(y(9)*180/%pi,360)) update_psi(modulo(y(11)*180/%pi,360))

end

(производится управление соответствующими ползунками – см. описание соответствующих функций в случае, когда у них есть входной аргумент)

k=k+1;t0=t0+dt;

(переход к следующей итерации – обновляется счѐтчик числа интегрирований, перемещается начало временного интервала интегрирования)

realtime(k);

38