--- slideOptions: transition: slide --- <style> .reveal { font-size: 24px; } </style> # Fuzzy Logic Navigation and Obstacle Avoidance "Implement Fuzzy Logic Controller in MATLAB and Simulate in V-REP" For better look check this note, please visit [HackMD.io](https://hackmd.io/@libernormous/flc_nav_obs) by: Zaman : me@zamzaman.com --- # Flow chart of the program ![Blok diagram](https://i.imgur.com/XFlxjQa.png =350x) --- # Starting simulation Detailed explanation of Integrating V-REP with MATLAB can be checked here: [V-Rep tutorial](https://hackmd.io/@libernormous/v-rep) At the beginning of the program there is always: ```c= vrep=remApi('remoteApi'); % using the prototype file (remoteApiProto.m) vrep.simxFinish(-1); % just in case, close all opened connections clientID=vrep.simxStart('127.0.0.1',19999,true,true,5000,5); if (clientID>-1) %//RUN EVERYTHING INSIDE end ``` And the program should only run when when MATLAB and V-REP are connected (`if (clientID>-1)`). --- # Getting object handlers We have 7 objects that we use in the program. 1. Pioneer-p3dx robot. string ID: `Pioneer_p3dx` We use this object to find the orientation and position of ROBOT body. 3. Goal object. Flat blue circular object. string ID: `GOAL` We use this object to find the orientation and position of GOAL body. 5. Right wheel of Pioneer-p3dx. string ID: `Pioneer_p3dx_rightMotor` We use this object to actuate the right wheel. 7. Left wheel of Pioneer-p3dx. string ID: `Pioneer_p3dx_leftMotor` We use this object to actuate the left wheel. 9. 3 ultrasound sensors of Pioneer-p3dx. string IDs: `Pioneer_p3dx_ultrasonicSensor2, Pioneer_p3dx_ultrasonicSensor5, Pioneer_p3dx_ultrasonicSensor7` ---- CODE: ```c= %get motor handler [returnCode,w_hdl(1)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_leftMotor',vrep.simx_opmode_blocking); [returnCode,w_hdl(2)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_rightMotor',vrep.simx_opmode_blocking); %get ultrasound handler [returnCode,ultsnd_h(1)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_ultrasonicSensor2',vrep.simx_opmode_blocking); [returnCode,ultsnd_h(2)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_ultrasonicSensor5',vrep.simx_opmode_blocking); %the angle of this sensor is little bit off [returnCode,ultsnd_h(3)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_ultrasonicSensor7',vrep.simx_opmode_blocking); %get robot and GOAL handler [returnCode,rob_h]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx',vrep.simx_opmode_blocking); [returnCode,gol_h]=vrep.simxGetObjectHandle(clientID,'GOAL',vrep.simx_opmode_blocking); ``` --- # Calculating Position Error 1. First we need to get the position of the pioneer robot and the goal object ```c= %% %get robot pos and orientation [returnCode,rob_poss]=vrep.simxGetObjectPosition(clientID,rob_h,-1,vrep.simx_opmode_blocking); %ret in meter, vecor [returnCode,rob_ortt]=vrep.simxGetObjectOrientation(clientID,rob_h,-1,vrep.simx_opmode_blocking); %ret in radian, vector %get goal pos and orientation [returnCode,gol_poss]=vrep.simxGetObjectPosition(clientID,gol_h,-1,vrep.simx_opmode_blocking); %ret in meter, vecor [returnCode,gol_ortt]=vrep.simxGetObjectOrientation(clientID,gol_h,-1,vrep.simx_opmode_blocking); %ret in radian, vecor ``` 2. To get position use function `vrep.simxGetObjectPosition` and `vrep.simxGetObjectOrientation` to get orientation. 3. `rob_poss` return position of the robot in vector $^W\mathbf{p}_R = (R_x, {R_y}, {R_z})$ relative to world frame $\{W\}$. The unit is meter. 4. `rob_ortt` return orientation vector $^W\xi_R = (R_\alpha, R_\beta, R_\gamma)$ relative to world frame $\{W\}$. Where $(\alpha, \beta, \gamma)$ are Euler rotation angles in X, Y, and Z axes respectively. The value ranging from $-\pi$ to $+\pi$. The unit is radian. 5. Same goes with `gol_poss` and `gol_ortt`. It return $^W\mathbf{p}_G = (G_x, {G_y}, {G_z})$ and $^W\xi_G = (G_\alpha, G_\beta, G_\gamma)$ respectively. ---- 6. To calculate position error or distance error we can use Euclidean distance between two points. $$ d = \sqrt{(R_x-G_x)^2+(R_y-G_y)^2+(R_z-G_z)^2} $$ ```c= %position error vec_pos = gol_poss-rob_poss; pos_err = sqrt(sum((vec_pos).^2)); %in meter ``` --- # Calculating Heading Error ![](https://i.imgur.com/hufG12F.png =500x) 1. To caculate Heading error we need to represent the position of coordinate frame of the goal $\{G\}$ relative to robot frame coordinate $\{R\}$. ---- 2. We can do this by using transformation matrix in 2D $$ \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 \end{align} $$ 4. Here we introduce $^W\tilde{P}_G$ and $^R\tilde{P}_G$ as homogenous coordinate notation of $^W{P}_G$ and $^R{P}_G$ respectively, where. $$ ^W\tilde{P}_G = \left( \begin{matrix} G_x\\ G_y\\ 1 \end{matrix} \right) \ \ \text{and} \ \ ^R\tilde{P}_G = \left( \begin{matrix} ^RG_x\\ ^RG_y\\ 1 \end{matrix} \right) $$ 5. And we find $\gamma_e$ as $$ \gamma_e = \text{atan2}(^RG_y\ ,\ ^RG_x) $$ 6. The result is in radian angle ---- CODE: ```c= %% %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); ``` --- # Reading sensor state (detecting or not detecting obstacle) 1. The sensor we are using is ultrasound sensor. There are many ultrasound sensors in Pioneer robot. But we use only 3 sensors as stated in Ref. [1]. 2. We read the sensor state using `vrep.simxReadProximitySensor()` function. CODE: ```c= %% %get sensor data detectedPoint={}; detectionState=zeros(3,1); for i=1:3 [returnCode,detectionState(i),detectedPoint{i},detectedObjectHandle,detectedSurfaceNormalVector]=vrep.simxReadProximitySensor(clientID,ultsnd_h(i),vrep.simx_opmode_blocking); end ``` 3. It returns 2 important values. `detectionState` contain `true` for detecting object and `false` for not detecting object. 4. `detectedPoint` return $3\times1$ vector containing the distance of detected object in X, Y, and Z direction respectively. Here we only use distance in Z direction. ---- 6. If the sensor detects and object, we keep the measured value; If not we assign $400$ centimeter as the default value. ```c= % sensor value constrain from 0 cm to 400 cm for i=1:3 if detectionState(i) ultsnd_masure_Zaxs(i) = detectedPoint{i}(3) *100; % ret in centimeter, vector else ultsnd_masure_Zaxs(i) = 400; end end ``` 7. To simulate the real ultrasound sensor, we define "object detected" as if one of the sensor measures a value below $80cm$. ```c= if min(ultsnd_masure_Zaxs)<80 %//OBSTACLE DETECTED, OAFLC control %% //OAFLC control routine %% //Then actuate the wheel else %//obstacle NOT detected, TFLC control %% //TFLC control routine %% //Then actuate the wheel end ``` --- # Fuzzy Control Detailed explanation of how I create fuzzy logic control can be checked here : [Fuzzy Notes](https://hackmd.io/@libernormous/fuzzy) ---- ## Robot to goal distance membership functions Input value is in meter. ![](https://i.imgur.com/gN8szNg.png) ---- ## Robot to goal heading angle membership functions I use the same as in Ref. [1]. The input is in degree angle. ![](https://i.imgur.com/Qpwd74p.png) ---- ## Output of TFLC (Tracking Fuzzy logic control) I use the same as in Ref. [1]. I assume the output is in $deg/s$. ![](https://i.imgur.com/QpmcfKR.png) ---- ## TFLC Rules I use the same as in Ref. [1]. ![](https://i.imgur.com/qndzMFK.png) ---- ## Sensor measured distance membership function I modify the input because it $70cm$ seems to be to late for the robot to respond. Input is in centimeter. ![](https://i.imgur.com/P1ul9vF.png) ---- ## Output of OAFLC (Obstacle Avoidance Fuzzy logic control) I modify the crisp output since $15 deg/s$ seems to be to fast for the robot to turn. ![](https://i.imgur.com/LFSF72R.png) ---- ## OAFLC Rules I use the same as in Ref. [1]. ![](https://i.imgur.com/UQBvkbd.png) --- # Actuating the wheels 1. To actuate the wheel we use VREP function `vrep.simxSetJointTargetVelocity()`. The function expects a speed input in $deg/s$ unit. 2. NOTE for TFLC control. Because the output of the control seems to be too fast, the robot is slithering like a snake to reach the goal and the robot will not stop at the goal. So, I divide the crisp output by $2$ to slowdown the robot. Also, I switch the output of left and right output of TFLC control. because, if not, somehow the output is a positive feedback. CODE: ```c= %//actuate the wheel centeroid_TFLC_L=centeroid_TFLC_L/2; %divide by 2 to slowdown centeroid_TFLC_R=centeroid_TFLC_R/2; %divide by 2 to slowdown %//somehow I need to flip R and L to make it work, if not it'd be %//possitive feedback [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(1),centeroid_TFLC_R,vrep.simx_opmode_blocking);%left [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(2),centeroid_TFLC_L,vrep.simx_opmode_blocking);%right ``` --- # Stopping simulation At the end of the simulation there is always an object destructor routine. CODE: ```c= [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(1),0,vrep.simx_opmode_blocking); [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(2),0,vrep.simx_opmode_blocking); vrep.delete(); % call the destructor! ``` --- # Video Results ## TFLC Simulation using V-REP {%youtube tAe7P6DFXdQ %} ---- ## OAFLC Simulation using V-REP {%youtube qADtNtXeQIE %} ---- ## TFLC and OAFLC combined {%youtube Q6hWn8U3ps0 %} --- # Graph Results of (TFLC only) ---- ## Robot position ![](https://i.imgur.com/wRIeAKz.png) ---- ## Angular velocity of both wheels ![](https://i.imgur.com/5OMrly7.png) Blue line is angular velocity of right wheel. Red line is angular velocity of left wheel. Both values are in $deg/s$. Cyan dotted lines is the state of detection. ---- ## Robot velocity ![](https://i.imgur.com/cCmxJS8.png) Black line is velocity magnitude of the robot in $m/s$. Cyan dotted lines is the state of detection. ---- ## Robot heading ![](https://i.imgur.com/XyfKoEJ.png) Black line is heading of the robot in $deg$. Cyan dotted lines is the state of detection. ---- ## Robot angular velocity ![](https://i.imgur.com/G5HbA88.png) Black line is angular velocity magnitude of the robot in $deg/s$. Cyan dotted lines is the state of detection. --- # Graph Results of (TFLC and OAFLC combined) ---- ## Robot position ![](https://i.imgur.com/kRm4ny5.png =600x) ---- ## Angular velocity of both wheels ![](https://i.imgur.com/JYGL5C3.png) Blue line is angular velocity of right wheel. Red line is angular velocity of left wheel. Both values are in $deg/s$. Cyan dotted lines is the state of detection. ---- ## Robot velocity ![](https://i.imgur.com/hwes7G3.png) Black line is velocity magnitude of the robot in $m/s$. Cyan dotted lines is the state of detection. ---- ## Robot heading ![](https://i.imgur.com/pUnzlXd.png) Black line is heading of the robot in $deg$. Cyan dotted lines is the state of detection. ---- ## Robot angular velocity ![](https://i.imgur.com/AfkrpPn.png) Black line is angular velocity magnitude of the robot in $deg/s$. Cyan dotted lines is the state of detection. --- # MATLAB CODE ```c= disp('Program started'); %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_L_var = {'z'; 's'; 'nm'; 'm'; 'nh'; 'h'; 'vh'}; 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; ]; var_OAFLC_output={'nh', 'n', 'p', 'hp', 'vhp'}; vrep=remApi('remoteApi'); % using the prototype file (remoteApiProto.m) vrep.simxFinish(-1); % just in case, close all opened connections clientID=vrep.simxStart('127.0.0.1',19999,true,true,5000,5); Ts = 0.05; %0.01 s = 10 ms %default simulation dt on vrep is 50 ms w_hdl = zeros(2,1); v_w = ones(2,1).*60*Ts; %degree/s convert to nominal/Ts ultsnd_h = zeros(3,1); ultsnd_masure_Zaxs = zeros(3,1); if (clientID>-1) disp('Connected to remote API server') %get motor handler [returnCode,w_hdl(1)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_leftMotor',vrep.simx_opmode_blocking); [returnCode,w_hdl(2)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_rightMotor',vrep.simx_opmode_blocking); %get ultrasound handler [returnCode,ultsnd_h(1)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_ultrasonicSensor2',vrep.simx_opmode_blocking); [returnCode,ultsnd_h(2)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_ultrasonicSensor5',vrep.simx_opmode_blocking); %the angle of this sensor is little bit off [returnCode,ultsnd_h(3)]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx_ultrasonicSensor7',vrep.simx_opmode_blocking); %get robot and GOAL handler [returnCode,rob_h]=vrep.simxGetObjectHandle(clientID,'Pioneer_p3dx',vrep.simx_opmode_blocking); [returnCode,gol_h]=vrep.simxGetObjectHandle(clientID,'GOAL',vrep.simx_opmode_blocking); n=0; while n<200 %-----getting data----- %get robot pos and orientation [returnCode,rob_poss]=vrep.simxGetObjectPosition(clientID,rob_h,-1,vrep.simx_opmode_blocking); %ret in meter, vecor [returnCode,rob_ortt]=vrep.simxGetObjectOrientation(clientID,rob_h,-1,vrep.simx_opmode_blocking); %ret in radian, vector %get goal pos and orientation [returnCode,gol_poss]=vrep.simxGetObjectPosition(clientID,gol_h,-1,vrep.simx_opmode_blocking); %ret in meter, vecor [returnCode,gol_ortt]=vrep.simxGetObjectOrientation(clientID,gol_h,-1,vrep.simx_opmode_blocking); %ret in radian, vecor %get sensor data detectedPoint={}; detectionState=zeros(3,1); for i=1:3 [returnCode,detectionState(i),detectedPoint{i},detectedObjectHandle,detectedSurfaceNormalVector]=vrep.simxReadProximitySensor(clientID,ultsnd_h(i),vrep.simx_opmode_blocking); end %-----processing data----- %position goal error / vector magnitude, and orientation error %position error vec_pos = gol_poss-rob_poss; pos_err = sqrt(sum((vec_pos).^2)); %in meter %orientation error gamma_r = rob_ortt(3); gamma_g = gol_ortt(3); rob_x_2_g_or = [cos(gamma_r) sin(gamma_r); -sin(gamma_r) cos(gamma_r)]*[cos(gamma_g) -sin(gamma_g); sin(gamma_g) cos(gamma_g)]*[1;0]; orr_err = atan2(rob_x_2_g_or(2), rob_x_2_g_or(1)); orr_err = rad2deg(orr_err); %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); % sensor value constrain from 0 cm to 400 cm for i=1:3 if detectionState(i) ultsnd_masure_Zaxs(i) = detectedPoint{i}(3) *100; % ret in centimeter, vector else ultsnd_masure_Zaxs(i) = 400; end end %-----Controller START here----- if min(ultsnd_masure_Zaxs)<60 %OBSTACLE DETECTED, OAFLC control %----------OAFLC control %fuzzyfication fuz_s1 = check_obstacle_membership(ultsnd_masure_Zaxs(1)); %left sensor fuz_s2 = check_obstacle_membership(ultsnd_masure_Zaxs(2)); %front sensor fuz_s3 = check_obstacle_membership(ultsnd_masure_Zaxs(3)); %right sensor %inference [mat_rules_val,v_OAFLC_L_th, v_OAFLC_R_th] = relate_OAFLC (fuz_s1, fuz_s2, fuz_s3, rules_OAFLC_R_L); %calculating centroid OAFLC R dt = 0.01; t = -10:dt:15; %output data range out = []; for i=1:length(t) ret=check_vl_vr_oaflc_membership(t(i)); %output fuzzification ret = min(v_OAFLC_R_th, ret); %Max value / real value of the inference out = [out max(ret)]; %MAX end centeroid_OAFLC_R = sum(out.*t)/sum(out) %calculating centroid OAFLC L out = []; for i=1:length(t) ret=check_vl_vr_oaflc_membership(t(i)); %output fuzzification ret = min(v_OAFLC_L_th, ret); %Max value / real value of the inference out = [out max(ret)]; %MAX end centeroid_OAFLC_L = sum(out.*t)/sum(out) %actuate the wheel [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(1),centeroid_OAFLC_L,vrep.simx_opmode_blocking);%left [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(2),centeroid_OAFLC_R,vrep.simx_opmode_blocking);%right else %obstacle NOT detected, TFLC control %----------TFLC control %fuzzyfication fuz_dist = check_distance_membership(pos_err); fuz_orie = check_err_angle_membership(hed_err); %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 centeroid_TFLC_L=centeroid_TFLC_L/2; centeroid_TFLC_R=centeroid_TFLC_R/2; %somehow I need to flip R and L to make it work, if not it'd be %possitive feedback [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(1),centeroid_TFLC_R,vrep.simx_opmode_blocking);%left [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(2),centeroid_TFLC_L,vrep.simx_opmode_blocking);%right end %-----Controller END here----- %increamnet counter n=n+1; %BREAK LOOP BY BUTTON ButtonHandle = uicontrol('Style', 'PushButton', ... 'String', 'Stop loop', ... 'Callback', 'delete(gcbf)'); drawnow; if ~ishandle(ButtonHandle) disp('Loop stopped by user'); break; end end vrep.simxFinish(clientID); else disp('Failed connecting to remote API server'); end [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(1),0,vrep.simx_opmode_blocking); [returnCode]=vrep.simxSetJointTargetVelocity(clientID,w_hdl(2),0,vrep.simx_opmode_blocking); vrep.delete(); % call the destructor! disp('Program ended'); %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% FUNCTIONS %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% =====================to check all value in distance fuzzification function out = check_distance_membership(input) 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 %% =====================to check all value from sensor function out = check_obstacle_membership(input) n = trapezoid (input, 0, 10, 30, 40, 0, 1, 1, 0);%near m = trapezoid (input, 30, 40, 60, 70, 0, 1, 1, 0);%medium f = trapezoid (input, 60, 70, 90, 100, 0, 1, 1, 1);%far out = [n;m;f]; end %% =====================to check all value in LV and RV of OAFLC function out = check_vl_vr_oaflc_membership(input) nh = triangle (input, -10, -5, 0, 0, 1, 0);%negative high n = triangle (input, -5, -2.5, 0, 0, 1, 0);%negative p = triangle (input, 0, 2.5, 5, 0, 1, 0);%positive hp = triangle (input, 0, 5, 10, 0, 1, 0);%high positive vhp = triangle (input, 5, 7.5, 10, 0, 1, 0);%very high positive out = [nh;n;p;hp;vhp]; 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 %% Relate a fuzzification to another with the result of rules table & vec % the relation is using minimum, because the relation in fuzzy rules are % using AND function [mat_rules_val,v_out_th1, v_out_th2] = relate_OAFLC (set1, set2, set3, rules_index) % find correspoding values for each rules m = zeros(size(rules_index)); c = 0; for i=1:length(set1) for j=1:length(set2) for k=1:length(set3) c = c+1; MIN = min(min(set1(i),set2(j)),set3(k)); m(c,1)=MIN; %MIN output1 m(c,2)=MIN; %MIN output2 end end end % find the output index of each rules values % then create vector, of possible maximum mambership value from output % membership class v_out1 = zeros(max(rules_index(:,1)),1); % vector output1 v_out2 = zeros(max(rules_index(:,2)),1); % vector output2 [h,w]=size(rules_index); for i = 1:h v_out1( rules_index(i,1) ) = max(v_out1( rules_index(i,1) ), m(i,1)); %MAX v_out2( rules_index(i,2) ) = max(v_out2( rules_index(i,2) ), m(i,2)); %MAX end mat_rules_val = m; v_out_th1 = v_out1; v_out_th2 = v_out2; 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; end end %% ===============trapezoid shaped fuzzy membership function out = trapezoid (input, start, middle1, middle2, stop, str_val, mid1_val, mid2_val, sto_val) if input<start out = str_val; elseif (input>=start) && (input<middle1) v = (mid1_val-str_val)/(middle1-start); out = str_val + v*(input-start); elseif (input==middle1) out = mid1_val; elseif (input>middle1) && (input<middle2) v = (mid2_val-mid1_val)/(middle2-middle1); out = mid1_val + v*(input-middle1); elseif (input==middle2) out = mid2_val; elseif (input>middle2) && (input<=stop) v = (sto_val-mid2_val)/(stop-middle2); out = mid2_val + v*(input-middle2); elseif input>stop out = sto_val; end end ``` --- # 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. ###### tags: `fuzzy logic` `matlab` `vrep` `robot` --- # Special thanks to 1. Professor Hsiu-Ming Wu of Taipei Tech