EKF-SLAM matlab仿真(2)

EKF-SLAM中機器人的運動軌跡爲:X={x1,...xk},其中每個x表示機器人在第i時刻的位姿,其中機器人在平面運動,故使用2D的參數:xi=[x,y,θ],路標的集合爲L={l1,...ln},需要建立運動方程和觀測方程,由於上述兩個方式是非線性的,根據EKF理論,需要將他們線性化,進而求得幾個重要的雅可比矩陣,然後對EKF的預測部分兩個方程和更新部分三個方程進行求解。
EKF-SLAM有兩個重要的假設:誤差爲高斯分佈,以及工作點附近可以用導數線性化。當這兩個假設成立時,EKF-SLAM可以實時的更新機器人的當前位姿與路標。
EKF-SLAM程序如下:
%-------------------------------------------------------------------------
% FILE: slam.m 
% DESC: Implements the SLAM algorithm based on a robot model and sensor 
%       data from Nebot.
%landmarks(真實路標) 
%estbeac=estimation(估計)+beacon(路標),將estbeac的值賦給landmarks然後將estbeac清除。
%xest                                   狀態矩陣
%Pest                                   協方差矩陣
%A W Jh                                 雅可比矩陣
%Q                                      過程激勵噪聲協方差矩陣
%k                                      迭代次數
%K                                      卡爾曼增益
%numStates                              狀態的數量  初始化時候就三個,即位置(x,y)和姿態(phi)
%phi                                    姿態,即與x軸的夾角
%Steering                               轉向角
%alpha                                  轉向角
%Ve = Velocity                          後輪的轉速
%Vc                                     車水平平移速度
%zlaser=[rangeArray; bearingArray];     機器人與路標的距離和方位
%--------------------------------------------------------------------------
clear all; clc;
load('data_set');
load('beac_juan3.mat');   %beac_juan3.mat中內容爲路標,命令whos –file查看該文件中的內容
landmarks=estbeac; clear estbeac; % true landmark positions (measured w/GPS sensor)
%---------------------  DATA INITIALIZATION   -----------------------------
% Vehicle constants
L=2.83;     % distance between front and rear axles(前後輪軸之間的距離)
h=0.76;     % distance between center of rear axle and encoder(後輪軸中心與編碼器的距離)
b=0.5;      % vertical distance from rear axle to laser(後輪軸中心到激光傳感器的垂直距離)
a=3.78;     % horizontal distance from rear axle to laser(後輪軸中心到激光傳感器的水平距離)

% EKF components used in multiple functions
global xest Pest A Q W   %定義全局變量
global numStates k  
xest = zeros(3,1);  % state matrix
Pest = zeros(3,3);  % covariance matrix2
numStates=3;        % initially, there are no landmarks(i.e. the number of value in the state matrix)

% matrixes initialization
A = zeros(3,3);                 % process model jacobian
W = eye(3);                     % process noise jacobian
Q = [.49   0   0; 0 .49 0; 0 0 (7*pi/180)^2];
Jh = zeros(2,3);                % sensor model jacobian
K = zeros(3,3);                 % kalman gain

% initialize time
To = min([TimeGPS(1),Time_VS(1),TimeLaser(1)]); % data starts being collected at 45 secs for some reason??
Time = Time - To;
t=Time(1);
tfinal = 112;   % there is 112 seconds worth of data
k=1;            % loop iteration counter(循環迭代計數)

% initialize estimates
xest(1,1) = GPSLon(1);      % x position of vehicle
xest(2,1) = GPSLat(1);      % y position of vehicle
xest(3,1) = -126*pi/180;    % phi of vehicle       % LB(?):how to get this value?
Pest(:,:) = [0.1, 0, 0; 0, 0.1, 0; 0, 0, 15*pi/180];

% initial inputs
alpha = Steering(1);    % measured steering angle(測量轉向角)
Ve = Velocity(1);       % measured velocity at back wheel(測量後輪速率)
Vc = Velocity(1) / (1 - (h/L)*tan(alpha));  % measured velocity transformed to vehicle center
%--------------------- end of DATA INITIALIZATION  ------------------------


disp('Running through Kalman filter...');


