⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slam_if_2d.m

📁 这是移动机器人同时定位与地图创建的第三部分
💻 M
📖 第 1 页 / 共 2 页
字号:
%% SLAM_IF_2D performs an interactive simulation of SLAM with information filter.%   SLAM_IF_2D() is a two-dimensional linear simulation of Simultaneous %   Localization and Mapping (SLAM) with the information filter. It is meant%   to serve as an introduction to the basic steps of IF SLAM and to explore%   some important traits of feature-based SLAM information filters.%%   This code was written by Matthew R. Walter (Massachusetts Institute of%   Technology) as part of a 2006 SLAM Summer School lab on the information%   filter. Feel free to play with the parameter settings to see how they%   affect the information filter.%%   For the most part, I have tried to be pretty verbose when it comes%   to my comments and hope that they help you to understand what is going on.%   Also, while there were not any obvious bugs upon my final writing, I can%   not guarantee that the code is free of errors.%% ------------% References:%%   R. Eustice, H. Singh, and J. Leonard. Exactly Sparse Delayed State%   Filters. ICRA 2005.%%   M. Walter, R. Eustice, and J. Leonard. A Provably Consistent Method%   for Imposing Exact Sparsity in Feature-based SLAM Information Filters.%   ISRR 2005.%%-----------------------------------------------------------------%    History:%    Date            Who         What%    -----------     -------     -----------------------------%    08-10-2006      mrw         Created and written.function slam_if_2d()% Clear variablesclear global;clear all;global TheJournal;global Truth;global Graphics;global Params;global Data;Params.verbose = input('Enter 1 for verbose output, else 0: ');%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Simulation ParametersParams.PlotPeriod = 20;Params.Verbose = 0;Params.PlotSwitch = 1;% System ParametersParams.Q = [0.15 0.1; 0.1 0.15].^2;Params.R = [0.2 0.1; 0.1 0.2].^2;Params.MaxObsRange = 10;Params.nObsPerIteration = 8;Params.density = 0.05;      % density of features% The information form utilizes the inverse of Q and R in sparse formParams.Q = sparse(Params.Q);Params.R = sparse(Params.R);Params.Qinv = inv(Params.Q);Params.Rinv = inv(Params.R);Params.MapSize = 20;        % width and height of the mapParams.nRepeat = 3;         % number of times that the vehicle goes around the loopParams.maxVelocity = 0.5;   Params.numFeatures = floor(Params.density*Params.MapSize^2);Params.FeatureSpacing = ((Params.MapSize^2)/Params.numFeatures)/5;Params.ObsFrequency = 1;        % [0,1] likelihood of observations%% Filter initializationSigma = diag([0.001 0.001]);     % initial 2x2 covariance matrixx = [0; 0];                      % initial state% Initial information matrix, Lambda = inv(Sigma), and information vector, eta = Lambda*x% We store the information matrix in sparse form and allocate all the memory beforehand.% As a result, size(Lambda,1) is proportional to the total number of features in the environment% and not the size of the current state, which is 2. This speeds things up by allowing us to avoid% some overhead in Matlab but requires that we carry around a list of indices of where stuff is in this% large matrix. Right now we only have 2 states, so our index is [1; 2]TheJournal.II = [1:2]';TheJournal.Lambda = spalloc(2*(1+Params.numFeatures),2*(1+Params.numFeatures),(2*(1+Params.numFeatures))^2);Temp = sparse(inv(Sigma));Temp = (Temp + Temp')/2;TheJournal.Lambda(1:2,1) = Temp(:,1);TheJournal.Lambda(1:2,2) = Temp(:,2);TheJournal.eta = TheJournal.Lambda(TheJournal.II,TheJournal.II)*x;% A lookup table to keep track of feature id's and their corresponding location within the state vectorTheJournal.LookUP = [NaN 1; 1 1];%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%if(Params.PlotSwitch)    Graphics.MainFigure = figure(1);    clf;    subplot(1,2,1)    hold on;    axis square;    set(gcf,'DoubleBuffer','on','Color',[1 1 1]);    set(gca,'Box','on');        subplot(1,2,1)    cla;    set(gcf,'ColorMap',colormap(flipud(colormap('gray'))));        if(Params.verbose)        Graphics.SecondFigure = figure(2);        clf;        Temp = get(gcf,'Position');        Temp(3:4) = [300 300];        set(gcf,'ColorMap',colormap(flipud(colormap('gray'))),'Position',Temp);    end;            figure(Graphics.MainFigure);            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    % Graphic settings    Graphics.TrueColor = 'g';    Graphics.Color = 'r';    Graphics.curLaser = [];    Graphics.TrueVehiclePose = [];  % handle for plot of true vehicle pose    Graphics.VehiclePose = [];      % handle for plot of filter estimate for vehicle pose    Graphics.VehicleEllipse = [];   %   "     "    "  "     "   pose estimate uncertainty ellipse    Graphics.Features = [];         % handle for plot of filter estimates for feature locations    Graphics.FeatureEllipse = [];   % handle for plot of feature uncertainty ellipse    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%end;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Generate the predicted and true motion (i.e. noise-corrupted) of the vehicleMakeSurvey();% Place the features in the worldMakeFeatures();%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Various logs for post-analysisTheJournal.Feature = [];TheJournal.ProjectionTime = [];TheJournal.UpdateTime = [];% The vehicle history log keeps track of the estimated vehicle pose error together with% the diagonal of the Sigma_vehicle sub-block and the chi-square error.% Each column corresponds to a different timeverror = x - Truth.VehicleTrajectory(2:3,1);TheJournal.VehicleHistory = [1; verror; diag(Sigma); verror'*inv(Sigma)*verror];%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   NOW WE LOOP OVER THE SIMULATION AND IMPLEMENT THE FILTERtstep = floor(0.1*Truth.VehicleTrajectory(1,end));  % time step simply for printing progress updatefor k=2:size(Truth.VehicleTrajectory,2)    if(~mod(k,tstep))        fprintf(1,'Simulation is at k = %i, %.2f%% done \n',k,100*k/Truth.VehicleTrajectory(1,end));    end;    if(Params.PlotSwitch & ~isempty(Graphics.curLaser))        set(Graphics.curLaser,'Visible','off');    end;    % Perform the motion update in the information form as the addition of the new pose    % to the state followed by the marginalization of the past pose    Information_DoProjection(k);    % update the plot of the vehicle and map;    if(Params.PlotSwitch)        PlotState(k);        title(['k = ' int2str(k) ' ( ' num2str(100*k/size(Truth.VehicleTrajectory,2),2) ' percent )']);        drawnow;    end;            % Simulate feature observations    Observations = [];    if(rand <= Params.ObsFrequency)        Observations = GetFeatureObservations(k);    end;    if(~isempty(Observations))        % data association is given by the first row        DA = Observations(1,:);        % Differentiate between features that have already been mapped and those that are new        if(size(TheJournal.LookUP,1) > 2)            [C,IA,IB] = intersect(DA,TheJournal.LookUP(3:end,1));            OldObs = Observations(:,IA);                        [C,IA] = setdiff(Observations(1,:),OldObs(1,:));            NewObs = Observations(:,IA);        else            OldObs = [];            NewObs = Observations;        end;                % Visualize observations        if(Params.PlotSwitch)            xv = GetMean(1:2);  % Estimate of the current vehicle pose            [C,IA,IB] = intersect(Truth.Features(1,:),Observations(1,:));            X = [repmat(xv(1),1,size(Observations,2)); Truth.Features(2,IA)];            Y = [repmat(xv(2),1,size(Observations,2)); Truth.Features(3,IA)];                        figure(Graphics.MainFigure);            subplot(1,2,1);            Graphics.curLaser = plot(X,Y,'y');            set(Graphics.curLaser,'Color',[0.268 0.686 1.00]);        end;                            % If the vehicle has observed new features, add them        if(~isempty(NewObs))            Information_AddFeature(NewObs);        end;                % If we have reobserved known features, run an update step        if(~isempty(OldObs))            Information_DoUpdate(OldObs);        end;    end;    % update the plot of the vehicle and map;    if(Params.PlotSwitch)        PlotState(k);        title(['k = ' int2str(k) ' ( ' num2str(100*k/size(Truth.VehicleTrajectory,2),2) ' percent )']);        drawnow;        ShowLinkStrength();    end;       if(~mod(k,5))        DoLogging(k)    end;    if(~issparse(TheJournal.Lambda))        fprintf(1,'k = %i : Lambda is no longer sparse \n',k);    end;end;% Plot the history for the shared information between the first 5 features and the robot.figure(3);clf;hold on;cmap = [colormap('hot'); colormap('jet'); colormap('gray')];Temp = randperm(size(cmap,1));Handles = [];IDs = [];for i=1:min(size(TheJournal.Feature,2),5)    IDs = [IDs; TheJournal.Feature{i}.id];    thandle = plot(TheJournal.Feature{i}.Link(1,:),(abs(TheJournal.Feature{i}.Link(2,:))),'k-');    set(thandle,'Color',cmap(Temp(i),:));    Handles(end+1) = thandle;end;    legend(Handles,int2str(IDs));xlabel('Time','FontSize',14);ylabel('Link Strength','FontSize',14);title('Shared Feature-Vehicle Information vs Time','FontSize',14);axis tight;set(gca,'box','on','yscale','log','ylim',[0 Truth.VehicleTrajectory(1,end)],'FontSize',14);return;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% This function executes the motion update for the information filter by forming it as the addition% of the new pose to the state vector followed by the marginalization of the previous posefunction Information_DoProjection(k);global Params;global TheJournal;global Data;global Graphics;% Motion model:%   x_new = x_old + velocity_x * delta_time%   y_new = y_old + velocity_y * delta_time% JacobianF = speye(2);% Velocity vectoru = Data.Velocity(2:3,find(Data.Velocity(1,:)==k));LambdaOld = TheJournal.Lambda(TheJournal.II,TheJournal.II);%%%%%%%%%%%%%%%% The time projection operation for the information matrix and information vector% as described in Eustice et al. (eustice05a) Section III.C.tic;Psi = inv(Params.Q + F*inv(TheJournal.Lambda(1:2,1:2))*F');Omegainv = inv(TheJournal.Lambda(1:2,1:2) + F*Params.Qinv*F');eta1 = Params.Qinv*F*Omegainv*TheJournal.eta(1:2) + Psi*u;if(length(TheJournal.eta) > 2)    eta2 = TheJournal.eta(3:end) - TheJournal.Lambda(3:TheJournal.II(end),1:2)*Omegainv*(TheJournal.eta(1:2)-F'*Params.Qinv*u);    Lambda12 = Params.Qinv*F*Omegainv*TheJournal.Lambda(1:2,3:TheJournal.II(end));    Lambda22 = TheJournal.Lambda(3:TheJournal.II(end),3:TheJournal.II(end)) - TheJournal.Lambda(3:TheJournal.II(end),1:2)*Omegainv*TheJournal.Lambda(1:2,3:TheJournal.II(end));    TheJournal.eta = [eta1; eta2];    TheJournal.Lambda(TheJournal.II,TheJournal.II) = [Psi Lambda12; Lambda12' Lambda22];else    TheJournal.eta = eta1;    TheJournal.Lambda(TheJournal.II,TheJournal.II) = Psi;endcomptime = toc;TheJournal.ProjectionTime = [TheJournal.ProjectionTime [k; length(TheJournal.II); comptime]];%%%%%%%%%%%%%%%% Update the timestamp in the LookUP tableTheJournal.LookUP(1,2) = k;if(Params.verbose)    fprintf(1,'\n\n');    fprintf(1,'----------------------- \n\n');    fprintf(1,'TIME PROJECTION STEP: \n\n')    fprintf(1,'    The IF has just performed the time prediction step. \n');    fprintf(1,'    Compare the new information matrix in Figure 1 to the\n');    fprintf(1,'    structure beforehand as shown in Figure 2.\n');    ShowLinkStrength(TheJournal.Lambda(TheJournal.II,TheJournal.II),0);    ShowLinkStrength(LambdaOld,0,Graphics.SecondFigure);    pause;    fprintf(1,'----------------------- \n\n');end;return;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Function to perform update step for information filterfunction Information_DoUpdate(Observations)global TheJournal;global Params;global Graphics;k = TheJournal.LookUP(1,end);xi = GetStateIndex(1,k);% Measurement model:%   z_x = x_f - x_v%   z_y = y_f - y_v% Note: with a linear observation model, we don't need the meanLambdaOld = TheJournal.Lambda(TheJournal.II,TheJournal.II);% Loop over the measurement data, performing an individual update for each observationH_I = []; H_J = []; H_S = [];Rinv_I = []; Rinv_J = []; Rinv_S = [];Z = [];II = [1:2]';for i=1:size(Observations,2)    id = Observations(1,i);    xfi = GetStateIndex(id,k);            %%%%%%%%%%%%%%%    % The update step for the information filter as described    % in Eustice et al. (eustice05a) Section III.B.            temp = 2*i - 1;    H_I = [H_I; [temp; temp; temp+1; temp+1]];    H_J = [H_J; [1; temp+2; 2; (temp+2)+1]];    H_S = [H_S; [-1; 1; -1; 1]];        II = [II; [xfi; xfi+1]];        Rinv_I = [Rinv_I; [temp; temp; temp+1; temp+1]];    Rinv_J = [Rinv_J; [temp; temp+1; temp; temp+1]];    Rinv_S = [Rinv_S; Params.Rinv(:)];        Z = [Z; Observations(2:3,i)];        %%%%%%%%%%%%%%%end;H = sparse(H_I,H_J,H_S,max(H_I),max(H_J));RINV = sparse(Rinv_I,Rinv_J,Rinv_S);tic;TheJournal.Lambda(II,II) = TheJournal.Lambda(II,II) + H'*RINV*H;TheJournal.eta(II) = TheJournal.eta(II) + H'*RINV*Z;comptime = toc;TheJournal.UpdateTime = [TheJournal.UpdateTime [k; length(TheJournal.II); comptime]];if(Params.verbose)    fprintf(1,'\n\n');    fprintf(1,'----------------------- \n\n');    fprintf(1,'MEASUREMENT UPDATE STEP: \n\n')    fprintf(1,'    The IF has just performed the update step based upon observations \n');    fprintf(1,'    of features: ');    disp(Observations(1,:)); fprintf(1,'\n');    fprintf(1,'    Compare the new information matrix in Figure 1 to the\n');    fprintf(1,'    structure beforehand as shown in Figure 2.\n');    ShowLinkStrength(TheJournal.Lambda(TheJournal.II,TheJournal.II),0);    ShowLinkStrength(LambdaOld,0,Graphics.SecondFigure);    pause;    fprintf(1,'----------------------- \n\n');end;return;                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Function to add featuresfunction Information_AddFeature(Observations)global TheJournal;global Params;global Graphics;% Measurement model:%   z_x = x_f - x_v%   z_y = y_f - y_v% JacobianG = speye(2);xi = GetStateIndex(1,TheJournal.LookUP(1,end));

⌨️ 快捷键说明

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