From 5b0d58c3f7f35f61c0a0437bac3ff708db57fe61 Mon Sep 17 00:00:00 2001 From: feiyu02 <risaku@163.com> Date: 星期四, 18 七月 2024 17:34:16 +0800 Subject: [PATCH] 1. 修正实时走航数据平滑处理算法,PM2.5、PM10、VOC采用新的修正算法 --- src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt | 135 ++++++++++++++++++++++++++++++++++----------- 1 files changed, 102 insertions(+), 33 deletions(-) diff --git a/src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt b/src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt index 08c1e5e..40bfa5a 100644 --- a/src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt +++ b/src/main/kotlin/com/flightfeather/uav/model/epw/EPWDataPrep.kt @@ -1,50 +1,77 @@ package com.flightfeather.uav.model.epw import com.flightfeather.uav.common.utils.DateUtil -import com.flightfeather.uav.common.utils.GsonUtils -import com.flightfeather.uav.lightshare.bean.CompanySOP import com.flightfeather.uav.lightshare.bean.DataVo import com.flightfeather.uav.model.BaseDataPrep +import com.flightfeather.uav.model.BaseSOP import com.flightfeather.uav.socket.bean.AirData import com.flightfeather.uav.socket.bean.AirDataPackage import com.flightfeather.uav.socket.eunm.FactorType +import com.flightfeather.uav.socket.eunm.UWDeviceType import kotlin.math.max import kotlin.math.min import kotlin.math.round import kotlin.math.sqrt -class EPWDataPrep : BaseDataPrep<DataVo, CompanySOP>() { +/** + * 鏁版嵁骞虫粦棰勫鐞� + * 瀵逛簬鏈�鏂扮殑涓�缁勬暟鎹紝鏍规嵁鍏朵箣鍓嶈繛缁殑鑻ュ共鏁版嵁锛岃繘琛屾暟鎹钩婊戝鐞� + * @Date 2024.5.16 + */ +class EPWDataPrep(val deviceType: UWDeviceType? = UWDeviceType.GRID) : BaseDataPrep<DataVo, BaseSOP>() { // 鍚戝墠妫�绱㈢殑鏁版嵁璁板綍鏁� private val ncal = 15 + // 鏍囧噯宸�嶆暟鍙傛暟 private val nstd = 3 + // 鍧囧�煎�嶆暟鍙傛暟 private val xratio = 3 - // 闇�瑕佸鐞嗙殑鍥犲瓙绫诲瀷 - private val calTypes = -// emptyList<String>() - WeightType.prep + + // 闇�瑕佸钩婊戝鐞嗙殑鍥犲瓙绫诲瀷 + private var calTypes = when (deviceType) { + UWDeviceType.VEHICLE, + UWDeviceType.UAV, + UWDeviceType.BOAT, + -> WeightType.prepUnderWay + UWDeviceType.GRID -> WeightType.prepFixed + else -> WeightType.prepFixed + } + + // 鍙渶瑕佹鏌ヨ寖鍥村拰鍙樺寲骞呭害鐨勫洜瀛愮被鍨� + private var rangeTypes = listOf( + FactorType.PM25.des, + FactorType.PM10.des, + FactorType.VOC.des + ) + + // 鏃犻渶淇鐨勫洜瀛愮被鍨� + private var noCalTypes = listOf( + FactorType.TEMPERATURE.des, + FactorType.HUMIDITY.des, + FactorType.LNG.des, + FactorType.LAT.des, + FactorType.VELOCITY.des, + FactorType.TIME.des, + FactorType.WIND_DIRECTION.des, + FactorType.HEIGHT.des + ) private val lastData = mutableListOf<DataVo>() override fun mDataPrep(mDataList: List<DataVo>): List<DataVo> { mDataList.forEach { - it.values?.forEach v@{a -> + it.values?.forEach v@{ a -> if (!calTypes.contains(a.factorName)) return@v val range = FactorType.getRange(a.factorName) ?: return@v // 鍒ゆ柇鏁版嵁鏄惁鍦ㄥ悎鐞嗚寖鍥村唴 - if (a.factorData ?: 0.0 < range.first || a.factorData ?: 0.0 > range.second) { + if (a.factorData != null && (a.factorData!! < range.first || a.factorData!! > range.second)) { a.factorData = null } } } - -// val newDataList = mutableListOf<DataVo>() -// mDataList.forEach { -// newDataList.add(it.copy()) -// } var i = ncal if (lastData.isNotEmpty()) { @@ -60,7 +87,7 @@ if (it.factorData!! > vMax) { val lastDataIndex = i - val thisIndex = if (i-ncal<0) 0 else i - ncal + val thisIndex = if (i - ncal < 0) 0 else i - ncal val list = mutableListOf<DataVo>() if (lastDataIndex < lastData.size) { list.addAll(lastData.subList(lastDataIndex, lastData.lastIndex + 1)) @@ -99,15 +126,22 @@ return mDataList } - override fun sopPrep(sopList: List<CompanySOP>): List<CompanySOP> { + override fun sopPrep(sopList: List<BaseSOP>): List<BaseSOP> { return sopList } + + /** + * 瀹炴椂鏁版嵁骞虫粦澶勭悊 + */ fun mDataPrep2(dataPackage: AirDataPackage): List<DataVo> { val vo = dataPackage.toDataVo() return mDataPrep2(listOf(vo)) } + /** + * 瀹炴椂鏁版嵁骞虫粦澶勭悊 + */ fun mDataPrep2(mDataList: List<DataVo>): List<DataVo> { var i = ncal if (lastData.isNotEmpty()) { @@ -116,14 +150,12 @@ while (i < mDataList.size) { for (y in mDataList[i].values?.indices ?: 0..0) { val it = mDataList[i].values?.get(y) ?: continue - - if (!calTypes.contains(it.factorName)) continue val vMax = FactorType.getVMax(it.factorName) ?: continue -// it.factorData ?: continue + it.factorData ?: continue if (it.factorData!! > vMax) { val lastDataIndex = i - val thisIndex = if (i-ncal<0) 0 else i - ncal + val thisIndex = if (i - ncal < 0) 0 else i - ncal val list = mutableListOf<DataVo>() if (lastDataIndex < lastData.size) { list.addAll(lastData.subList(lastDataIndex, lastData.lastIndex + 1)) @@ -135,17 +167,26 @@ // 鍘婚櫎鏃犳晥鍊肩殑鏍囧噯宸� val std = standardDeviation(avg.first, list, it.factorName) // 鍚堢悊鏈�澶у�� - val max = max(avg.first + std * nstd, avg.first + avg.first * xratio) + var maxValue = max(avg.first + std * nstd, avg.first + avg.first * xratio) + maxValue = max(maxValue, FactorType.getRange(it.factorName)?.second ?: .0) // 鍚堢悊鏈�灏忓�� - val min = min(avg.first - std * nstd, avg.first / (1 + xratio)) + val minValue = min(avg.first - std * nstd, avg.first / (1 + xratio)) - // 鏁版嵁涓嶅浜庡悎鐞嗚寖鍥村苟涓旀湁鏁堜釜鏁拌揪鏍囨椂锛岄噰鐢ㄨ绠楁墍寰楀潎鍊间唬鏇垮師濮嬪�� - if (avg.second > max(ncal / 5, 2) - && (it.factorData!! < min || it.factorData!! > max) - ) { - // 鍘熷鏁版嵁 -// it.factorData = null - it.factorData = avg.first + // 鍒ゆ柇鐩戞祴鍥犲瓙鏄惁闇�瑕佽繘琛屽钩婊戝鐞嗭紝 + if (calTypes.contains(it.factorName)) { + // 鏁版嵁涓嶅浜庡悎鐞嗚寖鍥村苟涓旀湁鏁堜釜鏁拌揪鏍囨椂锛岄噰鐢ㄨ绠楁墍寰楀潎鍊间唬鏇垮師濮嬪�� + if (avg.second > max(ncal / 5, 2) + && (it.factorData!! < minValue || it.factorData!! > maxValue) + ) { + it.factorData = avg.first + } + } + // 鍒ゆ柇閲忕骇鏄惁鍦ㄥ悎鐞嗚寖鍥村唴浠ュ強鍙樺寲鍊嶇巼鏄惁鍦ㄥ悎鐞嗚寖鍥村唴 + else if (rangeTypes.contains(it.factorName)) { + if (isInRange(it) != true || excessiveChange(it) == true) { + // 閲囩敤璁$畻鎵�寰楀潎鍊间唬鏇垮師濮嬪�� + it.factorData = avg.first + } } } } @@ -164,7 +205,7 @@ if (lastData.isNotEmpty() && newList.isNotEmpty()) { val lastTime = DateUtil.instance.StringToDate(lastData.last().time) val thisTime = DateUtil.instance.StringToDate(newList.first().time) - if (thisTime?.time?.minus(lastTime?.time ?: 0) ?: 0 >= (60 * 1000)) { + if ((thisTime?.time?.minus(lastTime?.time ?: 0) ?: 0) >= (60 * 1000)) { lastData.clear() } } @@ -182,7 +223,7 @@ * @param list 鐩戞祴鏁版嵁 * @return 鍧囧�煎拰鏈夋晥鏁版嵁涓暟 */ - private fun average(list: List<DataVo>, factorName:String?): Pair<Double, Int>? { + private fun average(list: List<DataVo>, factorName: String?): Pair<Double, Int>? { var t = 0.0 var c = 0 list.forEach { @@ -191,7 +232,7 @@ if (f?.factorName == factorName) { val range = FactorType.getRange(f?.factorName) ?: continue //鍒ゆ柇鏁版嵁鏄惁鍦ㄥ悎鐞嗚寖鍥村唴 - if (f?.factorData ?: 0.0 in range.first..range.second) { + if ((f?.factorData ?: 0.0) in range.first..range.second) { t += f?.factorData!! c++ } @@ -224,7 +265,7 @@ val f = it.values?.get(i) if (f?.factorName == factorName) { val range = FactorType.getRange(f?.factorName) ?: continue - if (f?.factorData ?: 0.0 in range.first..range.second) { + if ((f?.factorData ?: 0.0) in range.first..range.second) { t += (f?.factorData!! - avg) * (f.factorData!! - avg) c++ } @@ -239,4 +280,32 @@ sqrt(t / (c - 1)) } } + + /** + * 鍒ゆ柇鏁版嵁鏄惁鍦ㄦ甯搁噺绋嬪唴 + */ + private fun isInRange(airData: AirData): Boolean? { + val range = FactorType.getRange(airData.factorName) ?: return null + //鍒ゆ柇鏁版嵁鏄惁鍦ㄥ悎鐞嗚寖鍥村唴 + return (airData.factorData ?: 0.0) in range.first..range.second + } + + /** + * 鍒ゆ柇杩炵画鐨勬暟鎹噺绾т笂鍗囧箙搴︽槸鍚﹁繃澶� + */ + private fun excessiveChange(airData: AirData): Boolean? { + airData.factorData ?: return null + if (lastData.isEmpty()) return false + val latestData = lastData.last() + // 缁撴灉鍊嶇巼 + var m = 1.0 + for (i in latestData.values?.indices ?: 0..0) { + val f = latestData.values?.get(i) + if (f?.factorName == airData.factorName) { + m = airData.factorData!!.div(f?.factorData ?: airData.factorData!!) + break + } + } + return m > FactorType.getMultiplier(airData.factorName) + } } \ No newline at end of file -- Gitblit v1.9.3