classdef SwitchedFuzzyObserver
properties
% 基本参数
n % 状态维度
r % 规则数量
p % 前件变量数量
lower_MF % 下隶属函数
upper_MF % 上隶属函数
weighting_func % 权重函数 h_i(x)
premise_vars % 前件变量函数
% 关联对象
fuzzy_system % 关联的区间二型模糊系统对象
cyber_attack % 关联的混合攻击对象
% 观测器增益矩阵
F1 % 正常通信期间的观测器增益 F_{1,j}
F2 % DoS攻击期间的观测器增益 F_{2,j}
% 观测器状态
x_sigma % 观测器状态估计 x_σ(t)
y_sigma % 观测器输出估计 y_σ(t)
% 估计误差
estimation_error % 状态估计误差历史
output_error % 输出估计误差历史
% 配置参数
simulation_time % 仿真时间记录
config % 观测器配置参数%%%%%%%%%%%%%%%%%%%%%%
% 内部缓存
last_dos_status % 上次DoS攻击状态
trigger_history % 触发历史记录
% 攻击时间表
attack_schedule % 攻击时间表(Upsilon1:正常通信时段(初始为空)Upsilon2:DoS 攻击时段(初始为空)) Υ_{1,n}, Υ_{2,n}
end
methods
function obj = SwitchedFuzzyObserver(varargin)
p = inputParser;%创建输入解析器对象
addOptional(p, 'fuzzy_sys', [], @(x) isa(x, 'IntervalType2FuzzySystem') || isempty(x));
addOptional(p, 'cyber_attack_obj', [], @(x) isa(x, 'HybridCyberAttack') || isempty(x));
addParameter(p, 'n', 2, @isnumeric);
addParameter(p, 'r', 2, @isnumeric);
addParameter(p, 'p', 1, @isnumeric);
parse(p, varargin{:});%使用输入解析器p解析输入参数varargin,解析结果存储在p.Results结构中
if ~isempty(p.Results.fuzzy_sys)
% 如果提供了已存在的模糊系统对象(fuzzy_sys),则使用该对象和关联的网络攻击对象进行初始化
obj.fuzzy_system = p.Results.fuzzy_sys;%将观测器的fuzzy_system属性设置为传入的模糊系统对象(p.Results.fuzzy_sys)
obj.cyber_attack = p.Results.cyber_attack_obj;
obj.n = obj.fuzzy_system.n;
obj.r = obj.fuzzy_system.r;
obj.p = obj.fuzzy_system.p;
else
%如果没有提供模糊系统对象,则使用指定的参数(n, r, p)创建默认的模糊系统和网络攻击对象
obj.n = p.Results.n;
obj.r = p.Results.r;
obj.p = p.Results.p;
% 创建默认的模糊系统
obj.fuzzy_system = IntervalType2FuzzySystem(obj.n, obj.r, obj.p);
% 创建默认的攻击对象
obj.cyber_attack = HybridCyberAttack();
end
obj.lower_MF = cell(obj.r, obj.p);
obj.upper_MF = cell(obj.r, obj.p);
obj.weighting_func = cell(obj.r, 2); % {h_lower, h_upper}
obj.premise_vars = cell(obj.p, 1);
% 初始化增益矩阵(创建两个单元格数组F1和F2,长度等于规则数量obj.r)
obj.F1 = cell(obj.r, 1);%F_{1,j}
obj.F2 = cell(obj.r, 1);%r行1列
% 初始化默认增益(可根据需要修改)
for j = 1:obj.r
obj.F1{j} = eye(obj.n) * 0.5; % 默认正常增益
obj.F2{j} = eye(obj.n) * 0.2; % 默认攻击期间增益
end
% 添加触发历史初始化
obj.trigger_history = [];
% 初始化观测器状态
obj.x_sigma = zeros(obj.n, 1);
obj.y_sigma = zeros(obj.n, 1); % 默认输出维度与状态相同,维度均为 n×1(状态维度)
% 初始化误差记录
obj.estimation_error = [];
obj.output_error = [];
obj.simulation_time = [];
obj.last_dos_status = 0;
% 初始化攻击时间表(创建结构体 attack_schedule,包含两个字段:Upsilon1:正常通信时段(初始为空)Upsilon2:DoS 攻击时段(初始为空)用于存储预定义或检测到的攻击时间表)
obj.attack_schedule = struct('Upsilon1', [], 'Upsilon2', []);
% 默认配置
obj.config = struct(...
'use_type_reduction', true, ...
'error_threshold', 0.1, ...
'adaptive_gain', false, ...
'output_dimension', obj.n ...
);
end
function obj = setAttackSchedule(obj, Upsilon1, Upsilon2)
% 设置攻击时间表 Υ_{1,n}, Υ_{2,n}
obj.attack_schedule.Upsilon1 = Upsilon1; % 正常通信时段(一个数组或矩阵,表示正常通信的时间段。通常,这个参数应该是一个二维数组,每一行代表一个时间段(例如,[开始时间, 结束时间]))
obj.attack_schedule.Upsilon2 = Upsilon2; % DoS攻击时段
end
function obj = setSystemMatrices(obj, A_cell, B_cell, C_mat)%用于设置模糊系统矩阵的方法
% 设置系统矩阵
for j = 1:min(length(A_cell), obj.r)
obj.fuzzy_system.A{j} = A_cell{j};%将每个 A_i 矩阵赋值给模糊系统的对应规则,min(length(A_cell), obj.r):确保不会超出规则数量,只更新有对应矩阵的规则,如果提供的 A 矩阵少于规则数,剩余规则保持原样
end
for j = 1:min(length(B_cell), obj.r)
obj.fuzzy_system.B{j} = B_cell{j};
end
obj.fuzzy_system.C = C_mat;%直接设置模糊系统的输出矩阵 C,该矩阵通常对所有规则相同
obj.config.output_dimension = size(C_mat, 1);%根据 C 矩阵的行数更新输出维度配置
obj.y_sigma = zeros(obj.config.output_dimension, 1);
end
function obj = setObserverGains(obj, j, F1_j, F2_j)%设置单条规则的增益
% 设置第j条规则的观测器增益
if j <= obj.r && j > 0
obj.F1{j} = F1_j;
obj.F2{j} = F2_j;
else
error('规则索引超出范围');
end
end
function obj = setConfig(obj, field, value)
% 设置观测器配置参数
if isfield(obj.config, field)
obj.config.(field) = value;%将value的值赋值给相应参数配置,实现更新
else
error('无效的配置字段: %s', field);
end
end
function obj = setMembershipFunction(obj, i, j, lower_func, upper_func)
if i==1
obj.lower_MF{1, j} = lower_func;
obj.upper_MF{1, j} = upper_func;
end
if i==2
obj.lower_MF{2, j} = lower_func;
obj.upper_MF{2, j} = upper_func;
end
end
function obj = setWeightingFunction(obj, i, h_lower, h_upper)
obj.weighting_func{i, 1} = h_lower;
obj.weighting_func{i, 2} = h_upper;
end
function obj = setPremiseVariable(obj, j, premise_func)
obj.premise_vars{j} = premise_func;
end
function premise_var = getPremiseVariable(obj, j, x)
if ~isempty(obj.premise_vars{j})
premise_var = obj.premise_vars{j}(x);
else
premise_var = x(1);
end
end
function [firing_lower, firing_upper] = computeFiringStrength(obj, x)
firing_lower = zeros(obj.r, 1);
firing_upper = zeros(obj.r, 1);
for i = 1:obj.r
lower_strength = 1;
upper_strength = 1;
for j = 1:obj.p
premise_var = x(1);
if ~isempty(obj.lower_MF{i, j})
lower_mem = obj.lower_MF{i, j}(premise_var);
upper_mem = obj.upper_MF{i, j}(premise_var);
lower_strength = lower_strength * lower_mem;
upper_strength = upper_strength * upper_mem;
end
end
firing_lower(i) = lower_strength;
firing_upper(i) = upper_strength;
end
end
function [dx_sigma, obj] = computeObserverDynamics(obj, t, u, y, x_sigma)%计算观测器动态
% 获取DoS攻击状态
[D_dos, ~] = obj.cyber_attack.generateDoSAttack(t);%~:忽略其他输出(如攻击信息)
obj.last_dos_status = D_dos;
dos_status = D_dos;%没有时间表则使用实时监测
[firing_lower, firing_upper] = obj.computeFiringStrength(obj.x_sigma);
% 初始化状态导数和输出误差
dx_sigma = zeros(obj.n, 1);
obj.output_error = y - obj.y_sigma; % 输出误差 y(t) - y_σ(t)
total_weight = 0;
% 根据攻击状态选择增益,实现观测器动态计算
if dos_status == 0 % 正常通信
for j = 1:obj.r%对每条规则计算其对状态导数的贡献
if ~isempty(obj.fuzzy_system.A{j}) && ~isempty(obj.F1{j})
% 系统动力学部分
system_dyn = obj.fuzzy_system.A{j} * x_sigma; % 使用受攻击的状态估计
if ~isempty(obj.fuzzy_system.B{j})
system_dyn = system_dyn + obj.fuzzy_system.B{j} * u;%控制输入影响
end
% 校正项
correction = obj.F1{j} * obj.output_error;
%权重函数
h_lower = obj.weighting_func{j,1}(x_sigma(1)); % 取状态向量的第一个分量
h_upper = obj.weighting_func{j,2}(x_sigma(1));
chi_j = h_lower * firing_lower(j) + h_upper * firing_upper(j);
dx_sigma = dx_sigma + chi_j * (system_dyn + correction);
total_weight = total_weight + chi_j;
end
end
else % DoS攻击期间
for j = 1:obj.r
if ~isempty(obj.fuzzy_system.A{j}) && ~isempty(obj.F2{j})
% 系统动力学部分
system_dyn = obj.fuzzy_system.A{j} * x_sigma; % 使用受攻击的状态估计
if ~isempty(obj.fuzzy_system.B{j})
system_dyn = system_dyn + obj.fuzzy_system.B{j} * u;
end
% 校正项
correction = obj.F2{j} * obj.output_error;
h_lower = obj.weighting_func{j,1}(x_sigma(1));
h_upper = obj.weighting_func{j,2}(x_sigma(1));
chi_j = h_lower * firing_lower(j) + h_upper * firing_upper(j);
dx_sigma = dx_sigma + chi_j * (system_dyn + correction);
total_weight = total_weight + chi_j;
end
end
end
if total_weight > 0
dx_sigma = dx_sigma / total_weight;
end
% 更新观测器输出
if ~isempty(obj.fuzzy_system.C)
obj.y_sigma = obj.fuzzy_system.C * obj.x_sigma;
end
% 记录时间(记录每次调用观测器动态计算的时间点)
obj.simulation_time = [obj.simulation_time; t];
% 记录当前状态用于事件触发
trigger_info = struct();
trigger_info.time = t;
trigger_info.state = obj.x_sigma;
trigger_info.output = obj.y_sigma;
trigger_info.dos_status = dos_status;
obj.trigger_history = [obj.trigger_history; trigger_info];
end
function obj = updateObserverState(obj, dx_sigma, dt)
% 更新观测器状态,更新其输出估计
obj.x_sigma = obj.x_sigma + dx_sigma * dt;
if ~isempty(obj.fuzzy_system.C)
obj.y_sigma = obj.fuzzy_system.C * obj.x_sigma;
end
end
function [x_est, y_est] = getEstimate(obj)
% 获取当前状态和输出估计(可在一定程度上提供数值保护)
x_est = obj.x_sigma;
y_est = obj.y_sigma;
end
function obj = recordEstimationError(obj, x_true, y_true)
% 记录估计误差
if ~isempty(x_true) && length(x_true) == obj.n
error_state = x_true - obj.x_sigma;
obj.estimation_error = [obj.estimation_error; error_state'];
end
if ~isempty(y_true) && length(y_true) == length(obj.y_sigma)
error_output = y_true - obj.y_sigma;
obj.output_error = [obj.output_error; error_output'];
end
end
function obj = resetObserver(obj, x0)
% 重置观测器状态
if nargin < 2
x0 = zeros(obj.n, 1);%如果没有提供初始状态 x0
end
obj.x_sigma = x0;
if ~isempty(obj.fuzzy_system.C)
obj.y_sigma = obj.fuzzy_system.C * x0;
else
obj.y_sigma = x0;
end
obj.estimation_error = [];
obj.output_error = [];
obj.simulation_time = [];
end
function performance = evaluatePerformance(obj)
% 评估观测器性能
performance = struct();
if ~isempty(obj.estimation_error)
% 状态估计性能
performance.rmse_state = sqrt(mean(obj.estimation_error.^2, 1));%均方根误差
performance.mae_state = mean(abs(obj.estimation_error), 1);%平均绝对误差
performance.max_error_state = max(abs(obj.estimation_error), [], 1);%最大绝对误差
% 输出估计性能
if ~isempty(obj.output_error)
performance.rmse_output = sqrt(mean(obj.output_error.^2, 1));
performance.mae_output = mean(abs(obj.output_error), 1);
end
% 收敛性分析
performance.final_error = obj.estimation_error(end, :);
end
end
end
end