110 lines
6.3 KiB
JavaScript
110 lines
6.3 KiB
JavaScript
export function getResponse(args) {
|
||
let force = args.spec_force; //спектр силы
|
||
let vibro = args.spec_vibro; //спектр вибрации
|
||
let type = args.type; //способ вычисления отклика
|
||
let view = args.view; //способ отображения спектра в линейных единицах или дБ
|
||
|
||
/* Алгоритм
|
||
1. Получить спектры ускорения и силы в комплексном виде (вибропреобразователь и молоток).
|
||
2. Преобразовать спектр силы (молотка) в комплексно-сопряжённый вид.
|
||
3. Получить кросс-спектр (перекрёстный) между ускорением и силой.
|
||
4. Вычислить деление кросс-спектра на спектр силы.
|
||
*/
|
||
|
||
/* Кросс-спектры
|
||
Сигнал силы в комплексно-сопряжённом виде
|
||
сигнал вибрации умножается на сигнал силы, а НЕ наоборот
|
||
умножение комплексных чисел по формуле:
|
||
(a1+b1i)*(a2+b2i)=(a1*a2-b1*b2)*(a1*b2+b1*a2)i
|
||
(a1*a2-b1*b2) - действительная часть
|
||
(a1*b2+b1*a2)i - мнимая часть
|
||
*/
|
||
|
||
let n = force.data.length; // длина массива спектра
|
||
let cross_real = new Float64Array(n); // типизированный массив для действительной части
|
||
let cross_imag = new Float64Array(n); // типизированный массив для мнимой части
|
||
|
||
for (let i = 0; i < n; i++) {
|
||
const vReal = vibro.real[i]; // действительная часть спектра вибрации
|
||
const vImag = vibro.imag[i]; // мнимая часть спектра вибрации
|
||
const fReal = force.real[i]; // действительная часть спектра силы
|
||
const fImag = -force.imag[i]; // мнимая часть спектра силы сразу берём с обратным знаком
|
||
|
||
cross_real[i] = vReal * fReal - vImag * fImag;
|
||
cross_imag[i] = vReal * fImag + vImag * fReal;
|
||
}
|
||
|
||
/* Вычисление частотного отклика
|
||
деление комплексных чисел по формуле:
|
||
(a+bi)/(c+di)=(a*c-b*d)*(a*d+b*c)i
|
||
(a*c-b*d) - действительная часть
|
||
(a*d+b*c)i - мнимая часть
|
||
*/
|
||
let resp_real = new Float64Array(n); // типизированный массив для действительной части
|
||
let resp_imag = new Float64Array(n); // типизированный массив для мнимой части
|
||
|
||
// ОШИБКА в моей формуле вычисления частотного отклика
|
||
// ИПРАВИЛ на:
|
||
// деление комплексных чисел по формуле:
|
||
// (a+bi)/(c+di)=(a*c + b*d)/(c^2 + d^2) + (c*b - a*d)/(c^2 + d^2)i
|
||
// (a*c + b*d)/(c^2 + d^2) - действительная часть
|
||
// (c*b - a*d)/(c^2 + d^2)i - мнимая часть
|
||
// ПЕРЕВОД формулы в используемые переменные:
|
||
// const CF = fReal * fReal + fImag * fImag;
|
||
// resp_real[i] = (cReal * fReal + cImag * fImag) / CF;
|
||
// resp_imag[i] = (fReal * cImag - cReal * fImag) / CF;
|
||
|
||
if (type == 0) {
|
||
// Вариант 1: Частотный отклик как деление кросс-спектра вибрации и силы на автоспектр силы
|
||
// (Канал[0] & Канал[j]) / Канал[0]
|
||
for (let i = 0; i < n; i++) {
|
||
const cReal = cross_real[i]; // действительная часть кросс спектра
|
||
const cImag = cross_imag[i]; // мнимая часть кросс спектра
|
||
const fReal = force.real[i]; // действительная часть спектра силы
|
||
const fImag = force.imag[i]; // мнимая часть спектра силы
|
||
|
||
const CF = fReal * fReal + fImag * fImag;
|
||
resp_real[i] = (cReal * fReal + cImag * fImag) / CF;
|
||
resp_imag[i] = (fReal * cImag - cReal * fImag) / CF;
|
||
}
|
||
} else {
|
||
// Вариант 2: Частотный отклик как деление автоспектра вибрации на автоспектр силы
|
||
// Канал[j] / Канал[0]
|
||
for (let i = 0; i < n; i++) {
|
||
const vReal = vibro.real[i]; // действительная часть спектра вибрации
|
||
const vImag = vibro.imag[i]; // мнимая часть спектра вибрации
|
||
const fReal = force.real[i]; // действительная часть спектра силы
|
||
const fImag = force.imag[i]; // мнимая часть спектра силы
|
||
|
||
const VF = vReal * vReal + fImag * fImag;
|
||
resp_real[i] = (vReal * fReal - vImag * fImag) / VF;
|
||
resp_imag[i] = (fReal * vImag + vReal * fImag) / VF;
|
||
}
|
||
}
|
||
|
||
// запись массива амплитуды и фазы
|
||
let resp_ampl = new Float64Array(n); // типизированный массив для амплитуды
|
||
let resp_phase = new Float64Array(n); // типизированный массив для фазы
|
||
const RAD_TO_DEG = 180 / Math.PI; //перевод радиан в градусы
|
||
|
||
for (let i = 0; i < n; i++) {
|
||
const rReal = resp_real[i]; // действительная часть спектра отклика
|
||
const rImag = resp_imag[i]; // мнимая часто спектра отклика
|
||
|
||
resp_ampl[i] = Math.sqrt(rReal * rReal + rImag * rImag);
|
||
if (view > 0) { resp_ampl = resp_ampl.map((item) => (item = 20 * Math.log10(item / 1e-6))) }; //переводим в дБ
|
||
resp_phase[i] = Math.atan2(rImag, rReal) * RAD_TO_DEG;
|
||
}
|
||
|
||
// Приводим фазу к диапазону [0°, 360°]
|
||
for (let i = 0; i < n; i++) {
|
||
resp_phase[i] = resp_phase[i] % 360;
|
||
if (resp_phase[i] < 0) { resp_phase[i] += 360 }
|
||
}
|
||
|
||
return {
|
||
data: resp_ampl,
|
||
phase: resp_phase,
|
||
resolution: force.resolution
|
||
}
|
||
}; //рассчет перекрестного спектра
|