www.gusucode.com > MATLAB编程毕业设计 EKF SLAM仿真全部源代码 > SLAM_sim.m

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%主函数
function SLAM_sim(handles)

%载入重要变量数据
configFile;

%控制仿真结束的变量
global closeClickCount;

%%
% axes(handles.axes1);
% axis equal;
% hold on;
% %绘制墙体、挡板
% for i = 1:length(wall(:,1))/2
%     line([wall(i*2-1,1) wall(i*2,1)],[wall(i*2-1,2) wall(i*2,2)],'LineWidth',4,'Color','k');
% end
% 
% %绘制真实车辆的句柄
% H_robot = line([0 0],[0 0],'EraseMode','xor','Color','m','LineWidth',6);
% %绘制车辆真实轨迹的句柄
% H_path_true = line([0 0],[0 0],'EraseMode','none','linestyle','.','Color',[rand(1) rand(1) rand(1)],'LineWidth',0.1);
% %绘制车辆预计轨迹的句柄
% H_path_predict = line([0 0],[0 0],'EraseMode','none','linestyle','.','Color',[rand(1) rand(1) rand(1)],'LineWidth',0.1);

axes(handles.axes5);
hold on;
%绘制与真实值距离
% distFrPreToTrue = [1:600];
distFrPreToTrue = [];
H_PreTrue_Dis = line([0 1],[0 1],'EraseMode','none','Color','k','linestyle','.');
% line([0 0],[1 1],'EraseMode','xor','Color','k','linestyle','.');
% plot([0 1],[0 1]);


%%
axes(handles.axes2);
axis([-30 350 0 350]);
axis equal;
hold on;
grid on;
%绘制激光数据点的句柄
H_raser_point = line([0 0],[0 0],'EraseMode','xor','linestyle','.','Color','k');
%绘制兴趣点的句柄
H_interest_point = line([0 0],[0 0],'EraseMode','xor','linestyle','s','Color','b','LineWidth',3);
%扫描范围的半圆
raserCirX = 350*cos(0:pi/15:pi);
raserCirY = 350*sin(0:pi/15:pi);
line(raserCirX,raserCirY,'linestyle','--');
line(raserCirX*265/350,raserCirY*265/350,'linestyle','--');
line([-350 350],[30 30],'linestyle','--');

%%
axes(handles.axes3);
axis equal;
axis([-50 1050 -150 650]);
hold on;
H_true_robot = line([0 0],[0 0],'EraseMode','xor','Color','r','LineWidth',6);
H_predict_robot = line([0 0],[0 0],'EraseMode','xor','Color','b','LineWidth',6);
H_probably_robot = line([0 0],[0 0],'EraseMode','xor','Color','k');
H_probably_interest_point = [];
%绘制墙体、挡板
for i = 1:length(wall(:,1))/2
    line([wall(i*2-1,1) wall(i*2,1)],[wall(i*2-1,2) wall(i*2,2)],'LineWidth',4,'Color','k');
end
%绘制全局地图兴趣点的句柄
H_map_interest_point = line([0 0],[0 0],'EraseMode','xor','linestyle','s','Color','m','LineWidth',5);
%绘制激光扫描线的句柄
H_laser_line = line([0 0],[0 0],'EraseMode','xor','Color','y','LineWidth',2);

%%
axes(handles.axes6);
axis([-50 1050 -150 650]);
H_wall_predict = line([0 0],[0 0],'EraseMode','none','color','b');
H_wall_true = line([0 0],[0 0],'EraseMode','none','color','r');
hold on;

%%
%打开文件
fid = fopen('fileData.txt','r');

%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% junmpNum = 400;
% for i=1:junmpNum
%     [robx,roby,robphi,G,pointNum,px,py,splitNum,splitIndex] = getDataFrFile(fid);
% end
% x = [robx,roby,robphi];


