nav_plot.m

来自「approximate reinforcement learning」· M 代码 · 共 368 行

M
368
字号
function figh = nav_plot(cfg)% Plot various information regarding the navigation problem%   FIGH = NAV_PLOT(CFG)% Parameters:%   CFG         - history for a simple trajectory plot;%               or full configuration of plot, see commented defaults for explanations%% Returns:%   FIGH        - an (array of) handles to the created figure(s)% default argumentsif nargin < 1, cfg = ''; end;% support for default calling mode -- i.e. only historyif isstruct(cfg) && isfield(cfg, 't') && isfield(cfg, 'x'),    hist = cfg;    cfg = struct();    cfg.trajectory = 1;    cfg.datasource = 'caller';    cfg.hist = hist;end;% where from to load the data, one of:%       'problem'   - if nav_problem() should be used for init; cannot be used%           when plotting elements dependent on a learnt parameter vector (such as policy)%       'caller'    - if the variables should be taken from the calling function%       filename    - if data should be loaded from a file with name <filename>CFG.datasource = 'problem';CFG.datafile   = '';    % data source can be given as a data file here as well% What to plotCFG.schematic = 0;      % plot a schematic of the problemCFG.trajectory = 0;     % if a trajectory should be plotted; extradata should contain the historyCFG.addtraj = 0;        % do not create new figure for trajectory plot, add to fig with handle cfg.addtrajCFG.policy = 0;         % if a constant-speed slice thru the policy should be plottedCFG.Q = 0;              % if a constant-speed slice thru the Q-function should be plottedCFG.dampingmap = 0;     % if a colormap of the damping should be plottedCFG.dampingsurface = 0; % if the damping surface should be plottedCFG.both = 0;           % if both a damping colormap and a damping surface should be plottedCFG.centers = 0;        % if centers should be highlighted on the damping surface/colormap% plot configurationCFG.arrowscale = .2;    % how long should be the command be scaled to obtain arrow length in policy plotCFG.posstep = 1/3;      % the grid step for plotting the policyCFG.markersize = 3;     % the marker size for centers, grid points, trajectory samples etc.CFG.speedslice = [0; 0];% which speed slice through the policy/Q-function should be plotted, default (0,0)CFG.trajstyle = '-';    % the line style for trajectory plotCFG.trajcolor = 'k';    % the color for trajectory plotCFG.showreturn = 1;     % whether to show the return near the trajectory% save configurationCFG.plottarget = 'screen';     % 'latex', 'beamer', 'screen', ''% Save implemented for: policyCFG.savedir = 'D:\Work\tex\papers\alamas07\img\';                        % path for saving figureCFG.savefig = 'nav';    % filename for saving figure% process configif ischar(cfg), cfg = str2cfg(cfg, fieldnames(CFG)); end;cfg = checkparams(cfg, CFG);cfg.grayscale = grayscalefromconfig(cfg);% ensure compatibility with datafile fieldif ~isempty(cfg.datafile), cfg.datasource = cfg.datafile; end;% whether the damping map should be plotted as supportcfg.dampingsupport = (cfg.trajectory && ~cfg.addtraj) || cfg.policy || cfg.schematic;% cfg           % feedback on config% needed varsvars = {'model', 'X', 'U', 'DIMS', 'XMFS', 'theta'};% load model, grids, etc. from the data sourceswitch cfg.datasource,    case 'caller',              % load needed vars from caller space        for i=1:length(vars),            cv.(vars{i}) = evalin('caller', vars{i});        end;        structtovars(cv);    case 'problem',             % use problem fun to init (limited) vars        model = nav_problem('model');        grids = nav_problem('fuzzy');        X = grids.xgrids;        U = grids.ugrids;    otherwise                   % load from file        load(cfg.datasource, vars{:});end;% Compute the damping on a fine grid -- needed for all the optionsxp = -model.phys.maxx(1):.1:model.phys.maxx(1);yp = -model.phys.maxx(2):.1:model.phys.maxx(2);B = zeros(length(xp), length(yp));for i = 1:length(xp),    for j = 1:length(yp),        B(i, j) = feval(model.phys.damping.fun, model.phys.damping, [xp(i); yp(j)]);    end;end;% grayscale stylesgs.schemec = 'k';gs.innerc = .25 * [1 1 1];gs.centerc = 0 * [1 1 1];gs.cm = gray(96);% reverse, and only use from white to a dark gray, not to blackgs.cm = gs.cm(end:-1:end-64, :);% color stylescs.schemec = 'k';cs.innerc = 'b';cs.centerc = 'r';cs.cm = jet(64);% set styleif cfg.grayscale, sty = gs; else sty = cs; end;% readable labelscommonprop = {'Interpreter','LaTeX','FontSize',13};rl.x = {'$c_x$',commonprop{:}}; rl.y = {'$c_y$',commonprop{:}}; rl.ux = {'$u_x$',commonprop{:}}; rl.uy = {'$u_y$',commonprop{:}}; rl.b = {'$b(c_y,c_y)$',commonprop{:}}; rl.q = {'Q*(X,Y)'};% PSFRAG labels (when plotting for latex)psl.x = {'CX'}; psl.y = {'CY'}; psl.b = {'DAMP'}; psl.q = {'QSTAR'};psl.ux = {'UX'}; psl.uy = {'UY'};% set labelsswitch cfg.plottarget,    case 'latex',           labels = psl;    case {'beamer', 'screen', ''},          labels = rl; end;% fig size -- only takes effect for 2D figures switch cfg.plottarget    case 'latex',           cfg.figsize = [400 400];    case 'beamer',          cfg.figsize = [400 400];    otherwise       % default        cfg.figsize = [];end; % Process plot pathsfigh = [];% ------ Surface plotif cfg.dampingsurface || cfg.both,    figh(end+1) = figure; colormap(sty.cm);    meshc(xp, yp, B'); hold on;    xlabel(labels.x{:}); ylabel(labels.y{:});     zlabel(labels.b{:});    if cfg.centers,        [xx,yy] = ndgrid(X{1}, X{2});        Bc = zeros(length(X{1}), length(X{2}));        for i1 = 1:length(X{1}),            for i2 = 1:length(X{2}),                Bc(i1, i2) = feval(model.phys.damping.fun, model.phys.damping, [X{1}(i1); X{2}(i2)]);            end;        end;        if cfg.centers,            surface(X{1}, X{2}, Bc', 'EdgeColor', 'none', 'FaceColor', 'none', ...                'Marker' ,'o', 'MarkerFaceColor', sty.centerc, 'MarkerSize', cfg.markersize);         end;    end;end;% ------ Damping mapif cfg.dampingmap || cfg.both || cfg.dampingsupport,    figh(end+1) = figure;     if ~isempty(cfg.figsize),        set(gcf, 'Position', [0 0 cfg.figsize]);        movegui(gcf, 'center');    end;    if cfg.dampingsupport,        % damping map is support: always grayscale, otherwise foreground unreadable        colormap(gs.cm);    else        % damping map is colored as selected         colormap(sty.cm);    end;    if std(B(:)),        policy = pcolor(xp, yp, B'); hold on;        set(policy, 'LineStyle', 'none');    else % plot in white        policy = pcolor(xp, yp, B'); hold on;        set(policy, 'LineStyle', 'none', 'FaceColor', 'w');        hold on;    end;    xlabel(labels.x{:}); ylabel(labels.y{:});     % put a title unless colormap is just background for other plot    if cfg.dampingmap || cfg.both, title(labels.b{:}); end;    if cfg.centers && ~cfg.schematic,        [xx,yy] = ndgrid(X{1}, X{2});        plot(xx(:), yy(:), 'LineStyle', 'none', 'Color', sty.centerc, ...            'Marker', 'o', 'MarkerSize', cfg.markersize, 'MarkerFaceColor', sty.centerc);     end;    axis equal image    set(gcf, 'Units', 'normalized');end;% ------- Schematicif cfg.schematic,    % Displacement for nice placing of texts    XDISP = .05; YDISP = .3; FLEN = 1;        % goal region    tolx = model.goal.zeroband(1);    toly = model.goal.zeroband(2);    fill([tolx tolx -tolx -tolx], [-toly toly toly -toly], sty.innerc);    text(tolx+XDISP, -toly-YDISP, 'Goal region', 'Color', sty.innerc);        % point mass and its     w = model.phys.maxx(1); h = model.phys.maxx(2);    cx = w * .4;    cy = h * .6;    % point coords    plot([cx cx], [0 cy], sty.schemec, 'LineStyle', '--');    plot([0 cx], [cy cy], sty.schemec, 'LineStyle', '--');    text(cx/2, cy+YDISP, labels.x{:});    text(cx+XDISP, cy/2, labels.y{:});    text(cx+XDISP, cy - 2*YDISP, 'Point mass', 'Color', sty.centerc);        % forces    [fx fy] = axescoord2figurecoord([cx cx+FLEN], [cy cy]);    annotation('arrow', fx, fy, 'Color', sty.schemec);    [fx fy] = axescoord2figurecoord([cx cx], [cy cy+FLEN]);    annotation('arrow', fx, fy, 'Color', sty.schemec);    text(cx + FLEN, cy, labels.ux{:});    text(cx, cy + FLEN, labels.uy{:});        % point    plot(cx, cy, 'Color', sty.centerc, 'Marker', 'o', 'MarkerSize', cfg.markersize + 2, 'MarkerFaceColor', sty.centerc);     % 0-axes    plot([-w w], [0 0], sty.schemec, 'LineStyle', ':');    plot([0 0], [-h h], sty.schemec, 'LineStyle', ':');end;% ------ Trajectoryif cfg.trajectory,          % extradata holds the policy    if cfg.addtraj,         % select existing figure        figh(end+1) = figure(cfg.addtraj); hold on;    end;    plot(cfg.hist.x(1, :), cfg.hist.x(2, :), 'Color', cfg.trajcolor, 'LineStyle', cfg.trajstyle, ...        'LineWidth', 1, 'Marker', 'o', 'MarkerSize', cfg.markersize, 'MarkerFaceColor', cfg.trajcolor);    if cfg.showreturn,      % put the return label somewhere near the start of the trajectory        % compute an average position of the first part of the trajectory        p = mean(cfg.hist.x(1:2, 1:10), 2);        % move the text away a little bit, remaining within bounds        lx = model.phys.maxx(1)/8;        if p(1)+5*lx < model.phys.maxx(1), p(1) = p(1)+lx;        else p(1) = p(1)-4*lx;        end;        ly = model.phys.maxx(2)/16; % height of text smaller than width        if p(2)+2*ly < model.phys.maxx(2), p(2) = p(2)+ly;        else p(2) = p(2)-ly;        end;        text(p(1), p(2), ['R=' num2str(fix(cfg.hist.R(1)))], 'Color', cfg.trajcolor);    end;      end;speedslice = cfg.speedslice;% ------ Fuzzy policyif cfg.policy,        [Qstar ui] = max(theta, [], 2); clear Qstar;    ui = lin2ndi(ui, DIMS.dimu);    % compute optimal policy    hstar = zeros(DIMS.N, DIMS.q);    for q = 1:DIMS.q,        hstar(:, q) = U{q}(ui(:, q));    end;        % plot intermediate values on a uniform grid        x = X{1}(1):cfg.posstep:X{1}(end);    y = X{2}(1):cfg.posstep:X{2}(end);    [xx, yy] = ndgrid(x, y);    plot(xx(:), yy(:), 'LineStyle', 'none', 'Color', sty.innerc, ...            'Marker', 'o', 'MarkerSize', cfg.markersize-1, 'MarkerFaceColor', sty.innerc);    for i1 = 1:length(x),        for i2 = 1:length(y),            if any(x(i1) == X{1}) && any(y(i2) == X{2}), continue; end;            mu = mdegs(x(i1), XMFS{1});            mu = mu(:) * mdegs(y(i2), XMFS{2})';            for p = 3:DIMS.p, mu = mu(:) * mdegs(speedslice(p-2), XMFS{p})'; end; % zero speed            phi = find(mu); mu = mu(phi);            % compute optimal action            u = (mu' * hstar(phi, :))';            p0 = [x(i1)  y(i2)];            pend = p0 + u' * cfg.arrowscale;%             [fx fy] = axescoord2figurecoord([p0(1) pend(1)], [p0(2) pend(2)]);%             annotation('arrow', fx, fy, 'Color', sty.innerc, 'HeadStyle', 'plain');            line([p0(1) pend(1)], [p0(2) pend(2)], 'Color', sty.innerc);        end;    end;        % plot the optimal actions in the position grid points    % just pick up the indicated speed slice    % plot again the grid points, some will have been overwritten by the grid above    [xx,yy] = ndgrid(X{1}, X{2});    plot(xx(:), yy(:), 'LineStyle', 'none', 'Color', sty.centerc, ...        'Marker', 'o', 'MarkerSize', cfg.markersize, 'MarkerFaceColor', sty.centerc);     sliceix = [find(X{3} == speedslice(1)) find(X{4} == speedslice(2))];    for i1 = 1:DIMS.dimx(1),        for i2 = 1:DIMS.dimx(2),            i = ndi2lin([i1 i2 sliceix], DIMS.dimx);            p0 = [X{1}(i1)  X{2}(i2)];            pend = p0 + hstar(i, :) * cfg.arrowscale;            line([p0(1) pend(1)], [p0(2) pend(2)], 'Color', sty.centerc, 'LineWidth', 2);        end;    end;    % title    switch cfg.plottarget,        case {'latex', 'beamer'},        case {'screen', ''},              title(['$h^*(C_X, C_Y)$ for $[\dot{C}_X, \dot{C}_Y] = [' ...                num2str(speedslice(1)) ',' num2str(speedslice(2)) ']$'], 'Interpreter', 'LaTeX');    end;end;% ------ Fuzzy value functionif cfg.Q,    figh(end+1) = figure; clf;        % plot in red points the optimal values in the position grid points    % just pick up the indicated speed slice    sliceix = [find(X{3} == speedslice(1)) find(X{4} == speedslice(2))];    theta = reshape(max(theta, [], 2), DIMS.dimx);    % retrieve speed slice    theta = squeeze(theta(:, :, sliceix(1), sliceix(2)));    mesh(X{1}, X{2}, theta');    surface(X{1}, X{2}, theta', 'EdgeColor', 'none', 'FaceColor', 'none', ...        'Marker' ,'o', 'MarkerFaceColor', 'r', 'MarkerSize', cfg.markersize);    xlabel(labels.x{:}); ylabel(labels.y{:}); zlabel(labels.q{:});        % title    switch cfg.plottarget,        case {'latex', 'beamer'},        case {'screen', ''},              title(['$Q^*(C_X, C_Y)$ for $[\dot{C}_X, \dot{C}_Y] = [' ...                num2str(speedslice(1)) ',' num2str(speedslice(2)) ']$'], 'Interpreter', 'LaTeX');    end;end;% save last figure if indicatedsaveplot(figh(end), [cfg.savedir cfg.savefig], cfg.plottarget);% END nav_plot RETURNING array of figure handles =================================================% Old code:% Plotting intermediate Q-values on a fine grid -- unnecessary since they vary linearly%     x = X{1}(1):cfg.posstep:X{1}(end);%     y = X{2}(1):cfg.posstep:X{2}(end);%     Qstar = zeros(length(x), length(y));%     for i1 = 1:length(x),%         for i2 = 1:length(y),%             mu = mdegs(x(i1), XMFS{1});%             mu = mu(:) * mdegs(y(i2), XMFS{2})';%             % the rest are given by the speed slice%             for p = 3:DIMS.p, mu = mu(:) * mdegs(speedslice(p-2), XMFS{p})'; end;%             phi = find(mu); %             % compute optimal value%             Qstar(i1, i2) = max(mu(phi)' * theta(phi, :));%         end;%     end;%     mesh(x, y, Qstar'); hold on;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?