Generate the tuning function in FuzzyLD: "function_handle input" error
Show older comments
Hello,
I’ve been using the Fuzzy Logic Designer to tune some FIS systems for a few weeks, and it’s been working well—my cost function performs as expected, and my Simulink system gives great results.
However, I’d like to access and modify the tuning process (as: Log specific iterations during tuning or interrupt the process at a specific time to ensure consistent processing time across different configurations).
To achieve this, I tried generating the tuning function directly through the Designer app. However, I encountered the following error:
"Function is not defined for 'function_handle' inputs."
Knowing that I have the following settings:


And I am using the following custom cost function:
function [cost] = no_overshoot_cost(fis)
% I pass the FIS as variable for the workspace so that I can access it in
% my simulink system
assignin('base', 'fis_test', fis);
%I use a simulink to simulate my system
anz = sim("Fuzzy_PID");
signal = anz.Output;
% Extract data and time from both signals
step_data = anz.Input.Data;
output_data = signal.Data;
time = anz.Input.Time;
% Compute the difference (error) between the step input and the output signal
error_signal = output_data- step_data;
% overshoot (output signal is below step input)
pos_error_signal = max(error_signal, 0); % Take only positive errors
overshoot = trapz(time, pos_error_signal); % Integrate the positive error
% undeshoot (output signal is above step input)
neg_error_signal = min(error_signal, 0); % Take only negative errors
undershoot = -trapz(time, neg_error_signal); % Integrate the negative error
% I don't want any overshoot so I penalise if any
if overshoot > 0
cost = 10;
else
cost = undershoot;
end
From what I understand, the error occurs because a function cannot accept another function as an input when using a variable function_handle, I assume that it is about the cost function but I am unsure
To address this, I modified the cost function, as I was previously using a separate function to compute the undershoot and overshoot. However, despite this change, the same error persists.
Would you have any idea how to resolve this error to let me get the tunning code ?
Thanks in advance,
4 Comments
Hi @Arnaud
This is not a solution yet, but rather a prompt for you to consider the logic behind your engineering design.
Before tuning your fuzzy system, you should test whether your designed cost function is effective. Here is a very simple toy model (mass-damper-spring) that utilizes your cost function to tune a single parameter, C (damping) in the system.
Case 1: Before tuning with genetic algorithm
% System
M = 1; % mass
C = 0.5; % damping coefficient
K = 1; % spring stiffness
sys = tf(K, [M, C, K]) % C < 2 is underdamped, C > 2 is overdamped
stepinfo(sys)
% Output signal
t = 0:0.01:25;
u = zeros(length(t), 1);
u(t>=0) = 1;
[y, t] = lsim(sys, u, t);
plot(t, [y, u]), grid on
legend('Output', 'Step input')
xlabel('Time (seconds)')
ylabel('Output Amplitude')
title('Time Response of Output signal')
% Extract data and time from both signals
step_data = 1;
output_data = y;
time = t;
% Compute the difference (error) between the step input and the output signal
error_signal = output_data- step_data;
plot(t, error_signal), grid on
xlabel('Time (seconds)')
ylabel('Error Amplitude')
title('Time Response of Error signal')
% overshoot (output signal is below step input)
pos_error_signal = max(error_signal, 0); % Take only positive errors
plot(t, pos_error_signal), grid on
xlabel('Time (seconds)')
ylabel('Positive Error Amplitude')
title('Time Response of Positive Error signal')
overshoot = trapz(time, pos_error_signal) % Integrate the positive error
Case 2: After tuning with genetic algorithm
The optimal damping value for a critically damped system should be 2. Each time you run the optimizer, it may return a value that is either close to the optimal value or relatively far from it within the range
. This inconsistency suggests that you should revisit the logic of the cost function.
However, if your goal is simply to achieve a no-overshoot system, then the code for the cost function is acceptable.
lb = 1; % lower bound value of search range
ub = 3; % upper bound value of search range
C = ga(@no_overshoot_cost, 1, [], [], [], [], lb, ub)
% System
% C = 2; % Optimal damping value should be 2 (for a critically-damped system)
sys = tf(K, [M, C, K]) % C < 2 is underdamped, C > 2 is overdamped
stepinfo(sys)
% Output signal
t = 0:0.01:25;
u = zeros(length(t), 1);
u(t>=0) = 1;
[y, t] = lsim(sys, u, t);
plot(t, [y, u]), grid on
legend('Output', 'Step input')
xlabel('Time (seconds)')
ylabel('Output Amplitude')
title('Time Response of Output signal')
% Extract data and time from both signals
step_data = 1;
output_data = y;
time = t;
% Compute the difference (error) between the step input and the output signal
error_signal = output_data- step_data;
plot(t, error_signal), grid on
xlabel('Time (seconds)')
ylabel('Error Amplitude')
title('Time Response of Error signal')
% overshoot (output signal is below step input)
pos_error_signal = max(error_signal, 0); % Take only positive errors
plot(t, pos_error_signal), grid on
xlabel('Time (seconds)')
ylabel('Positive Error Amplitude')
title('Time Response of Positive Error signal')
overshoot = trapz(time, pos_error_signal) % Integrate the positive error
%% Cost function
function cost = no_overshoot_cost(C)
% System
sys = tf(1, [1, C, 1]);
% Output signal
t = 0:0.01:25;
u = zeros(length(t), 1);
u(t>=0) = 1;
[y, t] = lsim(sys, u, t);
% Extract data and time from both signals
step_data = 1;
output_data = y;
time = t;
% Compute the difference (error) between the step input and the output signal
error_signal = output_data- step_data;
% overshoot (output signal is below step input)
pos_error_signal = max(error_signal, 0); % Take only positive errors
overshoot = trapz(time, pos_error_signal); % Integrate the positive error
cost = overshoot;
end
Sam Chak
on 23 Dec 2024
Hi @Arnaud
Additionally, the reason your cost function performs as expected is that the optimizer merely finds a set of values within the 'no-overshoot' mathematical set for the fuzzy system.
This can be analogously compared to instructing a friend to find a path in this region that goes from Point A to Point B in less than 10 minutes, even though your friend is unaware of the shortest path between these two points.
Arnaud
on 23 Dec 2024
Sam Chak
on 23 Dec 2024
Hi @Arnaud
I do not have comprehensive knowledge of fuzzy logic in MATLAB. Returning to your question, how are you able to pass the fuzzy inference system (FIS) object as a parametric variable in the cost function for your optimizer to tune?
Is the no_overshoot_cost(fis) an embedded function within a function that creates the FIS object?
%% Main Cost function
function cost = actual_cost(param)
fis = mamfis("Name", ...);
fis = addInput(fis, ...);
fis = addMF(fis, "...", "gaussmf", [param(1), param(2)], "Name", ...);
fis = addOutput(fis, ...);
fis = addMF(fis, "...", "trimf", [param(4), param(4), param(5)], "Name", "...");
ruleList = ...;
fis = addRule(fis, ruleList);
...
cost = no_overshoot_cost(fis);
%% sub-Cost function
function [cost] = no_overshoot_cost(fis)
assignin('base', 'fis_test', fis);
...
end
end
Answers (0)
Categories
Find more on Fuzzy Logic in Simulink in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!