for i=1:1:1200
    
    %设置循环位置的显示
    set(handles.loopNum,'String',num2str(i));
    
    %暂停仿真
    while(closeClickCount)
        pause(0.2);
        if(closeClickCount == -1)
            return;
        end
    end
    
    %%
    %从文件中获取参数
    [robx,roby,robphi,G] = getDataFrFile1(fid);

    %计算真实位置
    xtrue = vehicle_model([robx;roby;robphi],V,G,WB,dt);
    
    %给控制量V和G融入噪声
    [Vn,Gn] = add_control_noise(V,G,Q);
    
    %EKF预测步骤
    [x,P] = predict(x,P,Vn,Gn,Q,WB,dt);
    % x = vehicle_model(x,Vn,Gn,WB,dt);
    
    %%
    if(mod(i,2)==0)
        %从文件中获取参数
        [pointNum,px,py,splitNum,splitIndex] = getDataFrFile2(fid);

        %从激光测距仪的输出中提取直线
        [lineNum,linePara] = getLine(px,py,pointNum,splitIndex,splitNum);
        closePoint = getClosePoint(lineNum,linePara,px,py);
        %在小坐标中提取兴趣点
        interestPoint = extractInterestPoint(closePoint,lineNum,linePara,px,py);
        %在大坐标中提取兴趣点
        mapInterestPoint = changeCoordinate(interestPoint,xtrue(1),xtrue(2),xtrue(3));
        
        %大坐标下,周围环境实际情况的反映和预计的反映
        cpNum = size(closePoint,1);
        mapClosePoint = zeros(cpNum*2,2);
        for tt = 1:cpNum
            mapClosePoint(tt*2-1,:) = closePoint(tt,1:2);
            mapClosePoint(tt*2,:) = closePoint(tt,3:4);
        end
        map_wall_true = changeCoordinate(mapClosePoint,xtrue(1),xtrue(2),xtrue(3));
        map_wall_predict = changeCoordinate(mapClosePoint,x(1),x(2),x(3));
        [map_wall_true_x,map_wall_true_y] = getWallXY(map_wall_true);
        [map_wall_predict_x,map_wall_predict_y] = getWallXY(map_wall_predict);
        
        %获取观测值
        z = interestPoint2z(interestPoint);

        %数据匹配
        [zf,idf,zn]= data_associate(x,P,z,R,GATE_REJECT,GATE_AUGMENT);

        %利用匹配成功的lm,zf更新机器人状态x和状态协方差P
        [x,P]= batch_update(x,P,zf,R,idf);

        %利用新发现的lm,zn更新更新机器人状态x和状态协方差P
        [x,P]= augment(x,P,zn,R);
    end  
    
   

    %%
    
    
    if(mod(i,2)==0)
        axes(handles.axes3);
        %【绘制】机器人真实位置
%         set(H_robot,'xdata',[xtrue(1)+25*cos(xtrue(3)) xtrue(1)-25*cos(xtrue(3))],'ydata',[xtrue(2)+25*sin(xtrue(3)) xtrue(2)-25*sin(xtrue(3))]);

        
        %【绘制】激光测距仪的散点
        set(H_raser_point,'xdata',px,'ydata',py);
        
%         %【绘制】大坐标兴趣点
%         if(~isempty(interestPoint))
%             set(H_interest_point,'xdata',interestPoint(:,1),'ydata',interestPoint(:,2));
%         else
%             set(H_interest_point,'xdata',[0],'ydata',[0]);
%         end
        %【绘制】小坐标兴趣点
        if(~isempty(mapInterestPoint))
            set(H_map_interest_point,'xdata',mapInterestPoint(:,1),'ydata',mapInterestPoint(:,2));
        else
            set(H_map_interest_point,'xdata',[0],'ydata',[0]);
        end

        %在第三幅图上作画
        %预计的轨迹
        line(x(1),x(2),'linestyle','.','MarkerSize',10);
        set(H_predict_robot,'xdata',[x(1)+25*cos(x(3)) x(1)-25*cos(x(3))],'ydata',[x(2)+25*sin(x(3)) x(2)-25*sin(x(3))]);
        %真实的轨迹
        line(xtrue(1),xtrue(2),'linestyle','.','color','r','MarkerSize',15);
        set(H_true_robot,'xdata',[xtrue(1)+25*cos(xtrue(3)) xtrue(1)-25*cos(xtrue(3))],'ydata',[xtrue(2)+25*sin(xtrue(3)) xtrue(2)-25*sin(xtrue(3))]);
        %机器人位置的不确定性
        ptmp= make_covariance_ellipses(x(1:3),P(1:3,1:3));
        set(H_probably_robot,'xdata',ptmp(1,1:11),'ydata',ptmp(2,1:11));
        
        %画出landmark的不确定性
        landmarkNum = (length(x)-3)/2;
        delete(H_probably_interest_point);
        H_probably_interest_point = [];
        for nm = 1:landmarkNum
            ptmp= make_covariance_ellipses([x(2*nm+2:2*nm+3)],P(2*nm+2:2*nm+3,2*nm+2:2*nm+3));
            tempHandle = line(ptmp(1,1:11),ptmp(2,1:11));
            H_probably_interest_point = [H_probably_interest_point tempHandle];
        end
        %绘制激光扫描线
        
        plines = make_laser_lines(z,x(1:3));
        if(~isempty(plines))
            set(H_laser_line,'xdata',plines(1,:),'ydata',plines(2,:));
        end
        
