From 5c1bd9012a7eb4ad612f9f444f883d7b0e786afb Mon Sep 17 00:00:00 2001 From: Aleksey_K Date: Mon, 26 Aug 2024 08:57:08 +0900 Subject: [PATCH] add new classes --- classes/maskClass.js | 163 +++++++++++++++++++++++++++ peakClass.js => classes/peakClass.js | 0 spmClass.js => classes/spmClass.js | 0 userFunctions.js | 65 +++++++++-- 4 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 classes/maskClass.js rename peakClass.js => classes/peakClass.js (100%) rename spmClass.js => classes/spmClass.js (100%) diff --git a/classes/maskClass.js b/classes/maskClass.js new file mode 100644 index 0000000..2a6e331 --- /dev/null +++ b/classes/maskClass.js @@ -0,0 +1,163 @@ +export class maskClass { + constructor(args) { + this.spec = args.spec; + this.set = args.set; + this.filter = args.filter; + this.tol = args.tol; + this.color = args.color; + this.visible = args.visible; + this.canvas = NaN; + if (this.visible == true) { this.canvas = gtl.plots.add("Model") }; + } + + getModel() { + let __model = this.spec.base; //массив точек базовой линии + let imin = 0; //левая граница коридора + let imax = 0; //правая граница коридора + for (let i = 0; i < this.spec.peaks.length; i++) { + let freq = this.spec.peaks[i].freq; //получаем значение частоты гармоники из массива обнаруженных гармоник + let level = this.spec.peaks[i].level; //получаем значение уровня гармоники из массива обнаруженных гармоник + imin = Math.round((freq - freq * 0.5 * this.tol / 100) / this.spec.resolution); + imax = Math.round((freq + freq * 0.5 * this.tol / 100) / this.spec.resolution); + if (imax > this.spec.base.length) { imax = this.spec.base.length - 1 }; //проверяем выход границы за размер массива + for (let j = imin; j <= imax; j++) { __model[j] = this.spec.base[j] + level }; + }; + + if (this.visible == true) { + this.canvas.add({ + color: this.color, + name: this.spec.name + "_model", + x: this.spec.resolution, + y: __model + }); + }; //отрисовка модели спектра на plot + + return __model; + } //построение упрощенной модели спектра + + getMask(options) { + let __model = options.model; //массив точек спектра для сравнения с портретом + let __mask = options.mask.base; //массив точек базовой линии для построения портрета дефекта + let harms = options.harms; //кол-во гармоник портрета + if (options.freq * harms > options.mask.frequency) { harms = Math.trunc(options.mask.frequency / options.freq) }; //проверяем максимальное кол-во гармоник в портрете + let df = 0; //отношение ширины фильтра частотному разрешению спектра + let dl = options.lvl; //разность уровней гармонической и случайной составляющей вибрации + if (options.filter != 0) { + df = options.mask.frequency / options.filter.width; + dl = 10 * Math.log10((options.lvl ** 2) / df + 1); + }; + let k = options.coef; //коэффициент затухания + let x = 0; //индекс элемента массива для гармоники + let dx = 0; //коридор индексов + let xmin = 0; //левая граница коридора + let xmax = 0; //правая граница коридора + let correlation = 0; //коэффициент корреляции + + function corr(a, b) { + let X = 0; //аргумент 1 + let Y = 0; //аргумент 2 + let Z = 0; //аргумент 3 + let a_avg = a.reduce((acc, item) => (acc + item)) / a.length; //среднее значение массива 1 + let b_avg = b.reduce((acc, item) => (acc + item)) / b.length; //среднее значение массива 2 + + for (let i = 0; i < a.length; i++) { + X += (a[i] - a_avg) * (b[i] - b_avg); + Y += (a[i] - a_avg) ** 2; + Z += (b[i] - b_avg) ** 2; + }; + + if (X <= 0) { return 0 } else { return X / (Math.sqrt(Y) * Math.sqrt(Z)) }; + }; + + let arr1 = []; + let arr2 = []; + switch (options.type) { + case 0: //обычный ряд + for (let i = 1; i <= harms; i++) { + x = Math.trunc(i * options.freq / options.mask.resolution); //определяем инднекс элемента массива для гармоники + dx = Math.trunc(i * (options.freq * options.tol / 100) / options.mask.resolution); //коридор индексов массива для гармоники + xmin = x - Math.round(dx / 2); //определяем индекс левой границы коридора + xmax = x + Math.round(dx / 2); //определяем индекс правой границы коридора + + if (xmax > options.mask.base.length) { xmax = options.mask.base.length - 2 }; //проверяем выход границы за размер массива + for (let j = xmin; j <= xmax; j++) { __mask[j] = options.mask.base[j] + dl }; //записываем значение глубины модуляции для коридора + dl = dl - (k * dl); //снижаем глубину модуляции с коэффициентом затухания + + for (let j = xmin - 2; j <= xmax + 2; j++) { + arr1.push(__mask[j]); + arr2.push(__model[j]); + }; //формируем массивы портретной гармоники и спектра (модели) под портретом + correlation += corr(arr1, arr2); //рассчитываем корреляцию данных из массивов + }; + break; + case 1: //четные составляющие + for (let i = 1; i <= harms; i++) { + x = Math.trunc(i * options.freq / options.mask.resolution); //инднекс элемента массива для гармоники + dx = Math.trunc(i * (options.freq * options.tol / 100) / options.mask.resolution); //коридор индексов массива для гармоники + xmin = x - Math.round(dx / 2); //определяем индекс левой границы коридора + xmax = x + Math.round(dx / 2); //определяем индекс правой границы коридора + + if (xmax > options.mask.base.length) { xmax = options.mask.base.length - 2 }; //проверяем выход границы за размер массива + if (i % 2 > 0) { + for (let j = xmin; j <= xmax; j++) { __mask[j] = options.mask.base[j] + k * dl }; //записываем значение глубины модуляции для коридора (нечетная гармоника) + } else { + for (let j = xmin; j <= xmax; j++) { __mask[j] = options.mask.base[j] + dl }; //записываем значение глубины модуляции для коридора (четная гармоника) + dl = dl - (k * dl); //снижаем глубину модуляции с коэффициентом затухания + }; + + for (let j = xmin - 2; j <= xmax + 2; j++) { + arr1.push(__mask[j]); + arr2.push(__model[j]); + }; //формируем массивы портретной гармоники и спектра (модели) под портретом + correlation += corr(arr1, arr2); //рассчитываем корреляцию данных из массивов + }; + break; + default: + break; + }; + + let __result = correlation / harms; + + if (this.visible == true) { + this.canvas.add({ + color: options.color, + name: options.name + " (" + __result.toFixed(2) + ")", + x: options.mask.resolution, + y: __mask + }); + }; //отрисовка маски дефекта на plot + + return __result; + } //построение маски дефекта + + getResult() { + let __result = {}; //результат + let __rows = Object.keys(this.set); //массив ключей объекта (наименование портретов) + let __model = this.getModel(); //рисуем модель спектра и получаем массив его данных + + for (let i = 0; i < __rows.length; i++) { + let __name = __rows[i]; //имена портретов + let __arr = this.set[__name]; //массив значений + let __corr = this.getMask( + { + name: __name, //имя маски дефекта + model: __model, //модель спектра для анализа (объект) + mask: this.spec, //базовый спектр для построения портрета (объект) + filter: this.filter, //полосовой фильтр (для определения разницы амплитуд гармонической и случайной составляющей) + tol: this.tol, //коридор обнаружения гармоники на портрете, % + color: __arr[0], //цвет портрета в формате HEX + freq: __arr[1], //функциональная частота, Гц + harms: __arr[2], //кол-во гармоник в портрете, шт + lvl: __arr[3], //глубина модуляции сильного дефекта для портрета, % + type: __arr[4], //тип портрета (0 - обычный ряд, 1 - четные составляющие) + coef: __arr[5] //коэффициент затухания гармоник портрета: дефект (0.05 - 0.10), износ (0.30 - 0.50) + } + ); //рисуем маску дефекта и получаем значение корреляции + + if (__corr >= 0.5) { __result[__name] = __corr }; //добавляем данные в результат + gtl.log.info("Вероятность: " + __name, __corr); //выводим корреляцию гармоник в лог + }; + + return __result; + } //оценка состояния по маске дефекта +} \ No newline at end of file diff --git a/peakClass.js b/classes/peakClass.js similarity index 100% rename from peakClass.js rename to classes/peakClass.js diff --git a/spmClass.js b/classes/spmClass.js similarity index 100% rename from spmClass.js rename to classes/spmClass.js diff --git a/userFunctions.js b/userFunctions.js index 6b02915..31cf7a7 100644 --- a/userFunctions.js +++ b/userFunctions.js @@ -313,7 +313,7 @@ export function getAusp(args) { export function getSpen(args) { let __spen = gtl.add_spen(args.src); __spen.name = args.name; - __spen.color = args.color; + __spen.color = args.color; __spen.frequency = args.frequency; __spen.resolution = args.resolution; __spen.average = args.average; @@ -329,6 +329,57 @@ export function getSpen(args) { return __spen; }; //построение спектра огибающей +export function getDefectsSet(freq) { + //Название: [цвет, частота, кол-во гармоник, уровень сильного дефекта, тип ряда, коэфф затухания] + let __set = {}; + + switch (options.objectType) { + case 0: //объект не выбран + break; + case 1: //подшипник скольжения + + break; + case 2: //подшипник качения + __set = { + "Износ наружного кольца": [0x42AAFF, BPFO(freq), 6, 0.06, 0, 0.3], + "Перекос наружного кольца": [0x4285B4, BPFO(freq), 4, 0.06, 1, 0.1], + "Дефект наружного кольца": [0x6A5ACD, BPFO(freq), 6, 0.06, 0, 0.07], + "Износ внутреннего кольца": [0x89AC76, FREQ(freq), 6, 0.06, 0, 0.3], + "Перекос внутреннего кольца": [0x34C924, FREQ(freq), 6, 0.06, 1, 0.1], + "Дефект внутреннего кольца": [0x008000, BPFI(freq), 6, 0.06, 0, 0.07], + "Дефект тел качения": [0xFFA000, BSF(freq), 5, 0.06, 0, 0.3], + "Износ тел качения и сепаратора": [0xFF2400, FTF(freq), 4, 0.06, 0, 0.5] + }; + break; + case 3: //ШВП + + break; + case 4: //редуктор + + break; + case 5: //ременная передача + + break; + case 6: //зубчатый ремень + + break; + case 7: //помпа (насос) + + break; + case 8: //планетарый редуктор + + break; + case 9: //турбина + + break; + case 10: //электродвигатель + + break; + }; + + return __set +}; //набор предполагаемых дефектов + export function createTools(options) { let __spec = options.spec; //источник данных спектра let __set = {}; //источник данных для построения частотных линий @@ -361,9 +412,9 @@ export function createTools(options) { let __color = __arr[0]; //цвет ряда в формате HEX let __freq = __arr[1]; //расчетная частота let __count = __arr[2]; //количество гармоник - let __mod = __arr[3]; //модулирующая частота - let __lvl = __arr[4]; //пороговый уровень сильного дефекта - + let __lvl = __arr[3]; //пороговый уровень сильного дефекта + let __mod = __arr[6]; //модулирующая частота + let __row = __tools.harms.add( { frequency: __freq, //функциональная частота @@ -375,7 +426,7 @@ export function createTools(options) { ); __row.name = __name; - if (options.mod != 0) { + if (__mod != undefined) { __row.modulate( { frequency: __mod, //частота амплитудной модуляции @@ -452,7 +503,7 @@ export function getStdMeasures(options) { let __ptp = gtl.add_value_peak_to_peak(src); __ptp.time = __time; __ptp.avg_cnt = __avg; - + return __ptp; }; //получение размаха @@ -522,4 +573,4 @@ export function getStdMeasures(options) { }; return __result; -}; //измерение стандартных параметров \ No newline at end of file +}; //измерение стандартных параметров