gusucode.com > 模糊控制工具箱 fuzzy logic toolbox源码程序 > fuzzy/fuzdemos/juggler.m
function [o1,o2,o3] = juggler(x_prev, y_prev, v_prev, delta_t, action) %JUGGLER Ball juggling system. % JUGGLER opens a window for the animation of the ball juggling % system. The small triangle indicates the desired ball position. % You can choose either human or fuzzy control to control this % system. If it is controlled by human, click the steering arrow % at the upper right corner to change the tilted angle of the % hitting board. If it is controlled by the fuzzy controller, use % the mouse to change the location of the triangle. (If fuzzy % controller is selected, the position of the small triangle will % also be updated randomly every 200 steps) % % File: juggler.m % % See also FUZDEMOS. % Roger Jang, 3-9-94, 10-20-94, 12-23-94. Kelly Liu, 11-20-97 % Copyright 1994-2004 The MathWorks, Inc. % $Revision: 1.17.2.2 $ $Date: 2004/04/10 23:15:21 $ if nargin == 0, action = 'initialize'; end global JugFigH JugFigTitle JugAxisH global JugAnimRunning JugAnimStepping JugAnimPause JugAnimClose global JugUpdateBoard JugCount global JugBallRadius xMin xMax ProjAngle theta global DesiredPos SamplingTime xNextHit g global JugFisMat if strcmp(action, 'next_pos'), % Returns [x, y, v] at the next point o1 = x_prev + real(v_prev)*delta_t; o2 = y_prev + imag(v_prev)*delta_t - 0.5*g*delta_t^2; o3 = real(v_prev) + j*(imag(v_prev) - g*delta_t); elseif strcmp(action, 'single_loop'), % ====== get animation objects if ~ishandle(JugFigH) return; end ud = get(JugFigH, 'userdata'); ballH = ud(3, 1); plateH = ud(3, 2); refH = ud(3, 3); countH = ud(1, 6); ball = get(ballH, 'userdata'); controllerH = ud(2, 1); which_controller = get(controllerH, 'value'); plate = get(plateH, 'userdata'); ref = get(refH, 'userdata'); % ====== get state variables x_prev = ud(3, 8); y_prev = ud(3, 9); v_prev = ud(3, 10); % ====== Change the desired position randomly if it's fuzzy % this is good for self-running demo autoupdate = 1; if rem(JugCount, 200) == 0 & which_controller == 2 & autoupdate, bound = [xMin+1.5*JugBallRadius xMax-1.5*JugBallRadius]; DesiredPos = rand*(bound(2)-bound(1))+bound(1); new_ref = ref + DesiredPos; set(refH, 'xdata', real(new_ref), 'ydata', imag(new_ref)); end % ====== find next position [x, y, v] = eval([mfilename, ... '(x_prev, y_prev, v_prev, SamplingTime, ''next_pos'')']); % ====== When y is out of range if y < JugBallRadius, JugUpdateBoard = 1; vy_prev = imag(v_prev); t_hit = (vy_prev+(vy_prev*vy_prev+2*g*(y_prev-JugBallRadius))^0.5)/g; x_hit = x_prev + real(v_prev)*t_hit; % When the ball really hits the plate first if xMin+JugBallRadius <= x_hit & x_hit <= xMax-JugBallRadius, [x, y, v] = ... eval([mfilename, ... '(x_prev,y_prev,v_prev,''ground'',''reflect'')']); end end % ====== When x is out of range if ~(xMin+JugBallRadius <= x & x <= xMax-JugBallRadius), JugUpdateBoard = 1; if x < xMin + JugBallRadius, bound = xMin + JugBallRadius; else bound = xMax - JugBallRadius; end t_hit = abs(bound - x_prev)/real(v_prev); y_hit = y_prev + imag(v_prev)*t_hit + 0.5*g*t_hit^2; % When the ball really hits the wall first if y_hit > JugBallRadius & x < xMin+JugBallRadius, [x, y, v] = ... eval([mfilename, ... '(x_prev,y_prev,v_prev,''left_wall'',''reflect'')']); elseif y_hit > JugBallRadius & x > xMin+JugBallRadius, [x, y, v] = ... eval([mfilename, ... '(x_prev,y_prev,v_prev,''right_wall'',''reflect'')']); end end % Update plate position when the ball passes its highest point % or when the ball hits X bounds while it's falling if imag(v) < 0 & JugUpdateBoard, vy = imag(v); xNextHit = (vy + (vy*vy+2*g*(y-JugBallRadius))^0.5)/g*real(v)+x; xNextHit = min(max(xNextHit, ... xMin + JugBallRadius), xMax - JugBallRadius); if which_controller == 1, % human controlller set(plateH, 'xdata', xNextHit + real(plate)); else % fuzzy controller theta = ... eval([mfilename, '(x, y, v, [], ''fuzzy_controller'')']); theta = min(max(theta, -pi/4), pi/4); new_plate = plate*exp(j*theta); set(plateH, 'ydata', imag(new_plate), ... 'xdata', xNextHit + real(new_plate)); end JugUpdateBoard = 0; end % ====== count operation set(countH, 'string', int2str(JugCount)); JugCount = JugCount+1; % ====== update ball set(ballH, 'xdata', x + real(ball), 'ydata', y + imag(ball)); drawnow; % ====== put current state variables back into userdata ud(3, 8) = x; ud(3, 9) = y; ud(3, 10) = v; if ishandle(JugFigH) set(JugFigH, 'userdata', ud); end elseif strcmp(action, 'reflect') subaction = delta_t; if strcmp(subaction, 'ground'), % The ball did hit the plate first ProjAngle = ProjAngle + 2*theta; % ====== change project angle if it downward. if ProjAngle < 0, ProjAngle = -ProjAngle; fprintf('Bouncing from the ground, project angle = %d\n', ... ProjAngle*180/pi); elseif ProjAngle > pi, ProjAngle = 2*pi - ProjAngle; fprintf('Bouncing from the ground, project angle = %d\n', ... ProjAngle*180/pi); end vy_prev = imag(v_prev); t_hit = (vy_prev + (vy_prev*vy_prev+2*g*(y_prev-JugBallRadius))^0.5)/g; [x_hit, y_hit, v_in] = ... eval([mfilename, '(x_prev, y_prev, v_prev, t_hit, ''next_pos'')']); v_out = abs(v_in)*exp(j*ProjAngle); [o1, o2, o3] = ... eval([mfilename, '(x_hit, y_hit, v_out, SamplingTime-t_hit, ''next_pos'')']); % ====== The ball hits the wall also if o1 < xMin + JugBallRadius, bound = xMin + JugBallRadius; [o1, o2, o3] = ... eval([mfilename, '(2*bound-x_hit,JugBallRadius, -conj(v_out), SamplingTime-t_hit, ''next_pos'')']); ProjAngle = pi - ProjAngle; elseif o1 > xMax - JugBallRadius, bound = xMax - JugBallRadius; [o1, o2, o3] = ... eval([mfilename, '(2*bound-x_hit,JugBallRadius, -conj(v_out), SamplingTime-t_hit, ''next_pos'')']); ProjAngle = pi - ProjAngle; end % ====== Stay at ground if the ball cannot bounce if o2 < JugBallRadius o2 = y_prev; o3 = v_prev; end elseif strcmp(subaction, 'left_wall') % The ball did hit the left wall first bound = xMin + JugBallRadius; x_prev = 2*bound - x_prev; v_prev = -conj(v_prev); [o1, o2, o3] = ... eval([mfilename, '(x_prev, y_prev, v_prev, SamplingTime, ''next_pos'')']); ProjAngle = pi - ProjAngle; % The ball hits the ground also if o2 < JugBallRadius, [o1, o2, o3] = ... eval([mfilename, '(x_prev, y_prev, v_prev, ''ground'', ''reflect'')']); end elseif strcmp(subaction, 'right_wall') % The ball did hit the right wall first bound = xMax - JugBallRadius; x_prev = 2*bound - x_prev; v_prev = -conj(v_prev); [o1, o2, o3] = ... eval([mfilename, '(x_prev, y_prev, v_prev, SamplingTime, ''next_pos'')']); ProjAngle = pi - ProjAngle; % The ball hits the ground also if o2 < JugBallRadius, [o1, o2, o3] = ... eval([mfilename, '(x_prev, y_prev, v_prev, ''ground'', ''reflect'')']); end else fprintf('Subaction string = %s\n', subaction); error('Unknown subaction string in ''reflect''!'); end elseif strcmp(action, 'initialize'), JugFigTitle = 'Ball Juggling Animation'; JugFigH = findobj(0,'Name', JugFigTitle); JugCount = 1; if isempty(JugFigH) eval([mfilename, '(0,0,0,0,''set_all_gui'')']); eval([mfilename, '(0,0,0,0,''set_anim_obj'')']); eval([mfilename, '(0,0,0,0,''set_mouse_action'')']); eval([mfilename, '(0,0,0,0,''load_fis_mat'')']); % eval([mfilename, '(0,0,0,0,''single_loop'')']); % ====== change to normalized units set(findobj(JugFigH,'Units','pixels'), 'Units','normal'); % ====== make all UI interruptable set(findobj(JugFigH,'Interrupt','off'), 'Interrupt','on'); else % set(gcf, 'color', get(gcf, 'color')); refresh(JugFigH); end eval([mfilename, '(0,0,0,0,''set_constant'')']); eval([mfilename, '(0,0,0,0,''set_init_cond'')']); ud = get(JugFigH, 'userdata'); % set(ud(1, 1), 'visible', 'off'); % set(ud(1, 4:5), 'visible', 'off'); % set(ud(1, 2:3), 'visible', 'on'); set(JugFigH, 'HandleVisibility', 'callback'); elseif strcmp(action, 'set_constant'), JugAnimRunning = 0; JugAnimStepping = 0; JugAnimPause = 0; JugAnimClose = 0; JugUpdateBoard = 1; g = 9.8; SamplingTime = 0.02; %elseif strcmp(action, 'set_standard_gui'), % standard UI's elseif strcmp(action, 'set_all_gui'), % ====== standard UI's % ====== % No figure, initialize everything ui_row_n = 2; % No. of UI rows % ###### default UI settings for SIMUINK ###### JugFigH = figure( ... 'Name', JugFigTitle, ... 'CloseRequestFcn', 'juggler(0, 0, 0, 0, ''stop_anim''); closereq', ... 'NumberTitle', 'off', ... 'DockControls', 'off'); % V4 default color colordef(JugFigH, 'black'); % Black background set(JugFigH, 'color', [0 0 0]); set(0, 'Currentfigure', JugFigH); figPos = get(JugFigH, 'position'); % ====== proportion of UI frame and axes ui_area = 0.2; axis_area = 1-ui_area; % ====== animation area axisPos = [0 figPos(4)*ui_area figPos(3) figPos(4)*axis_area]; k = 1.0; x = axisPos(1); y = axisPos(2); w = axisPos(3); h = axisPos(4); axisPos = [x+w*(1-k)/2 y+h*(1-k)/2 w*k, h*k]; % weird thing: if you don't use normalized unit for % axes, patch for ground doesn't appear axisPos = axisPos./[figPos(3) figPos(4) figPos(3) figPos(4)]; JugAxisH = axes('unit', 'normal', 'pos', axisPos-[0 .0 0 0]); set(JugAxisH, 'visible', 'off'); % ====== background frame coverPos = [0 0 figPos(3) figPos(4)*ui_area]; [frameH, framePos] = uiarray(coverPos, 1, 1, 0); % ====== rows for UI controls spacing = 5; [H, Pos] = uiarray(framePos, ui_row_n, 1, spacing); % ====== split lower-most rows into 2 uneven regions delete(H(2)); [tmpH, tmpPos] = uiarray(Pos(2,:), 1, 6, 0, spacing); % lower left frame delete(tmpH(2:4)); lPos = tmpPos(1, :); lPos(3) = 4*lPos(3)+3*spacing; set(tmpH(1), 'pos', lPos); % lower right frame delete(tmpH(6)); rPos = tmpPos(5, :); rPos(3) = 2*rPos(3)+spacing; set(tmpH(5), 'pos', rPos); % ====== lower-right UI's (same for all SL animation) cb1 = [mfilename '(0,0,0,0,''info'')']; cb2 = [mfilename '(0,0,0,0,''close'')']; [lrH, lrPos] = uiarray(rPos, 1, 2, spacing, spacing, ... str2mat('push', 'push'), ... str2mat(cb1, cb2), ... str2mat('Help', 'Close')); infoH = lrH(1); set(infoH, 'tag', 'info'); closeH = lrH(2); set(closeH, 'tag', 'close'); % ====== lower-left UI's (same for all SL animation) cb1 = ''; cb2 = [mfilename '(0,0,0,0,''set_init_cond'');', ... mfilename '(0,0,0,0,''main_loop'');']; cb3 = ''; cb4 = ''; [llH, llPos] = uiarray(lPos, 1, 4, spacing, spacing, ... str2mat('text', 'push', 'text', 'text'), ... str2mat(cb1, cb2, cb3, cb4), ... str2mat('t = 0', 'Start Animation ...','','')); countH = llH(1); set(countH, 'tag', 'count'); % ====== extend the width of start button delete(llH(3:4)); startH = llH(2); set(startH, 'tag', 'start'); startPos = llPos(2,:); startPos(3) = 3*startPos(3)+2*spacing; set(startH, 'pos', startPos); % ====== create stop and pause (under start) cb1 = [mfilename '(0,0,0,0,''stop_anim'')']; cb2 = [mfilename '(0,0,0,0,''pause_anim'')']; cb3 = ''; [h, pos] = uiarray(startPos, 1, 3, 0,spacing,'push', ... str2mat(cb1, cb2, cb3), ... str2mat('Stop', 'Pause ...', '')); set(h, 'visible', 'off'); stopH = h(1); set(stopH, 'tag', 'stop'); pauseH = h(2); set(pauseH, 'tag', 'pause'); % ====== extend the width of pause button delete(h(3)); pausePos = pos(2, :); pausePos(3) = 2*pausePos(3)+spacing; set(pauseH, 'pos', pausePos); % ===== create continue and step (under pause) cb1 = [mfilename '(0,0,0,0,''continue_anim'')']; cb2 = [mfilename '(0,0,0,0,''step_anim'')']; [h, pos] = uiarray(pausePos, 1, 2, 0, spacing, ... 'push', ... str2mat(cb1, cb2), ... str2mat('Continue', 'Step')); set(h, 'visible', 'off'); contH = h(1); set(contH, 'tag', 'continue'); stepH = h(2); set(stepH, 'tag', 'step'); %===== put UI handles into current figure's user data ud = [startH stopH pauseH contH stepH countH -1 -1 -1 -1]; set(JugFigH, 'userdata', ud); %elseif strcmp(action, 'set_extra_gui'), % extra UI's % ====== extra UI % ====== The upper UI controls (Specific to each animation) cb1 = [mfilename '(0,0,0,0,''show_trail'')']; cb2 = [mfilename '(0,0,0,0,''clear_trail'')']; cb3 = ''; cb4 = [mfilename '(0,0,0,0,''set_mouse_action'')']; string1 = 'Show Trails'; string2 = 'Clear Trails'; string3 = 'Controller:'; string4 = 'Human|Fuzzy'; [upH, upPos] = uiarray(Pos(1,:), 1, 4, spacing, 2*spacing, ... str2mat('check', 'push', 'text', 'popup'), ... str2mat(cb1, cb2, cb3, cb4), ... str2mat(string1, string2, string3, string4)); set(upH(3), 'HorizontalAlignment', 'right'); controllerH = upH(4); showTrailH = upH(1); set(showTrailH, 'tag', 'show_trail'); set(controllerH, 'value', 2); % ====== Appending handles as the second row of userdata tmp = [controllerH showTrailH -1 -1 -1 -1 -1 -1 -1 -1]; set(JugFigH, 'userdata', [get(JugFigH, 'userdata'); tmp]); % ====== change labels of standard UI controls % ud = get(JugFigH, 'userdata'); % set(ud(1, 1), 'visible', 'off'); % set(ud(1, 2:3), 'visible', 'on'); elseif strcmp(action, 'set_init_cond'), JugCount = 1; theta = 0; ProjAngle = pi/3; v_magnitude = 4.5; x_prev = xMin + JugBallRadius; y_prev = JugBallRadius; v_prev = v_magnitude*exp(j*ProjAngle); ud = get(findobj(0, 'name', JugFigTitle), 'userdata'); ud(3, 8) = x_prev; ud(3, 9) = y_prev; ud(3, 10) = v_prev; set(JugFigH, 'userdata', ud); DesiredPos = (xMin+xMax)/2; % ====== set refH refH = ud(3, 3); ref = get(refH, 'userdata'); new_ref = ref + DesiredPos; set(refH, 'xdata', real(new_ref), 'ydata', imag(new_ref)); % ====== set plate plateH = ud(3, 2); plate = get(plateH, 'userdata'); new_plate = plate*exp(j*theta); set(plateH, 'xdata', real(new_plate), 'ydata', imag(new_plate)); % ====== set arrow arrowH = ud(3, 4); center = ud(3, 7); arrow = get(arrowH, 'userdata'); new_arrow = arrow*exp(sqrt(-1)*theta) + center; set(arrowH, 'xdata', real(new_arrow), 'ydata', imag(new_arrow)); % ====== redraw eval([mfilename, '(0,0,0,0,''clear_trail'')']); elseif strcmp(action, 'set_anim_obj'), % ====== Setting up the axis xMin = -2.0; xMax = -xMin; y_min = -0.3; y_max = -xMin; axis([xMin xMax y_min y_max]); axis equal; % ====== Setting up the ground %colormap(gray); % To assign correct patch color %patch([xMin xMax xMax xMin], ... % [-y_max/8 -y_max/8 0 0], [10 10 55 55]); h = line([xMin xMax], [0 0]); set(h, 'color', 'b'); % ====== Setting up the ball JugBallRadius = 0.1; ball = JugBallRadius*exp(j*linspace(0, 2*pi, 21)); %colormap(cool); %ballH = patch(real(ball), imag(ball), 64*ones(size(ball))); ballH = line(real(ball)+xMin + JugBallRadius, imag(ball)+JugBallRadius); set(ballH, 'color', 'c', 'clipping', 'off', 'erasemode','xor'); set(ballH, 'userdata', ball); % ====== Setting up the plate plate_leng = (xMax-xMin)/10; plate = plate_leng*[-0.5 0.5]' + j*[0 0]'; plateH = line(real(plate), imag(plate)); set(plateH, 'color', 'y', 'erasemode', 'xor', 'linewidth', 5); set(plateH, 'userdata', plate); % ====== Setting up the base %baseH = line(real(plate), imag(plate)); %set(baseH, 'color', 'r', 'erasemode', 'xor', 'linewidth', 5); %set(baseH, 'erase', 'xor', 'userdata', plate); %set(baseH, 'clipping', 'off'); % ====== Setting the reference triangle ref = JugBallRadius*[-1 1 0 -1]' + j*2*JugBallRadius*[0 0 1 0]' - 2*j*JugBallRadius; refH = line(real(ref), imag(ref)); set(refH, 'color', 'r', 'linewidth', 2); set(refH, 'erase', 'xor', 'clipping', 'off'); set(refH, 'userdata', ref); % ====== Setting steering arrow sy_min = 1.50; % min. of y of loc. of steering device sy_max = 2.00; % max. of y of loc. of steering device s_JugBallRadius = (sy_max - sy_min)/sqrt(2); sx_min = 1.5; center = sx_min + j*((sy_max - sy_min)/2 + sy_min); tmp = s_JugBallRadius*exp(sqrt(-1)*linspace(-pi/4, pi/4, 100)); arc = [0 tmp 0 s_JugBallRadius] + center; arrow_baseH = line(real(arc), imag(arc)); dummyLine=line(real(center), real(center), 'color', 'black'); set(arrow_baseH, 'clipping', 'off'); arrow_x = [0 1 nan 0.9 1 0.9]; arrow_y = [0 0 nan 0.1 0 -0.1]; arrow = s_JugBallRadius*(arrow_x + sqrt(-1)*arrow_y); curr_arrow = arrow + center; arrowH = line(real(curr_arrow), imag(curr_arrow)); set(arrowH, 'color', 'red', 'erasemode', 'xor'); set(arrowH, 'clipping', 'off', 'userdata', arrow); set(arrowH, 'userdata', arrow); % ====== set 'userdata' ud = [ballH plateH refH arrowH arrow_baseH -1 center -1 -1 -1]; % ud(6) is for JugFisMat flag, ud(8:10) is for x, y and v set(JugFigH, 'userdata', [get(JugFigH, 'userdata'); ud]); elseif strcmp(action, 'set_mouse_action'), ud = get(JugFigH, 'userdata'); which_controller = get(ud(2, 1), 'value'); if which_controller == 1, % human controller % ====== move refH to center DesiredPos = (xMin+xMax)/2; refH = ud(3, 3); ref = get(refH, 'userdata'); new_ref = ref + DesiredPos; set(refH, 'xdata', real(new_ref), 'ydata', imag(new_ref)); % ====== show steering arrow set(ud(3,4:5), 'visible', 'on'); % ====== action when button is first pushed down action1 = [mfilename '(0,0,0,0,''mouse_action_steering'')']; % ====== actions after the mouse is pushed down action2 = action1; % ====== action when button is released action3 = action1; else % automatic controller % ====== hide steering arrow set(ud(3,4:5), 'visible', 'off'); % ====== action when button is first pushed down action1 = [mfilename '(0,0,0,0,''mouse_action_ref'')']; % ====== actions after the mouse is pushed down action2 = ''; % ====== action when button is released action3 = ''; end % ====== temporary storage for the recall in the down_action set(gca,'UserData',action2); % ====== set action when the mouse is pushed down down_action=[ ... 'set(gcf,''WindowButtonMotionFcn'',get(gca,''UserData''));' ... action1]; set(gcf,'WindowButtonDownFcn',down_action); % ====== set action when the mouse is released up_action=[ ... 'set(gcf,''WindowButtonMotionFcn'','' '');', action3]; set(gcf,'WindowButtonUpFcn',up_action); elseif strcmp(action, 'main_loop'), JugAnimRunning = 1; % ====== get animation objects tmp = get(JugFigH, 'userdata'); % ====== change visibility of GUI's set(tmp(1, 1), 'visible', 'off'); set(tmp(1, 4:5), 'visible', 'off'); set(tmp(1, 2:3), 'visible', 'on'); % ====== looping while 1 & ~JugAnimClose if ~JugAnimRunning | JugAnimPause, break; end eval([mfilename, '(0, 0, 0, 0, ''single_loop'')']); end % ====== shut down if JugAnimClose, delete(JugFigH); end elseif strcmp(action, 'load_fis_mat'), ud = get(JugFigH, 'userdata'); if ud(3, 6) < 0, % FIS not been built JugFisMat = readfis('juggler'); ud(3, 6) = 1; set(JugFigH, 'userdata', ud); end name='juggler'; figNum=findobj(allchild(0), 'name', ['Rule Viewer: ' name]); if isempty(figNum) ruleview(JugFisMat); figNum=findobj(allchild(0), 'name', ['Rule Viewer: ' name]); pstn=get(figNum, 'Position'); set(figNum, 'Position', pstn+[.35 -.3 0 0]); figure(JugFigH); else figure(figNum); end elseif strcmp(action, 'mouse_action_steering') % Action for mouse when steered by human tmp = get(gca, 'currentpoint'); tmp_x = tmp(1, 1); tmp_y = tmp(1, 2); ud = get(gcf, 'userdata'); center = ud(3, 7); theta = angle(tmp_x + sqrt(-1)*tmp_y - center);, theta = min(max(theta, -pi/4), pi/4); plateH = ud(3, 2); arrowH = ud(3, 4); arrow = get(arrowH, 'userdata'); plate = get(plateH, 'userdata'); new_arrow = arrow*exp(sqrt(-1)*theta) + center; set(arrowH, 'xdata', real(new_arrow), 'ydata', imag(new_arrow)); new_plate = plate*exp(j*theta); set(plateH, 'xdata', xNextHit + real(new_plate), ... 'ydata', imag(new_plate)); elseif strcmp(action, 'mouse_action_ref') curr_info = get(gca, 'CurrentPoint'); mouse_pos = curr_info(1,1); bound = [xMin+1.5*JugBallRadius xMax-1.5*JugBallRadius]; DesiredPos = min(max(mouse_pos, bound(1)), bound(2)); ud = get(JugFigH, 'userdata'); refH = ud(3, 3); new_ref = get(refH, 'userdata') + DesiredPos; set(refH, 'xdata', real(new_ref), 'ydata', imag(new_ref)); elseif strcmp(action, 'ideal_controller'), % Ideal controller % ====== find where the ball hits the ground vy = imag(v_prev); t_hit = (vy + (vy*vy+2*g*(y_prev-JugBallRadius))^0.5)/g; x_hit = real(v_prev)*t_hit + x_prev; v_hit = real(v_prev) + j*(imag(v_prev) - g*t_hit); % ====== get animation objects % Note that sin(2*theta) = k has two solution theta1 and theta2, % and theta1 + theta2 = pi/2; tmp = g*(DesiredPos - x_hit)/abs(v_hit)^2; tmp = min(max(tmp, -1), 1); tmp_angle = asin(tmp); % tmp_angle is equal to two times the next_project_angle % tmp_angle must be in [0, 2*pi] in order to make the next % project angle between [0, pi]. % For every tmp_angle, we can find another solution. if tmp_angle >= 0, solution1 = tmp_angle; solution2 = pi - tmp_angle; else solution1 = pi - tmp_angle; solution2 = 2*pi + tmp_angle; end % To make next_proj_angle as close as possible to pi/2 if abs(solution1-pi) < abs(solution2-pi), next_proj_angle = solution1/2; else next_proj_angle = solution2/2; end o1 = (next_proj_angle - ProjAngle)/2; elseif strcmp(action, 'fuzzy_controller'), % fuzzy controller % ====== find where the ball hits the ground vy = imag(v_prev); t_hit = (vy + (vy*vy+2*g*(y_prev-JugBallRadius))^0.5)/g; x_hit = real(v_prev)*t_hit + x_prev; v_hit = real(v_prev) + j*(imag(v_prev) - g*t_hit); % ====== get animation objects ud = get(JugFigH, 'userdata'); o1 = evalfis([x_hit - DesiredPos ProjAngle], JugFisMat); % ====== rule viewer xx=allchild(0); figN=[]; for i=1:length(xx) name=get(xx(i), 'name'); if length(name)>11 & strcmp(name(1:12), 'Rule Viewer:'); figN=xx(i); break; end end if ~isempty(figN) set(figN, 'HandleVis', 'on'); ruleview('#simulink', [x_hit - DesiredPos ProjAngle], figN); set(figN, 'HandleVis', 'callback'); end elseif strcmp(action, 'state_feedback_controller'), % SF controller % ====== find where the ball hits the ground vy = imag(v_prev); t_hit = (vy + (vy*vy+2*g*(y_prev-JugBallRadius))^0.5)/g; x_hit = real(v_prev)*t_hit + x_prev; v_hit = real(v_prev) + j*(imag(v_prev) - g*t_hit); % ====== get animation objects ud = get(JugFigH, 'userdata'); % coef is obtained from showsurf.m coef = [0.12493010239152 -0.50000000017091 0.78539816478460]'; state = [x_hit-DesiredPos ProjAngle 1]; out = state*coef; elseif strcmp(action, 'stop_anim'), ud = get(JugFigH, 'userdata'); set(ud(1, 1), 'visible', 'on'); set(ud(1, 2:5), 'visible', 'off'); JugAnimRunning = 0; JugAnimPause = 0; elseif strcmp(action, 'pause_anim'), ud = get(JugFigH, 'userdata'); set(ud(1, 3), 'visible', 'off'); set(ud(1, 4:5), 'visible', 'on'); JugAnimRunning = 0; JugAnimClose = 0; JugAnimPause = 1; elseif strcmp(action, 'step_anim'), JugAnimStepping = 1; eval([mfilename, '(0, 0, 0, 0, ''single_loop'')']); elseif strcmp(action, 'continue_anim'), ud = get(JugFigH, 'userdata'); set(ud(1, 3), 'visible', 'on'); set(ud(1, 4:5), 'visible', 'off'); JugAnimRunning = 1; JugAnimPause = 0; JugAnimClose = 0; JugAnimStepping = 0; eval([mfilename, '(0,0,0,0,''set_constant'')']); eval([mfilename, '(0,0,0,0,''main_loop'')']); elseif strcmp(action, 'info'), helpwin(mfilename); % title = get(JugFigH, 'Name'); % content = ... % [' ' % ' Animation of the ball juggling system. The small ' % ' triangle indicates the desired ball position. ' % ' You can choose either human or fuzzy control to ' % ' control this system. If it is controlled by human, ' % ' click the steering arrow at the upper right corner ' % ' to change the tilted angle of the hitting board. ' % ' If it is controlled by fuzzy controller, use mouse ' % ' to change the location of the triangle. (If fuzzy ' % ' controller is selected, the position of the small ' % ' triangle will also be updated randomly every ' % ' 200 step counts.) ' % ' ' % ' File: juggler.m ']; % fhelpfun(title, content); elseif strcmp(action, 'close'), if JugAnimRunning == 1, JugAnimClose = 1; % close via main_loop else % close when animation is stopped or paused ud = get(JugFigH, 'userdata'); delete(JugFigH); end % ###### additional UI controls elseif strcmp(action, 'show_trail'), ud = get(JugFigH, 'userdata'); showTrailH = ud(2, 2); objectH = ud(3, 1:4); dispmode = get(showTrailH, 'value'); if dispmode == 0, % xor set(objectH, 'erasemode', 'xor'); % set(JugFigH, 'color', get(JugFigH, 'color')); refresh(JugFigH); else set(objectH, 'erasemode', 'none'); end elseif strcmp(action, 'clear_trail'), refresh(JugFigH); % set(JugFigH, 'color', get(JugFigH, 'color')); else fprintf('Action string = %s\n', action); error('Unknown action string!'); end