%         %绘制距离差距
%         axes(handles.axes5);
%         distFrPreToTrue =  sqrt((x(1)-xtrue(1))^2+(x(2)-xtrue(2))^2);
%         line([fix(i/2) fix(i/2)],[0 distFrPreToTrue]);
        
        %绘制真实的墙和预估的墙
%         set(H_wall_true,'xdata',map_wall_true_x,'ydata',map_wall_true_y);
%         set(H_wall_predict,'xdata',map_wall_predict_x,'ydata',map_wall_predict_y);
        axes(handles.axes6);
        if(i<570)
            line(map_wall_true_x,map_wall_true_y,'color','r');
            line(map_wall_predict_x,map_wall_predict_y,'color','b','LineStyle',':');
        else
            line(map_wall_predict_x,map_wall_predict_y,'color','m');
        end

%         set(H_PreTrue_Dis,'xdata',[fix(i/2) fix(i/2)],'ydata',[0 distFrPreToTrue]);


%         if(~isempty(zf))
%             xyf = z2xy(zf);
%             mapxyf = changeCoordinate(xyf,x(1),x(2),x(3));
%             line(mapxyf(:,1),mapxyf(:,2),'linestyle','p','color','r');
%         end
%         if(~isempty(zn))
%             xyn = z2xy(zn);
%             mapxyn = changeCoordinate(xyn,x(1),x(2),x(3));
%             line(mapxyn(:,1),mapxyn(:,2),'linestyle','p','color','k');
%         end
        drawnow;
    end
    
    
    %%
    pause(0.01);
end

fclose(fid);
end

%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%从文件组中获取参数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [robx,roby,robphi,G] = getDataFrFile1(fid)
    robx = fread(fid,1,'double');
    roby = fread(fid,1,'double');
    robphi = fread(fid,1,'double');
    
    G = fread(fid,1,'double');
end

%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%从文件组中获取参数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [pointNum,px,py,splitNum,splitIndex] = getDataFrFile2(fid)
    pointNum = fread(fid,1,'uchar');
    px = fread(fid,pointNum,'double');
    py = fread(fid,pointNum,'double');
    
    splitNum = fread(fid,1,'uchar');
    splitIndex = [];
    splitIndex(:,1) = fread(fid,splitNum,'uchar');
    splitIndex(:,2) = fread(fid,splitNum,'uchar');
end


%%
function p= make_covariance_ellipses(x,P)
% compute ellipses for plotting state covariances
N= 10;
inc= 2*pi/N;
phi= 0:inc:2*pi;

lenx= length(x);
lenf= (lenx-3)/2;
p= zeros (2,(lenf+1)*(N+2));

ii=1:N+2;
p(:,ii)= make_ellipse(x(1:2), P(1:2,1:2), 2, phi);

ctr= N+3;
for i=1:lenf
    ii= ctr:(ctr+N+1);
    jj= 2+2*i; jj= jj:jj+1;
    
    p(:,ii)= make_ellipse(x(jj), P(jj,jj), 2, phi);
    ctr= ctr+N+2;
end
end

%
%

function p= make_ellipse(x,P,s, phi)
% make a single 2-D ellipse of s-sigmas over phi angle intervals 
r= sqrtm(P);
a= s*r*[cos(phi); sin(phi)];
p(2,:)= [a(2,:)+x(2) NaN];
p(1,:)= [a(1,:)+x(1) NaN];
end
%
%


function p= make_laser_lines (rb,xv)
% compute set of line segments for laser range-bearing measurements
if isempty(rb), p=[]; return, end
len= size(rb,2);
lnes(1,:)= zeros(1,len)+ xv(1);
lnes(2,:)= zeros(1,len)+ xv(2);
lnes(3:4,:)= TransformToGlobal([rb(1,:).*cos(rb(2,:)); rb(1,:).*sin(rb(2,:))], xv);
p= line_plot_conversion (lnes);
end

function [wallx,wally] = getWallXY(wall)

    num = size(wall,1)/2;
    
    wallx = zeros(1,3*num);
    wally = zeros(1,3*num);
    
    for i = 1:num
        wallx(i*3-2:i*3) = [wall(2*i-1,1) wall(2*i,1) nan];
        wally(i*3-2:i*3) = [wall(2*i-1,2) wall(2*i,2) nan];
    end
    
end