// diff.go package diff import ( "fmt" "math" "strconv" "strings" ) type KalmanVarDiff struct { Kf *KalmanFilter StartDiff float64 MinDiff float64 MaxDiff float64 TargetInterval float64 MhsEst float64 DiffEst float64 } type KalmanFilter struct { X float64 // 估计的状态 P float64 // 状态协方差 F float64 // 状态转移矩阵 H float64 // 观测矩阵 Q float64 // 过程噪声协方差 R float64 // 观测噪声协方差 K float64 // 卡尔曼增益 } func NewKalmanFilter(init_mhs float64, init_state_p float64) *KalmanFilter { x := init_mhs p := init_state_p f := 1.0 h := 1.0 q := 0.01 r := init_mhs * 3 //r := 1.0 return &KalmanFilter{ X: x, P: p, F: f, H: h, Q: q, R: r, } /* return &KalmanFilter{ X: 1.0, P: 1.0, F: 1.0, H: 1.0, Q: 0.1, R: 1.0, }*/ } func (kf *KalmanFilter) Update(measurement float64) (float64, float64) { kf.R = measurement * 2 // 预测 p := kf.X*kf.Q + kf.P // 计算卡尔曼增益 kf.K = p / (p + kf.R + 1) // 更新状态估计 if measurement >= kf.X { kf.X = kf.X + kf.K*(measurement-kf.X) } else { kf.X = kf.X - kf.K*(kf.X-measurement) } // 更新协方差矩阵 kf.P = (1 - kf.K) * p // 自适应调整过程噪声和观测噪声 //kf.adapt() return kf.X, kf.P } func (kf *KalmanFilter) adapt() { // 自适应调整参数 if kf.P > 10.0 { kf.Q *= 1.1 // 增加过程噪声 } else { kf.Q *= 0.9 // 减少过程噪声 } if kf.K > 0.5 { kf.R *= 1.1 // 增加观测噪声 } else { kf.R *= 0.9 // 减少观测噪声 } } func (kd *KalmanVarDiff) Init(startDiff float64, minDiff float64, maxDiff float64, targetTime float64) { kd.StartDiff = startDiff kd.MinDiff = minDiff kd.MaxDiff = maxDiff kd.TargetInterval = targetTime kd.DiffEst = startDiff kd.MhsEst = startDiff / targetTime kd.Kf = NewKalmanFilter(startDiff/targetTime, 1.0) } func (kd *KalmanVarDiff) DeInit() { } // 提取科学计数法有效数字(整数部分和一位小数)及指数,并合并为新的浮点数 func extractAndCombine(num float64) float64 { // 将浮点数格式化为科学计数法 scientificStr := fmt.Sprintf("%.10e", num) // 分离小数部分和指数部分 parts := strings.Split(scientificStr, "e") if len(parts) != 2 { fmt.Println("Error: unexpected scientific notation format") return 0 } // 处理小数部分 decimalPart := parts[0] exponentPart := parts[1] // 去除小数部分前的 "0." decimalPart = strings.TrimPrefix(decimalPart, "0.") // 提取整数部分和一位小数 decimalParts := strings.Split(decimalPart, ".") if len(decimalParts) < 2 { decimalPart = decimalParts[0] + ".0" // 没有小数部分时,添加 ".0" } else { decimalPart = decimalParts[0] + "." + decimalParts[1][:1] // 只取一位小数 //decimalPart = decimalParts[0] } // 将指数部分转换为整数 exponent, err := strconv.Atoi(exponentPart) if err != nil { fmt.Println("Error parsing exponent:", err) return 0 } // 计算新的浮点数 newNumber := (func() float64 { digit, err := strconv.ParseFloat(decimalPart, 64) if err != nil { fmt.Println("Error parsing decimal part:", err) return 0 } return digit * math.Pow(10, float64(exponent)) })() return newNumber } func (kd *KalmanVarDiff) Handler(diff float64, interval float64) (float64, float64) { //newx, newp := kd.Kf.Update(kd.DiffEst / interval) newx, newp := kd.Kf.Update(diff / interval) kd.MhsEst = newx newdiff := newx * kd.TargetInterval kd.DiffEst = newdiff newdiff2 := extractAndCombine(newdiff) return newdiff2, newp }