u_func = @(t) 12 * (sin(2*pi*0.4*t) > 0);
sigma = 0;% Magnitud del ruido. Darle un valor >0 para simular con ruido <1
fs_ruido = 2000; % Alta frecuencia para que parezca continuo
t_ruido = -0.01 : (1/fs_ruido) : (t_span(end)+0.01);
ruido_vals = sigma * randn(size(t_ruido));
% Interpolador para el ruido
ruido_func = @(t) interp1(t_ruido, ruido_vals, t, 'previous');
% Ejecutar ODE45 con la función de ruido pre-generado
[t, z] = ode45(@(t,z) dynamics_rlc(t, z, A, B, C_mat, L_obs, u_func, ruido_func), t_span, z0);
% Desempaquetar resultados
% Recalcular vectores exactos para graficar
u_vec = arrayfun(u_func, t); % Entrada exacta
ruido_vec = arrayfun(ruido_func, t); % Ruido exacto
y_clean = (C_mat * x_real')'; % Salida limpia
y_medida = y_clean + ruido_vec; % Salida ruidosa (Lo que entró al observador)
figure('Name', 'Entrada del Sistema', 'Color', 'w');
plot(t, u_vec, 'b', 'LineWidth', 2);
title('Entrada del Sistema - Voltaje (u(t))', 'FontSize', 10, 'FontWeight', 'bold', 'Color', 'k');
ylabel('Voltaje (V)', 'FontSize', 10, 'Color', 'k');
xlabel('Tiempo (s)', 'FontSize', 10, 'Color', 'k');
ylim([min(u_vec)-2 max(u_vec)+2])
lgd = legend('Voltaje de Entrada', 'Location', 'best');
set(lgd, 'TextColor', 'k', 'Color', 'w', 'EdgeColor', 'k', 'FontSize', 10);
figure('Name', 'Salida del Sistema', 'Color', 'w', 'Position', [100 100 800 400]);
plot(t, y_medida, 'k-', 'LineWidth', 0.5, 'Color', [0 0 0 0.3]); hold on;
plot(t, y_clean, 'r', 'LineWidth', 2);
title('Salida del Sistema - Medición (y(t))', 'FontSize', 10, 'FontWeight', 'bold', 'Color', 'k');
ylabel('Salida', 'FontSize', 10, 'Color', 'k');
xlabel('Tiempo (s)', 'FontSize', 10, 'Color', 'k');
lgd = legend('Medición', 'Salida Real', 'Location', 'best');
set(lgd, 'TextColor', 'k', 'Color', 'w', 'EdgeColor', 'k', 'FontSize', 10);
% 3. CORRIENTE DEL INDUCTOR
figure('Name', 'Corriente Inductor', 'Color', 'w', 'Position', [100 100 800 500]);
plot(t, x_est(:,1), 'b--', 'LineWidth', 2); hold on;
plot(t, x_real(:,1), 'r', 'LineWidth', 2);
title('Estimación de Corriente Inductor', 'FontSize', 10, 'FontWeight', 'bold', 'Color', 'k');
ylabel('Amperes (A)', 'FontSize', 10, 'Color', 'k');
xlabel('Tiempo (s)', 'FontSize', 10, 'Color', 'k');
lgd = legend('Corriente Estimada (Observador)','Corriente Real', 'Location', 'best');
set(lgd, 'TextColor', 'k', 'Color', 'w', 'EdgeColor', 'k', 'FontSize', 10);
% 4. VOLTAJE DEL CAPACITOR
figure('Name', 'Voltaje Capacitor', 'Color', 'w', 'Position', [100 100 800 500]);
plot(t, x_est(:,2), 'b--', 'LineWidth', 2); hold on;
plot(t, x_real(:,2), 'r', 'LineWidth', 2);
title('Estimación de Voltaje Capacitor', 'FontSize', 10, 'FontWeight', 'bold', 'Color', 'k');
ylabel('Voltios (V)', 'FontSize', 10, 'Color', 'k');
xlabel('Tiempo (s)', 'FontSize', 10, 'Color', 'k');
lgd = legend('Voltaje Estimado (Observador)','Voltaje Real', 'Location', 'best');
set(lgd, 'TextColor', 'k', 'Color', 'w', 'EdgeColor', 'k', 'FontSize', 10);
% 5. ERROR ABSOLUTO - CORRIENTE
figure('Name', 'Error Absoluto - Corriente', 'Color', 'w', 'Position', [100 100 800 400]);
error_iL = abs(x_real(:,1) - x_est(:,1));
area(t, error_iL, 'FaceColor', [0.85 0.33 0.1], 'FaceAlpha', 0.4, 'EdgeColor', 'r', 'LineWidth', 1);
title('Error Absoluto de Estimación - Corriente Inductor', 'FontSize', 10, 'FontWeight', 'bold', 'Color', 'k');
ylabel('|Error| (A)', 'FontSize', 10, 'Color', 'k');
xlabel('Tiempo (s)', 'FontSize', 10, 'Color', 'k');
error_max_iL = max(error_iL);
error_final_iL = error_iL(end);
text(t_span(end)*0.4, error_max_iL*0.6, ...
sprintf('Error máximo: %.4f A\nError final: %.4f A', error_max_iL, error_final_iL), ...
'FontSize', 10, 'Color', 'k', 'FontWeight', 'bold', 'BackgroundColor', 'w');
% 6. ERROR ABSOLUTO - VOLTAJE
figure('Name', 'Error Absoluto - Voltaje', 'Color', 'w', 'Position', [100 100 800 400]);
error_vC = abs(x_real(:,2) - x_est(:,2));
area(t, error_vC, 'FaceColor', [0.85 0.33 0.1], 'FaceAlpha', 0.4, 'EdgeColor', 'r', 'LineWidth', 1);
title('Error Absoluto de Estimación - Voltaje Capacitor', 'FontSize', 10, 'FontWeight', 'bold', 'Color', 'k');
ylabel('|Error| (V)', 'FontSize', 10, 'Color', 'k');
xlabel('Tiempo (s)', 'FontSize', 10, 'Color', 'k');
error_max_vC = max(error_vC);
error_final_vC = error_vC(end);
text(t_span(end)*0.4, error_max_vC*0.6, ...
sprintf('Error máximo: %.4f V\nError final: %.4f V', error_max_vC, error_final_vC), ...
'FontSize', 10, 'Color', 'k', 'FontWeight', 'bold', 'BackgroundColor', 'w');
figure('Name', 'Visualización del Ruido', 'Color', 'w', 'Position', [100 100 800 300]);
plot(t, ruido_vec, 'Color', [0.4 0.4 0.4], 'LineWidth', 1);
title('Ruido Inyectado en el Sensor', 'FontSize', 10, 'FontWeight', 'bold', 'Color', 'k');
ylabel('Amplitud Ruido', 'FontSize', 10, 'Color', 'k');
xlabel('Tiempo (s)', 'FontSize', 10, 'Color', 'k');
function dz = dynamics_rlc(t, z, A, B, C, L, u_func, noise_func)
u = u_func(t); % Evaluar entrada
ruido = noise_func(t); % Evaluar ruido pre-generado
y_medida = C * x + ruido;
dx_hat = A * x_hat + B * u + L * (y_medida - y_hat);