--- slideOptions: transition: slide --- <style> .reveal { font-size: 24px; } </style> # Fuzzy Logic Control Simulation on MATLAB and Simulink *"We implement Dynamic model on simulink and put FLC only using MATLAB code"* For better look check this note, please visit [HackMD.io](https://hackmd.io/@libernormous/flc_mat_sim) by: [Liber Normous](https://hackmd.io/@libernormous) --- # Fuzzy Logic control 1. The Fuzzy Logic Control is based on Ref [1]. 2. We have a tutorial for creating Fuzzy Logic Control (FLC) only using MATLAB code [here](https://hackmd.io/@libernormous/fuzzy) 3. This is the second version of FLC implementation. Previously we implemented the FLC on V-REP. The tutorial can be found [here](https://hackmd.io/@libernormous/flc_nav_obs). --- # Dynamic model of the robot 1. The dynamic model of the robot is based on Ref [2]. 2. We have a tutorial to build this dynamic model on Simulink. It can be found in [here](https://hackmd.io/@libernormous/dynamic_ddmr). 3. We will use the previous model and modify it. We add FLC in it. --- # Overall simulink model ![](https://i.imgur.com/L2S3pUb.png) Open the image in new tab if it is too small. In this model add `pos_orr_err` block. That is a block to measure the distance between the robot and goal. It also calculate the heading error of the robot. The other block is TFLC block which is Tracking Fuzzy Logic Control from Ref. [1]. --- # Calculating position and orientation error ![](https://i.imgur.com/7IhXQZE.png =200x) This is the code inside the block: ```c= function [pos_err,orr_err] = pos_orr_err(R_x, R_y, R_g, G_x, G_y, G_g) %values assignment rob_poss = [R_x; R_y]; %in meter gol_poss = [G_x; G_y]; %in meter gamma_r = R_g; %in radian % % convert radian to -pi to pi values % if gamma_r>pi % gamma_r = gamma_r-2*pi; % elseif gamma_r<pi % gamma_r = gamma_r+2*pi; % end %position error vec_pos = gol_poss-rob_poss; pos_err = sqrt(sum((vec_pos).^2)); %in meter %Goal position relative to robot position to find heading error fTr = [cos(gamma_r) -sin(gamma_r) rob_poss(1); sin(gamma_r) cos(gamma_r) rob_poss(2); 0 0 1]; gol_2_r_pos = (fTr)\[gol_poss(1); gol_poss(2); 1]; %heading error hed_err = atan2(gol_2_r_pos(2), gol_2_r_pos(1)); hed_err = rad2deg(hed_err); orr_err = hed_err; %in degree angle end ``` ---- ## Position error The position error is calculated using Euclidean distance: $$ d = \sqrt{(R_x-G_x)^2+(R_y-G_y)^2} $$ That is why we need the position of the robot $(R_x, R_y)$ and the position of the goal $(G_x, G_y)$. Here we do the simulation on 2D plane. More explanation [here](https://hackmd.io/@libernormous/flc_nav_obs#Calculating-Position-Error). ---- ## Heading error All the calculation of heading error are in $rad$ degree. To calculate heading error, we need $G_x, G_y, R_x, R_y$ and $R_\gamma$ which is orientation of the robot. We will represent the pose of the goal in the robot frame. ![](https://i.imgur.com/hufG12F.png =400x) To do this we need a transformation matrix. $$ \begin{align} ^R\tilde{P}_G &= {^RT_W}\ ^W\tilde{P}_G\\ &= {^WT_R}^{-1} \ ^W\tilde{P}_G\\ &= \left( \begin{matrix} \cos(R_\gamma) & -\sin(R_\gamma) & R_x\\ \sin(R_\gamma) & \cos(R_\gamma) & R_y\\ 0 &0 &1 \end{matrix} \right)^{-1} \ ^W\tilde{P}_G\\ \left( \begin{matrix} ^RG_x\\ ^RG_y\\ 1 \end{matrix} \right)&=\left( \begin{matrix} \cos(R_\gamma) & -\sin(R_\gamma) & R_x\\ \sin(R_\gamma) & \cos(R_\gamma) & R_y\\ 0 &0 &1 \end{matrix} \right)^{-1} \left( \begin{matrix} ^WG_x\\ ^WG_y\\ 1 \end{matrix} \right) \end{align} $$ And we find the orientation as: $$ \gamma_e = \text{atan2}(^RG_y\ ,\ ^RG_x) $$ This explanation can be found in [here](https://hackmd.io/@libernormous/flc_nav_obs#Calculating-Heading-Error). --- # TFLC block ![](https://i.imgur.com/Ih88CjW.png =200x) This is what inside the block: ```c= function [v_r,v_l] = tflc(position_error,orientation_error) %% global constant %TFLC RULES rules_TFLC_L = [ 1 1 1 1 3 3 4; 2 2 1 2 3 5 6; 2 2 2 3 5 6 7; 1 1 1 4 6 6 7; 2 2 3 5 5 6 7; 1 1 4 6 5 6 7; 2 2 3 7 5 6 7 ]; rules_TFLC_R = flip(rules_TFLC_L,2); %OAFLC RULES rules_OAFLC_R_L = [ 1 1; 2 1; 2 1; 1 1; 2 1; 2 1; 1 1; 2 1; 2 1; 1 2; 1 1; 5 3; 3 5; 5 3; 5 3; 1 2; 5 3; 5 3; 1 2; 3 5; 1 1; 1 2; 3 5; 5 3; 1 2; 3 5; 4 4; ]; %% run all nested function %fuzzyfication fuz_dist = check_distance_membership(position_error); % in meter fuz_orie = check_err_angle_membership(orientation_error); % in degree angle %inference [mat_TFLC_L_rel,v_TFLC_L_th] = relate_TFLC (fuz_dist, fuz_orie, rules_TFLC_L); [mat_TFLC_R_rel,v_TFLC_R_th] = relate_TFLC (fuz_dist, fuz_orie, rules_TFLC_R); %calculating centroid TFLC L dt = 0.01; t = -1:dt:13; %output data range out = []; for i=1:length(t) ret=check_velocity_membership(t(i)); %output fuzzification ret = min(v_TFLC_L_th, ret); %Max value / real value of the inference out = [out max(ret)]; %MAX end centeroid_TFLC_L = sum(out.*t)/sum(out); %calculating centroid TFLC R out = []; for i=1:length(t) ret=check_velocity_membership(t(i)); %output fuzzification ret = min(v_TFLC_R_th, ret); %Max value / real value of the inference out = [out max(ret)]; %MAX end centeroid_TFLC_R = sum(out.*t)/sum(out); %actuate the wheel v_r = centeroid_TFLC_L; %because the rules is inverted v_l = centeroid_TFLC_R; %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% FUNCTIONS %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% =====================to check all value in distance fuzzification function out = check_distance_membership(input) %meter z = triangle (input, 0, 0, 0.50, 1, 1, 0); %zero nz = triangle (input, 0, 0.50, 1.00, 0, 1, 0); %near zero n = triangle (input, 0.50, 1.00, 1.50, 0, 1, 0); %near m = triangle (input, 1.00, 1.50, 2.00, 0, 1, 0); %medium nf = triangle (input, 1.50, 2.00, 2.50, 0, 1, 0); %near far f = triangle (input, 2.00, 2.50, 3.00, 0, 1, 0); %far vf = triangle (input, 2.50, 3.00, 3.00, 0, 1, 1); %very far out = [z;nz;n;m;nf;f;vf]; end %% =====================to check all value in angle error fuzzification function out = check_err_angle_membership(input) n = triangle (input, -175, -175, -88, 1, 1, 0); %negative sn = triangle (input, -175, -88, -43, 0, 1, 0); %small neg nnz = triangle (input, -88, -43, 0, 0, 1, 0); % near neg zero z = triangle (input, -43, 0, 43, 0, 1, 0); %zero npz = triangle (input, 0, 43, 88, 0, 1, 0); %near pos zero sp = triangle (input, 43, 88, 175, 0, 1, 0); %small pos p = triangle (input, 88, 175, 175, 0, 1, 1); %positive out = [n; sn; nnz; z; npz; sp; p]; end %% =====================to check all value in velocity of motors in TFLC fuzzification function out = check_velocity_membership(input) z = triangle (input, 0, 0, 2, 1, 1, 0);%zero s = triangle (input, 0, 2, 4, 0, 1, 0);%slow nm = triangle (input, 2, 4, 6, 0, 1, 0);%near medium m = triangle (input, 4, 6, 8, 0, 1, 0);%medium nh = triangle (input, 6, 8, 10, 0, 1, 0);%near high h = triangle (input, 8, 10, 12, 0, 1, 0);%high vh = triangle (input, 10, 12, 12, 0, 1, 1);%very high out = [z;s;nm;m;nh;h;vh]; end %% ===============triangle shaped fuzzy membership function out = triangle (input, start, middle, stop, str_val, mid_val, sto_val) if input<start out = str_val; elseif (input>=start) && (input<middle) v = (mid_val-str_val)/(middle-start); out = str_val + v*(input-start); elseif (input==middle) out = mid_val; elseif (input>middle) && (input<=stop) v = (sto_val-mid_val)/(stop-middle); out = mid_val + v*(input-middle); elseif input>stop out = sto_val; else out = 0; end end %% Relate a fuzzification to another with the result of matrix & vec % the relation is using minimum, because the relation in fuzzy rules are % using AND function [mat_rules_val,v_out_th] = relate_TFLC (set1, set2, rules_index) % set1 is rows, and set2 is columns % find correspoding values for each rules m = zeros(length(set1), length(set2)); for i=1:length(set1) for j=1:length(set2) m(i,j)=min(set1(i),set2(j)); %MIN end end % find the output index of each rules values % then create vector, of possible maximum mambership value from output % membership class v_out = zeros(max(max(rules_index)),1); [h,w]=size(rules_index); for i = 1:h for j = 1:w v_out( rules_index(i,j) ) = max(v_out( rules_index(i,j) ), m (i,j)); %MAX end end mat_rules_val = m; v_out_th = v_out; end end ``` Essentially it is the same as our [previous model](https://hackmd.io/@libernormous/flc_nav_obs), but we simplify it to a function of TFLC only. --- # Running the simulation To run the simulation, we need another file to initialize all the parameters. We have done this before in [previous note](https://hackmd.io/@libernormous/dynamic_ddmr#Parameters). ```c= clear; %% Parameters La=0.94; %H, inductance of the armature winding Ra=1; %Ohm, resistance of the armature winding Kb= 1;%0.0301; %V/rad/s the back emf constant N=1; %the gear ratio Kt=0.0300; %Nm/Amp the torque constant J = 2; % Moment inertia of robot KG*m^2 M = 5; % Robot mass in KG d = 0.02; % Location of center of gravity of robot. x=d y=o in robot frame R = 0.02;%radius of wheel in meter L = 0.1;%distance between wheel in meter %% Input V_r = 1; % right motor voltage V_l = 0; % right motor voltage G_x = 1; %Goal x position G_y = -1; %Goal y position G_g = pi/2; %Goal z orientation xa=0; ya=0; theta=0; vol_gain = 1; % to slowdown the robot TF = 40; %simulation time %% Run simulation simout = sim('func1_v4'); figure(3); subplot(3,3,1),plot(simout.tout, simout.ya), xlabel('t(s)'), ylabel('ya(m)'); subplot(3,3,2),plot(simout.tout, simout.xa), xlabel('t(s)'), ylabel('xa(m)'); subplot(3,3,3),plot(simout.xa, simout.ya, G_x, G_y, '*'), xlabel('xa(m)'), ylabel('ya(m)'); subplot(3,3,4),plot(simout.tout, simout.theta), xlabel('t(s)'), ylabel('theta(rad)'); subplot(3,3,5),plot(simout.tout, simout.poser), xlabel('t(s)'), ylabel('position error(m)'); subplot(3,3,6),plot(simout.tout, simout.orrer), xlabel('t(s)'), ylabel('heading error(deg)'); subplot(3,3,7),plot(simout.tout, simout.vr_flc), xlabel('t(s)'), ylabel('right motor armature (volt)'); subplot(3,3,8),plot(simout.tout, simout.vl_flc), xlabel('t(s)'), ylabel('left motor armature (volt)'); subplot(3,3,9),plot(simout.tout, simout.vl_flc, 'r', simout.tout, simout.vr_flc, 'b'), xlabel('t(s)'), ylabel('armature (volt)'); ``` In above code we use motor model C-23-L33-W20 (winding code 20) from Ref. [[3]](https://www.moog.com/content/dam/moog/literature/MCG/moc23series.pdf). **BUT** we use $K_b=1{v/rad/s}$. This is to make the wheel stop faster. --- # Result 1 From previous code we can create simulations of many goals references. For example we make 9 simulation with sequence of $(G_x, G_y)$ in this matrix. $$ \left(\begin{matrix} G_x\\ G_y \end{matrix}\right)=\left(\begin{matrix} -1 & 0 & 1 & -1 & 0 & 1 & -1 & 0 & 1\\ 1 & 1 & 1 & 0 & 0 & 0 & -1 & -1 & -1 \end{matrix}\right) $$ ---- ![](https://i.imgur.com/UACQKy0.png) The **stars** are the goals. The middle graph is the result of all the graphs combined. In these images we know that the robot reach the goal, but we are not sure for how long the simulation has been run. We will have a closer look of the heading and distance error in the next section. ---- Here is the result of the robot approaching $G_x=-1m, G_y=-1m$. As we see, the position error are decreasing without problem, but the orientation is oscillating. So the robot is slithering like a snake. We can also see that the the armature voltages are dropping near the goal. The simulation time is $40s$. ![](https://i.imgur.com/r1Nu7Uo.png) ---- Here is another result when the goal is $G_x=-2.5m, G_y=0m$. ![](https://i.imgur.com/yyPHADH.png) ---- We move the goal to $G_x=-15m, G_y=0m$, and $40s$ of simulation is not enough anymore. ![](https://i.imgur.com/PcTRs7B.png) --- # Result 2 (Using real motor parameter) We don't simulate the friction force. We chose $K_b=1{v/rad/s}$ because it is the only thing that will stop the motors. If we use the real motor parameter values from datasheets, the results are quite unsatisfying. Here we change $K_b=0.0301{v/rad/s}$ to match the model C-23-L33-W20 (winding code 20) from Ref. [[3]](https://www.moog.com/content/dam/moog/literature/MCG/moc23series.pdf). ---- This is when $G_x=-25m, G_y=0m$ ![](https://i.imgur.com/gZgcq5P.png) ---- And this is when $G_x=30m, G_y=3m$. ![](https://i.imgur.com/osx5eXs.png) ---- And to show the dullness of the control system (or maybe the simulation) we set $G_x=100m, G_y=0m$, which means $100m$ in front of the robot, and the system still have a dumb result. ![](https://i.imgur.com/kCt7pV4.png) --- # Adding torque disturbance experiment Here we introduce torque disturbance. We subtract the value of torque output from motor $\tau$ with some value $\tau_d$. The value of torque disturbance is relative to motor angular velocity. If the motor is stopping $\omega=0$ then there is no disturbance $\tau_d=0$. Because a constant value of disturbance will add a backward movement to the robot when it should not be. The direction of disturbance is the opposite of the movement, just like friction force. This sentences can be described in this formula: $$ \tau_d = \text{sign}(\omega)*G $$ With $G$ is value of the disturbance. The value is constant except the direction. In short, $\tau_d$ is ranging to $\{-G,0,G\}$. ![](https://i.imgur.com/0t3XAIh.png) The concept seems logical but I've got no results because the simulation get really slow. The time sampling of simulation turns to $3\cdot10^{-27}$s ![](https://i.imgur.com/jqEHdIa.png) --- # Adding force disturbance experiment (friction force) We got a friction model from MATLAB which can be found in Ref. [[4]](https://www.mathworks.com/help/simulink/slref/friction-model-with-hard-stops.html). This is the preview picture of that model. ![](https://i.imgur.com/ugVvex9.png) ![](https://i.imgur.com/wKgYsr2.png) Basically this model will put a spring force. The spring force is given by initial length of spring $x$. Also because of this force, the $x$ is changed each second. But each iteration, the force is reduced because of the friction and so $x$ is reduced each iteration. ---- What we adopt from this model is the friction force model. ![](https://i.imgur.com/j5ohKly.png) We modify the model so we can input the force from the wheel torque and the system will output a reduced force, by friction. Here also we use a Normal Force from our model, that is the mass of the robot multiplied by gravity ($F_N=W=Mg$). So, we got an input force, and output force as indicated by cyan mark in above picture. ---- We put the model in our system like this picture below. ![](https://i.imgur.com/3WqIB5N.png) We used pretty big friction coefficient of $\mu_s=3.07$ (the static coefficient of friction, SCOF) and $\mu_d=2.8$ (the dynamic coefficient of friction, DCOF) Here is the result: (like always, open image in new tab if you want it bigger) ![](https://i.imgur.com/RlJVYtC.jpg) ![](https://i.imgur.com/fDs9a0L.jpg) Here we can see that, even using a big friction force, the system cannot reach the goal properly. So **We revoke our hypothesis that it is either the system or the simulation that is bad**. Maybe, this fuzzy system is designed for a robot with a high torque motor or a heavy robot so that it may stop on the goal position. *Knowing this problem, we would like to try a fuzzy controller that allows a backward movement. So the system may reduce the speed by moving backward. It may hold its position on the goal point by balancing backward and forward movement*. --- # Yet another parameter experiment (High torque motor) So here we go back to our default model. Our model in the beginning of this note. We don't add any disturbance, but rather we try to use another motor and robot parameters. Here is our code: ```c= %% Parameters for C23-L33-W20 terminal voltage for this motor is 12V La= 0.94e-3; %H, inductance of the armature winding Ra= 1; %Ohm, resistance of the armature winding Kb= 0.0301; %V/rad/s the back emf constant N=10; %the gear ratio Kt=0.03; %Nm/Amp the torque constant %% Parameters for robot bod M = 1000e-3; % Robot mass in KG d = 0.0; % Location of center of gravity of robot. x=d y=o in robot frame R = 0.02;%radius of wheel in meter L = 20e-2;%distance between wheel in meter J = 0.01;% Kg*m^2 Moment inertia of disk robot KG*m^2 calculated using https://www.omnicalculator.com/physics/mass-moment-of-inertia %% Input V_r = 1; % right motor voltage V_l = 0; % right motor voltage G_x = -10; %Goal x position G_y = 0; %Goal y position G_g = pi/2; %Goal z orientation xa=0; ya=0; theta=0; vol_gain = 1; % to slowdown the robot TF = 5; %simulation time mu_s = 0;%1.07; mu_k = 0;%0.953; %% Run simulation simout = sim('func1_v4'); figure(1); subplot(3,3,1),plot(simout.tout, simout.ya), xlabel('t(s)'), ylabel('ya(m)'); subplot(3,3,2),plot(simout.tout, simout.xa), xlabel('t(s)'), ylabel('xa(m)'); subplot(3,3,3),plot(simout.xa, simout.ya, G_x, G_y, '*'), xlabel('xa(m)'), ylabel('ya(m)'); subplot(3,3,4),plot(simout.tout, simout.theta), xlabel('t(s)'), ylabel('theta(rad)'); subplot(3,3,5),plot(simout.tout, simout.poser), xlabel('t(s)'), ylabel('position error(m)'); subplot(3,3,6),plot(simout.tout, simout.orrer), xlabel('t(s)'), ylabel('heading error(deg)'); subplot(3,3,7),plot(simout.tout, simout.vr_flc), xlabel('t(s)'), ylabel('right motor armature (volt)'); subplot(3,3,8),plot(simout.tout, simout.vl_flc), xlabel('t(s)'), ylabel('left motor armature (volt)'); subplot(3,3,9),plot(simout.tout, simout.vl_flc, 'r', simout.tout, simout.vr_flc, 'b'), xlabel('t(s)'), ylabel('armature (volt)'); ``` We use the same motor model (C23-L33-W20) from Ref.[3]. It is the most realistic because the terminal voltage to operate this motor is $12V$. But there is difference in inductance value than the previous model. Now we use $La= 0.94\cdot10^{-3}H$. Previously we use $La= 0.94H$. It is pretty extreme difference. The other parameter we changed is the moment of inertia. So we assume the robot is a disk with the center of the mass in its center. Robot mass is $1Kg$ with the radius of $20cm$. Using a tool from Ref. [[6]](https://www.omnicalculator.com/physics/mass-moment-of-inertia), we can roughly estimate the mass moment inertia of the robot as $J=0.01\ Kg\ m^2$. The most important part is the gear ratio parameter. We chose gear ratio $N=10$ to simulate a high torque motor. Higher $N$ will produce higher torque ($\tau=NK_ti_a$). ---- Here is when we place the goal to $(-10,0)$. Let's see if the robot can reach the goal which is $10m$ behind it. Using this parameter, the result is pretty good. The robot reach distance of $10m$ in 3 seconds or with a speed of $10.8km/s$. For comparison, human walk roughly with speed of 5km/h, or about $1.4m/s$. So, we conclude that the result seems logical or realistic. We can continue research on using this model. ![](https://i.imgur.com/JfkhLsK.jpg) ---- # Conclusion The designed system is good enough. We just need a right parameter to make a simulation that is close to real life results.The controller is good but still we would like to know the result if we allows backward movement, so the robot will not miss the goal. For the future work, we can use the last parameter combined with a better controller and see if we got better results. --- # Trying another controller ---- ## Heading error fuzzification We use $9$ classes. Error is calculated in degree angles. ![](https://i.imgur.com/O5jZtHY.png) ---- ## Distance error fuzzification We use $11$ classes. Error is calculated in the unit of meters. ![](https://i.imgur.com/H9UZGdF.png) ---- ## Motor voltage fuzzification We use 11 classes. The output voltage is in the unit of volts. ![](https://i.imgur.com/7XUqaaQ.png) ---- ## Rules ![](https://i.imgur.com/P7lZx3c.png) ---- ## Code ```c= function [v_r,v_l] = tflc(position_error,orientation_error) %% global constant %TFLC RULES r_w_v = [ %Rules for right wheel 1 1 1 1 1 2 2 3 4; 1 1 1 2 2 3 3 4 5; 1 1 2 2 3 4 4 5 6; 1 1 2 3 4 5 5 5 7; 1 2 3 4 5 6 6 6 8; 1 2 3 4 6 7 7 7 9; 1 2 4 5 7 8 8 9 10; 1 3 5 6 8 9 9 10 11; 1 4 5 6 9 10 10 11 11; 1 4 6 7 10 10 11 11 11; 1 4 6 8 11 11 11 11 11; ]; l_w_v = flip(r_w_v,2); %Rules for left wheel %% run all nested function %fuzzyfication fuz_dist = check_distance_membership(position_error); % in meter fuz_orie = check_err_angle_membership(orientation_error); % in degree angle %inference [v_TFLC_R_th,v_TFLC_L_th]=relate_dis_head(fuz_dist, fuz_orie, r_w_v, l_w_v); %calculating centroid TFLC L dt = 0.01; t = -1:dt:13; %output data range out = []; for i=1:length(t) ret=check_velocity_membership(t(i)); %output fuzzification ret = min(v_TFLC_L_th, ret); %Max value / real value of the inference out = [out max(ret)]; %MAX end centeroid_TFLC_L = sum(out.*t)/sum(out); %calculating centroid TFLC R out = []; for i=1:length(t) ret=check_velocity_membership(t(i)); %output fuzzification ret = min(v_TFLC_R_th, ret); %Max value / real value of the inference out = [out max(ret)]; %MAX end centeroid_TFLC_R = sum(out.*t)/sum(out); %actuate the wheel v_r = centeroid_TFLC_R; v_l = centeroid_TFLC_L; %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% FUNCTIONS %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% =====================to check all value in distance fuzzification function out = check_distance_membership(input) %meter d0 = triangle (input, 0.0, 0.0, 0.3, 1, 1, 0); %scale 0 d1 = triangle (input, 0.0, 0.3, 0.6, 0, 1, 0); %scale 1 d2 = triangle (input, 0.3, 0.6, 0.9, 0, 1, 0); %scale 2 d3 = triangle (input, 0.6, 0.9, 1.2, 0, 1, 0); %scale 3 d4 = triangle (input, 0.9, 1.2, 1.5, 0, 1, 0); %scale 4 d5 = triangle (input, 1.2, 1.5, 1.8, 0, 1, 0); %scale 5 d6 = triangle (input, 1.5, 1.8, 2.1, 0, 1, 0); %scale 6 d7 = triangle (input, 1.8, 2.1, 2.4, 0, 1, 0); %scale 7 d8 = triangle (input, 2.1, 2.4, 2.7, 0, 1, 0); %scale 8 d9 = triangle (input, 2.4, 2.7, 3.0, 0, 1, 0); %scale 9 d10 = triangle(input, 2.7, 3.0, 3.0, 0, 1, 1); %scale 10 out = [d0;d1;d2;d3;d4;d5;d6;d7;d8;d9;d10]; end %% =====================to check all value in angle error fuzzification function out = check_err_angle_membership(input) nl = triangle (input, -180, -160, -120, 1, 1, 0); %negative large nm = triangle (input, -160, -120, -80, 0, 1, 0); %negative medium ns = triangle (input, -120, -80, -40, 0, 1, 0); %negative small n = triangle (input, -80, -40, 0, 0, 1, 0); %negative z = triangle (input, -40, 0, 40, 0, 1, 0); %zero p = triangle (input, 0, 40, 80, 0, 1, 0); %positive ps = triangle (input, 40, 80, 120, 0, 1, 0); %positive small pm = triangle (input, 80, 120, 160, 0, 1, 0); %positive medium pl = triangle (input, 120, 160, 180, 0, 1, 1); %positive large out = [nl; nm; ns; n; z; p; ps; pm; pl]; end %% =====================to check all value in velocity of motors in TFLC fuzzification function out = check_velocity_membership(input) v0 = triangle (input, 0, 0, 1, 1, 1, 0);%zero v1 = triangle (input, 0, 1, 2, 0, 1, 0);%slow v2 = triangle (input, 1, 2, 3, 0, 1, 0);%near medium v3 = triangle (input, 2, 3, 4, 0, 1, 0);%medium v4 = triangle (input, 3, 4, 5, 0, 1, 0);%near high v5 = triangle (input, 4, 5, 6, 0, 1, 0);%high v6 = triangle (input, 5, 6, 7, 0, 1, 0);%very high v7 = triangle (input, 6, 7, 8, 0, 1, 0);%very high v8 = triangle (input, 7, 8, 9, 0, 1, 0);%very high v9 = triangle (input, 8, 9, 11, 0, 1, 0);%very high v10 = triangle (input, 9, 10, 12, 0, 1, 1);%very high out = [v0;v1;v2;v3;v4;v5;v6;v7;v8;v9;v10]; end %% ===============triangle shaped fuzzy membership function out = triangle (input, start, middle, stop, str_val, mid_val, sto_val) if input<start out = str_val; elseif (input>=start) && (input<middle) v = (mid_val-str_val)/(middle-start); out = str_val + v*(input-start); elseif (input==middle) out = mid_val; elseif (input>middle) && (input<=stop) v = (sto_val-mid_val)/(stop-middle); out = mid_val + v*(input-middle); elseif input>stop out = sto_val; else out = 0; end end %% =Relate one fuzzification to another: matrix & vec====== % the relation is using minimum, because the relation in fuzzy rules are % using AND function [v_out_R, v_out_L] = relate_dis_head(distance, heading, rules_R, rules_L) % set1 is rows, and set2 is columns % find correspoding values for each rules m = zeros(length(distance), length(heading)); for i=1:length(distance) for j=1:length(heading) m(i,j)=min(distance(i),heading(j)); %MIN end end % find the output index of each rules values % then create vector, of possible maximum mambership value from output % membership class v_out_R = zeros(max(max(rules_R)),1); v_out_L = v_out_R; [w,h]=size(rules_R); for i = 1:w for j = 1:h v_out_R( rules_R(i,j) ) = max(v_out_R( rules_R(i,j) ), m (i,j)); %MAX v_out_L( rules_L(i,j) ) = max(v_out_L( rules_L(i,j) ), m (i,j)); %MAX end end end end ``` ---- ## Result This is the result when the goal posiiton is $10m$ behind the robot.The control is faster, and it can stop at the goal position. ![](https://i.imgur.com/V4BaIdG.png) ---- And this is the plot of speed, position, and heading over time period. The result is better than before. ![](https://i.imgur.com/kBiqyUj.png) ---- This is the result when the goal is $10m$ around the robot with various angles. ![](https://i.imgur.com/6HGV191.png) --- # Trying another controller 2 ## Modify angle classes ![](https://i.imgur.com/iikDsKD.png) ## Rules modification ![](https://i.imgur.com/egtZntM.png) ## Code ```c= function [v_r,v_l] = tflc(position_error,orientation_error) %% global constant %TFLC RULES r_w_v = [ %Rules for right wheel 1 1 1 1 1 1 2 3 4 5 6; 1 1 1 1 1 2 3 4 5 6 7; 1 1 1 1 2 3 4 5 6 7 8; 1 1 1 2 3 4 5 6 7 8 9; 1 1 2 3 4 5 6 7 8 9 10; 1 2 3 4 5 6 7 8 9 10 11; 1 1 2 3 5 7 8 9 10 11 11; 1 1 1 4 6 8 9 10 11 11 11; 1 1 1 1 7 9 10 11 11 11 11; 1 1 1 1 1 10 11 11 11 11 11; 1 1 1 1 1 11 11 11 11 11 11; ]; l_w_v = flip(r_w_v,2); %Rules for left wheel %% run all nested function %fuzzyfication fuz_dist = check_distance_membership(position_error); % in meter fuz_orie = check_err_angle_membership(orientation_error); % in degree angle %inference [v_TFLC_R_th,v_TFLC_L_th]=relate_dis_head(fuz_dist, fuz_orie, r_w_v, l_w_v); %calculating centroid TFLC L dt = 0.01; t = -1:dt:13; %output data range out = []; for i=1:length(t) ret=check_velocity_membership(t(i)); %output fuzzification ret = min(v_TFLC_L_th, ret); %Max value / real value of the inference out = [out max(ret)]; %MAX end centeroid_TFLC_L = sum(out.*t)/sum(out); %calculating centroid TFLC R out = []; for i=1:length(t) ret=check_velocity_membership(t(i)); %output fuzzification ret = min(v_TFLC_R_th, ret); %Max value / real value of the inference out = [out max(ret)]; %MAX end centeroid_TFLC_R = sum(out.*t)/sum(out); %actuate the wheel v_r = centeroid_TFLC_R; v_l = centeroid_TFLC_L; %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% FUNCTIONS %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% =====================to check all value in distance fuzzification function out = check_distance_membership(input) %meter d0 = triangle (input, 0.0, 0.0, 0.3, 1, 1, 0); %scale 0 d1 = triangle (input, 0.0, 0.3, 0.6, 0, 1, 0); %scale 1 d2 = triangle (input, 0.3, 0.6, 0.9, 0, 1, 0); %scale 2 d3 = triangle (input, 0.6, 0.9, 1.2, 0, 1, 0); %scale 3 d4 = triangle (input, 0.9, 1.2, 1.5, 0, 1, 0); %scale 4 d5 = triangle (input, 1.2, 1.5, 1.8, 0, 1, 0); %scale 5 d6 = triangle (input, 1.5, 1.8, 2.1, 0, 1, 0); %scale 6 d7 = triangle (input, 1.8, 2.1, 2.4, 0, 1, 0); %scale 7 d8 = triangle (input, 2.1, 2.4, 2.7, 0, 1, 0); %scale 8 d9 = triangle (input, 2.4, 2.7, 3.0, 0, 1, 0); %scale 9 d10 = triangle(input, 2.7, 3.0, 3.0, 0, 1, 1); %scale 10 out = [d0;d1;d2;d3;d4;d5;d6;d7;d8;d9;d10]; end %% =====================to check all value in angle error fuzzification function out = check_err_angle_membership(input) nxl = triangle (input, -180, -150, -120, 1, 1, 0); %negative large nl = triangle (input, -150, -120, -90, 0, 1, 0); %negative large nm = triangle (input, -120, -90, -60, 0, 1, 0); %negative medium ns = triangle (input, -90, -60, -30, 0, 1, 0); %negative small n = triangle (input, -60, -30, 0, 0, 1, 0); %negative z = triangle (input, -30, 0, 30, 0, 1, 0); %zero p = triangle (input, 0, 30, 60, 0, 1, 0); %positive ps = triangle (input, 30, 60, 90, 0, 1, 0); %positive small pm = triangle (input, 60, 90, 120, 0, 1, 0); %positive medium pl = triangle (input, 90, 120, 150, 0, 1, 0); %positive large pxl = triangle (input, 120, 150, 180, 0, 1, 1); %positive large out = [nxl; nl; nm; ns; n; z; p; ps; pm; pl; pxl]; end %% =====================to check all value in velocity of motors in TFLC fuzzification function out = check_velocity_membership(input) v0 = triangle (input, 0, 0, 1, 1, 1, 0);%zero v1 = triangle (input, 0, 1, 2, 0, 1, 0);%slow v2 = triangle (input, 1, 2, 3, 0, 1, 0);%near medium v3 = triangle (input, 2, 3, 4, 0, 1, 0);%medium v4 = triangle (input, 3, 4, 5, 0, 1, 0);%near high v5 = triangle (input, 4, 5, 6, 0, 1, 0);%high v6 = triangle (input, 5, 6, 7, 0, 1, 0);%very high v7 = triangle (input, 6, 7, 8, 0, 1, 0);%very high v8 = triangle (input, 7, 8, 9, 0, 1, 0);%very high v9 = triangle (input, 8, 9, 11, 0, 1, 0);%very high v10 = triangle (input, 9, 10, 12, 0, 1, 1);%very high out = [v0;v1;v2;v3;v4;v5;v6;v7;v8;v9;v10]; end %% ===============triangle shaped fuzzy membership function out = triangle (input, start, middle, stop, str_val, mid_val, sto_val) if input<start out = str_val; elseif (input>=start) && (input<middle) v = (mid_val-str_val)/(middle-start); out = str_val + v*(input-start); elseif (input==middle) out = mid_val; elseif (input>middle) && (input<=stop) v = (sto_val-mid_val)/(stop-middle); out = mid_val + v*(input-middle); elseif input>stop out = sto_val; else out = 0; end end %% =Relate one fuzzification to another: matrix & vec====== % the relation is using minimum, because the relation in fuzzy rules are % using AND function [v_out_R, v_out_L] = relate_dis_head(distance, heading, rules_R, rules_L) % set1 is rows, and set2 is columns % find correspoding values for each rules m = zeros(length(distance), length(heading)); for i=1:length(distance) for j=1:length(heading) m(i,j)=min(distance(i),heading(j)); %MIN end end % find the output index of each rules values % then create vector, of possible maximum mambership value from output % membership class v_out_R = zeros(max(max(rules_R)),1); v_out_L = v_out_R; [w,h]=size(rules_R); for i = 1:w for j = 1:h v_out_R( rules_R(i,j) ) = max(v_out_R( rules_R(i,j) ), m (i,j)); %MAX v_out_L( rules_L(i,j) ) = max(v_out_L( rules_L(i,j) ), m (i,j)); %MAX end end end end ``` ## Results ![](https://i.imgur.com/u1YgolJ.png) ![](https://i.imgur.com/4PS2rzh.png) From the result we can see that the system is capable of faster heading correction! Not only it can maneuver sharply from far away, but also from close distance. ![](https://i.imgur.com/SaFTKi6.png) ![](https://i.imgur.com/5o0HqXN.png) This is beacuse we introduce a turning only region in the fuzzy rules. Here is the rules for right motor output voltage. The yellow marked region is the region where the robot will only turning, without moving forward. It is either when the robot is too far from the goal position or too close to the goal position. ![](https://i.imgur.com/3uSnLjW.png) # Path tracking upgrade In this part we add algorithm for the robot to follow point array. This sceme is similar to Line follower robot. The robot will approach one of the points. When the distance of the robot to that point is bellow 0.1 m $(position error < 0.1m)$, the robot will approch the next point. Block diagram: ![](https://i.imgur.com/Rls2n4O.png) The changes that I made are `path_iterator` function and `robot_path` constant variable. `robot_path` is array containing points. In this case, the points resemble figure of 8 (*the lemniscate of Gerono, or lemniscate of Huygens*). The job of `path_iterator` is to feed 1 point (x and y coordinate) to the system to approach. When the robot succesfully approach that point, `path_iterator` will feed another point. Code: ```c= function [i_next,x,y] = path_iterator(i, pos_err, robot_path) [r,c] = size(robot_path); if pos_err < 0.1 i = i + 1; if i > c i = 1; end end x = robot_path(1,i); y = robot_path(2,i); i_next = i; end ``` Because there is an iterative variable in that block, we need to give an initial value to that variable. We do by putting *Memory block* ![](https://i.imgur.com/P82GItp.png =50x) from HDL/Discrete library. We give both block initial value of $1$. To create the robot path, I made a routine in the matlab main code: ```c= %% the lemniscate of Gerono, or lemniscate of Huygens, or figure-eight curve t = 0:0.02: 2*pi; % t is between 1~2pi x = cos(t); y = sin(2*t)/2; plot(x,y); robot_path = [x;y]; ``` That code will give you a figure of 8 array. And this is the code in `path_iterator` function: ```c= function [i_next,x,y] = path_iterator(i, pos_err, robot_path) [r,c] = size(robot_path); if pos_err < 0.1 i = i + 1; if i > c i = 1; end end x = robot_path(1,i); y = robot_path(2,i); i_next = i; end %(i,pos_err) are initially 1 from memory block ``` This is the result of how the robot approach that points: ![](https://i.imgur.com/uGLm3QP.png) ![](https://i.imgur.com/h82Ppmk.png) # References [1] Faisal, Mohammed, et al. "Fuzzy logic navigation and obstacle avoidance by a mobile robot in an unknown dynamic environment." International Journal of Advanced Robotic Systems 10.1 (2013): 37. [2] Dhaouadi, Rached, and A. Abu Hatab. "Dynamic modelling of differential-drive mobile robots using lagrange and newton-euler methodologies: A unified framework." Advances in Robotics & Automation 2.2 (2013): 1-7. [3] [Moog Components Group, "Permanent Magnet DC Motors datasheet"](https://www.moog.com/content/dam/moog/literature/MCG/moc23series.pdf) [4] [MATLAB friction model](https://www.mathworks.com/help/simulink/slref/friction-model-with-hard-stops.html) [5] Li, Kai Way, et al. "Floor slipperiness measurement: friction coefficient, roughness of floors, and subjective perception under spillage conditions." Safety Science 42.6 (2004): 547-565. [6] [Mass Moment of Inertia Calculator](https://www.omnicalculator.com/physics/mass-moment-of-inertia) --- # Special thanks to 1. Professor Hsiu-Ming Wu of Taipei Tech ###### tags: `fuzzy logic` `matlab` `simulink` `robot`