Сначала вычисляю конечные составляющие скорости: вертикальную составляющую с учетом силы тяжести и коэффициента сопротивления воздуха, и вертикальную просто с учетом коэффициента сопротивления воздуха.
Потом вычисляю координаты, при этом беру скорость как среднее арифметическое от начальной/конечной скоростей.
Это для понимания ситуации, код MATLAB привожу ниже:
Код
function [out_x, out_y, out_spdx, out_spdy] = par_model(in_x, in_y, in_spdx, in_spdy, mass, R_x, R_y,sample_time)
out_spdx = in_spdx + R_x*in_spdx*in_spdx/mass;
out_spdy = in_spdy + ((R_y*in_spdy*in_spdy/mass)-9.8);
out_x = in_x + (out_spdx+in_spdx)*sample_time/2.0;
out_y = in_y + (out_spdy+in_spdy)*sample_time/2.0;
end
out_spdx = in_spdx + R_x*in_spdx*in_spdx/mass;
out_spdy = in_spdy + ((R_y*in_spdy*in_spdy/mass)-9.8);
out_x = in_x + (out_spdx+in_spdx)*sample_time/2.0;
out_y = in_y + (out_spdy+in_spdy)*sample_time/2.0;
end
Соответственно, тестовое окружение для него работает следующим образом. Беру большие массивы нулей, даю в первом значении начальные условия, задаю коэффициенты и массу, и последовательно забиваю массивы числами пока объект не достигнет земли (т.е. пока текущая координата y(i) не станет отрицательной или равной нулю) либо пока не кончится массив. Код ниже, содержит два теста:
Код
% INIT ARRAYS
x = zeros(10000,1,'double');
y = zeros(10000,1,'double');
vx = zeros(10000,1,'double');
vy = zeros(10000,1,'double');
%
%TEST ONE
%
H = 1000;
x(1) = 2;
y(1) = H;
vx(1) = 2;
vy(1) = 0;
K_x = -0.001;
K_y = 0.001;
m = 1;
sample_time = 0.002;
i = 1;
while y(i)>=0 && i<=10000
[x(i+1), y(i+1), vx(i+1), vy(i+1)] = par_model(x(i), y(i), vx(i), vy(i), m, K_x, K_y, sample_time);
i = i + 1;
end
subplot(2,1,1);
plot(x(1:i)+1i*y(1:i));
%
%TEST TWO
%
H = 100;
x(1) = 4;
y(1) = H;
vx(1) = 2;
vy(1) = 0;
K_x = 0.0001;
K_y = 0.003;
m = 1;
sample_time = 0.002;
i = 1;
while y(i)>=0 && i<=1000
[x(i+1), y(i+1), vx(i+1), vy(i+1)] = par_model(x(i), y(i), vx(i), vy(i), m, K_x, K_y, sample_time);
i = i + 1;
end
subplot(2,1,2);
plot(x(1:i)+1i*y(1:i));
x = zeros(10000,1,'double');
y = zeros(10000,1,'double');
vx = zeros(10000,1,'double');
vy = zeros(10000,1,'double');
%
%TEST ONE
%
H = 1000;
x(1) = 2;
y(1) = H;
vx(1) = 2;
vy(1) = 0;
K_x = -0.001;
K_y = 0.001;
m = 1;
sample_time = 0.002;
i = 1;
while y(i)>=0 && i<=10000
[x(i+1), y(i+1), vx(i+1), vy(i+1)] = par_model(x(i), y(i), vx(i), vy(i), m, K_x, K_y, sample_time);
i = i + 1;
end
subplot(2,1,1);
plot(x(1:i)+1i*y(1:i));
%
%TEST TWO
%
H = 100;
x(1) = 4;
y(1) = H;
vx(1) = 2;
vy(1) = 0;
K_x = 0.0001;
K_y = 0.003;
m = 1;
sample_time = 0.002;
i = 1;
while y(i)>=0 && i<=1000
[x(i+1), y(i+1), vx(i+1), vy(i+1)] = par_model(x(i), y(i), vx(i), vy(i), m, K_x, K_y, sample_time);
i = i + 1;
end
subplot(2,1,2);
plot(x(1:i)+1i*y(1:i));
Теперь собственно описание проблемы:
Попытка сгенерировать для этого кода вариант с фиксированной точкой приводит к следующей ошибке:
-------------- output variable : out_x --------------
Matrix dimensions must agree.
При этом графики строятся, но на них показан бред - объект вместо того, чтобы плавно падать, стремительно взлетает ввысь. Моделирование исходного кода заканчивается успешно и без ошибок/предупреждений.
Еще выяснилось, что:
Деление пополам (при вычислении среднего арифметического) кодер заменяет на смещение на разряд, при этом благополучно игнорируя знаковость. А поскольку для вертикальной координаты делимое, как правило, отрицательно - ясно почему взлетает объект.
Также выяснилось, что масса благополучно округляется с единицы на ноль, в результате чего моделирование готового fixed point тестового окружения приводит к куче ошибок типа деления на ноль.
Самое печальное, что попытки зафиксировать типы для значений не решают проблемы, выставлял для всех переменных ufix16_En24, ставил для массы целочисленный тип, но все равно в результатах получался бред.
Есть у кого предложения по решению этих проблем?