n_dsp = 0;
%------------------  EXTENDED KALMAN FILTER PROCEDURE  --------------------
while t<tfinal

    k=k+1;
    t=Time(k);
    dt=t-Time(k-1);
    % Calculate time update matrices (prediction step of kalman filter)
    % Vc and alpha are updated after prediction...therefore, Vc is Vc(k-1) & alpha is alpha(k-1)
    %下面是公式(1)
    phi = xest(3,k-1);  % so I don't have to type in xest(3,k-1) for every phi below
    xest(1,k) = xest(1,k-1) + dt*Vc*cos(phi) - dt*Vc/L*tan(alpha)*(a*sin(phi)+b*cos(phi));     % x prediction
    xest(2,k) = xest(2,k-1) + dt*Vc*sin(phi) + dt*Vc/L*tan(alpha)*(a*cos(phi)-b*sin(phi));     % y prediction
    xest(3,k) = xest(3,k-1) + dt*Vc/L*tan(alpha);     % phi prediction
    xest(3,k) = normalizeAngle(xest(3,k));      % keep phi between -180 and 180 degrees
    
    % landmarks are assumed to be static, i.e. pi(k) = pi(k-1)         
    if(numStates>3)
        for i=4:numStates
            xest(i,k)= xest(i,k-1);
        end
    end
    
    % Calculate Jacobian A based on vehicle model (df/dx)
    A(1,1)=1; A(1,2)=0; A(1,3) = -dt*Vc*sin(phi) - dt*Vc/L*tan(alpha)*(a*cos(phi)-b*sin(phi));
    A(2,1)=0; A(2,2)=1; A(2,3) = dt*Vc*cos(phi) - dt*Vc/L*tan(alpha)*(a*sin(phi)+b*cos(phi)); 
    A(3,1)=0; A(3,2)=0; A(3,3)=1;
    % rest of A (which is just 2 null matrices and 1 identity) is added in new_state function
        
    % Calculate prediction for covariance matrix
    Pest = A*Pest*A' + W*Q*W';      %(公式2)

    % Check to see if new velocity and steering measurements are available
    if Sensor(k)==2   % encoders(編碼器) are sensor #2
        Ve = Velocity(Index(k));
        alpha = Steering(Index(k));
        Vc = Ve / (1-(h/L)*tan(alpha));
    end  
    
    % Check to see if new laser(激光) data is available    
    if (Sensor(k)==3 && t>1)   % SICK is sensor #3                
        
        % from a single 180 degree scan, determine # of landmarks & center of each landmark
        [rangeArray bearingArray] = getLandmarkCenter(Laser(Index(k),:), Intensity(Index(k),:));   
        zlaser=[rangeArray; bearingArray];          % range/bearing data in observation model format
        numLandmarks = size(rangeArray,2);          % number of LMs captured in a single scan      
              
        for i=1:numLandmarks                            % for i = 1 to # of landmakrs picked up in single scan
            if(numStates==3)                            % if 1st observed landmark, update state and covariance
                new_state(zlaser(:,i));                 % add new state (i.e. increase all matrix sizes)
                numStates = numStates + 2;              % increase number of states by 2 (1 for xi, 1 for yi)
                [xest,Pest] = updateNew(zlaser(:,i));   % update state and covariance
            else                                        % not 1st landmark -> check to make sure no LMs in range
                [dist,index]=nearby_LMs(zlaser(:,i));   % dist from observation to already incorporated LMs (< 3m)
                min_dist = 2;                           % minimum distance between landmark and observation
                if dist>min_dist                        % if dist to nearby_LM is > "min_dist", add observation as new LM
                    new_state(zlaser(:,i));             % add new state (i.e. increase all matrix sizes)
                    numStates = numStates + 2;          % increase number of states by 2 (1 for xi, 1 for yi)
                    [xest,Pest] = updateNew(zlaser(:,i));               % update state and covariance
                else                                                    % else find closest LM and associate
                    closest = 4 + 2*(index-1);                          % find LM which is closest to observation
                    [xest,Pest] = updateExisting(zlaser(:,i),closest);  % update state and covariance
                end
            end
        end
    end
    % LB_add: display information
    if( floor(t/tfinal*100) > n_dsp)
        clc;
        n_dsp = floor(t/tfinal*100);
        str = sprintf('運行卡爾曼濾波... [%d%c]', n_dsp,'%');
        disp(str);
    end
end  % end while
%-------------- end of  EXTENDED KALMAN FILTER PROCEDURE -----------------

%--------------------------- PLOT RESULTS --------------------------------
figure(1); hold on;
plot(GPSLon(1:560),GPSLat(1:560));          % robot position (true)
plot(xest(1,1:k),xest(2,1:k),'g');          % robot position (model)
plot(landmarks(:,1),landmarks(:,2),'*');    % landmark position (true)
for i=4:2:numStates
    plot(xest(i,k),xest(i+1,k),'r*');     % landmark position (model)
end
legend('機器人實際位置','機器人slam位置','路標實際位置','路標slam位置',2);
xlabel('x [meters]'); ylabel('y [meters]');
axis([-10 20 -25 20]);

%% Estimate error(估計誤差)  
x_error1 = GPSLon(1:560)-xest(1,1:560);
x_error2 = GPSLat(1:560)-xest(2,1:560);
for i=4:2:numStates 
    landmarks_error1=landmarks(:,2)-xest(i+1,k);
end
for i=4:2:numStates 
    landmarks_error2=landmarks(:,1)-xest(i,k);
end
%% Graph 2  
figure(2)   
plot(x_error1),grid on;  
title('機器人位置誤差 on X axis')  
xlabel('時間 [sec]')  
ylabel('位置均方根誤差 [m]') 
axis([0 112 -25 25]);
hold off; 
%% Graph 3  
figure(3)   
plot(x_error2),grid on;  
title('機器人位置誤差 on Y axis')  
xlabel('時間 [sec]')  
ylabel('位置均方根誤差 [m]') 
axis([0 112 -25 25]);
hold off;
%% Graph 4  
figure(4)   
plot(landmarks_error1),grid on;  
title('路標位置誤差 on x axis')  
xlabel('時間 [sec]')  
ylabel('位置均方根誤差 [m]') 
axis([0 18 -25 25]);
hold off;
%% Graph 5 
figure(5)   
plot(landmarks_error2),grid on;  
title('路標位置誤差 on Y axis')  
xlabel('時間 [sec]')  
ylabel('位置均方根誤差 [m]') 
axis([0 18 -25 25]);
hold off;
%------------------------ end of PLOT RESULTS -----------------------------

其中用到的子函數在EKF-SLAM matlab仿真(1)中下載文檔裏。分別爲

運行EKF-SLAM matlab程序結果如下圖所示:









發佈了11 篇原創文章 · 獲贊 24 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章