Bước cập nhật EKF-SLAM, Kalman Gain trở thành số ít


16

Tôi đang sử dụng EKF cho SLAM và tôi gặp một số vấn đề với bước cập nhật. Tôi đang nhận được một cảnh báo rằng K là số ít, rcondđánh giá near eps or NaN. Tôi nghĩ rằng tôi đã tìm ra vấn đề đối với sự đảo ngược của Z. Có cách nào để tính toán Kalman Gain mà không đảo ngược thuật ngữ cuối cùng không?

Tôi không tích cực 100% đây là nguyên nhân của vấn đề, vì vậy tôi cũng đã đặt toàn bộ mã của mình ở đây . Điểm vào chính là slam2d.

function [ x, P ] = expectation( x, P, lmk_idx, observation)
    % expectation
    r_idx = [1;2;3];
    rl = [r_idx; lmk_idx];

    [e, E_r, E_l] = project(x(r), x(lmk_idx)); 
    E_rl = [E_r E_l];
    E = E_rl * P(rl,rl) * E_rl';

    % innovation
    z = observation - e;
    Z = E;

    % Kalman gain
    K = P(:, rl) * E_rl' * Z^-1;

    % update
    x = x + K * z;
    P = P - K * Z * K';
end


function [y, Y_r, Y_p] = project(r, p)     
    [p_r, PR_r, PR_p] = toFrame2D(r, p);
    [y, Y_pr]   = scan(p_r);
    Y_r = Y_pr * PR_r;
    Y_p = Y_pr * PR_p;    
end


function [p_r, PR_r, PR_p] = toFrame2D(r , p)
    t = r(1:2);
    a = r(3);
    R = [cos(a) -sin(a) ; sin(a) cos(a)];
    p_r = R' * (p - t);
    px = p(1);
    py = p(2);
    x = t(1);
    y = t(2);
    PR_r = [...
        [ -cos(a), -sin(a),   cos(a)*(py - y) - sin(a)*(px - x)]
        [  sin(a), -cos(a), - cos(a)*(px - x) - sin(a)*(py - y)]];
    PR_p = R';    
end


function [y, Y_x] = scan(x)
    px = x(1);
    py = x(2);
    d = sqrt(px^2 + py^2);
    a = atan2(py, px);
    y = [d;a];
    Y_x =[...
    [     px/(px^2 + py^2)^(1/2), py/(px^2 + py^2)^(1/2)]
    [ -py/(px^2*(py^2/px^2 + 1)), 1/(px*(py^2/px^2 + 1))]];
end

Chỉnh sửa: project(x(r), x(lmk))nên đã project(x(r), x(lmk_idx))và đang được sửa chữa ở trên.

K đi số ít sau một lúc, nhưng không ngay lập tức. Tôi nghĩ rằng đó là khoảng 20 giây hoặc lâu hơn. Tôi sẽ thử những thay đổi mà @josh đề xuất khi tôi về nhà tối nay và đăng kết quả.

Cập nhật 1:

Mô phỏng của tôi trước tiên quan sát 2 mốc, vì vậy K là . dẫn đến ma trận , do đó không thể thêm nó vào x trong dòng tiếp theo. 7 x 2(P(rl,rl) * E_rl') * inv( Z )5 x 2

K trở thành số ít sau 4,82 giây, với các phép đo ở 50Hz (241 bước). Theo lời khuyên ở đây , tôi đã thử K = (P(:, rl) * E_rl')/Zkết quả trong 250 bước trước khi cảnh báo về K là số ít được tạo ra.

Điều này cho tôi biết vấn đề không phải là đảo ngược ma trận, nhưng nó ở đâu đó gây ra vấn đề.

Cập nhật 2

Vòng lặp chính của tôi là (với một đối tượng robot để lưu trữ x, P và các con trỏ mốc):

for t = 0:sample_time:max_time
    P = robot.P;
    x = robot.x;
    lmks = robot.lmks;
    mapspace = robot.mapspace;

    u = robot.control(t);
    m = robot.measure(t);

    % Added to show eigenvalues at each step
    [val, vec] = eig(P);
    disp('***')
    disp(val)

    %%% Motion/Prediction
    [x, P] = predict(x, P, u, dt);

    %%% Correction
    lids = intersect(m(1,:), lmks(1,:));  % find all observed landmarks
    lids_new = setdiff(m(1,:), lmks(1,:));
    for lid = lids
        % expectation
        idx = find (lmks(1,:) == lid, 1);
        lmk = lmks(2:3, idx);
        mid = m(1,:) == lid;
        yi = m(2:3, mid);

        [x, P] = expectation(x, P, lmk, yi);
    end  %end correction

    %%% New Landmarks

    for id = 1:length(lids_new)
    % if id ~= 0
        lid = lids_new(id);
        lmk = find(lmks(1,:)==false, 1);
        s = find(mapspace, 2);
        if ~isempty(s)
            mapspace(s) = 0;
            lmks(:,lmk) = [lid; s'];
            yi = m(2:3,m(1,:) == lid);

            [x(s), L_r, L_y] = backProject(x(r), yi);

            P(s,:) = L_r * P(r,:);
            P(:,s) = [P(s,:)'; eye(2)];
            P(s,s) = L_r * P(r,r) * L_r';
        end
    end  % end new landmarks

    %%% Save State
    robot.save_state(x, P, mapspace, lmks)
    end  
end

Ở cuối vòng lặp này, tôi lưu x và P trở lại robot, vì vậy tôi tin rằng tôi đang truyền bá hiệp phương sai qua mỗi lần lặp.

Nhiều chỉnh sửa Các giá trị bản địa chính xác (hy vọng) hiện đang ở đây . Có một số giá trị riêng là âm. Mặc dù cường độ của chúng không bao giờ lớn, nhưng tối đa , nó xảy ra ở lần lặp ngay sau khi mốc đầu tiên được quan sát và thêm vào bản đồ (trong phần "mốc mới" của vòng lặp chính).102


1
Bạn đang tuyên truyền sự không chắc chắn? Giá trị bản địa của hiệp phương sai của bạn có được tùy ý nhỏ hay lớn không?
Josh Vander Hook

1
Những gì bạn đặt trong pastebin là các hàm riêng, không phải giá trị riêng. làm điều này: [v, d] = eig (P). phân tán (diag (d)). hoặc chỉ phân tán (eig (P)). Sau đó, bạn có thể kiểm tra các điều kiện cần thiết sau: Có phải tất cả các giá trị riêng> 0 ở mỗi bước (chúng nên có trong thực tế). Chúng có tăng sau khi nhân giống và giảm sau khi đo / hiệu chỉnh không? Theo kinh nghiệm của tôi, đây thường là vấn đề.
Josh Vander Hook

2
Một cái gì đó sai nếu giá trị riêng của bạn là âm. Khi bạn khởi tạo một mốc, sự không chắc chắn liên quan đến vị trí ước tính đầu tiên của nó là gì?
Josh Vander Hook

Sự quan sát là một cặp. Khi mốc đầu tiên được khởi tạo, nó có hiệp phương sai [5,8938, 3.0941; 3.0941, 2.9562]. Đối với lần thứ hai, hiệp phương sai của nó là [22.6630 -14,3822; -14,3822, 10,5484] Ma trận đầy đủ có ở đây
munk

Câu trả lời:


5

Tôi chỉ thấy bài viết của bạn bây giờ và có lẽ đã quá muộn để thực sự giúp bạn ... nhưng trong trường hợp bạn vẫn quan tâm đến điều này: tôi nghĩ rằng tôi đã xác định được vấn đề của bạn.

Bạn viết ma trận hiệp phương sai đổi mới theo cách sau

E = jacobian measure * P * jacobian measure

Về mặt lý thuyết có thể ổn nhưng điều xảy ra là nếu thuật toán của bạn có hiệu quả và đặc biệt nếu bạn đang làm việc trên một mô phỏng: độ không đảm bảo sẽ giảm, đặc biệt là theo hướng đo lường của bạn. Vì vậy, Esẽ có xu hướng [[0,0][0,0]].

Để tránh vấn đề này, điều bạn có thể làm là thêm tiếng ồn đo tương ứng với độ không đảm bảo trong phép đo và hiệp phương sai đổi mới của bạn trở thành

E= Jac*P*Jac'+R

trong đó Rhiệp phương sai của nhiễu đo (ma trận đường chéo trong đó các số hạng trên đường chéo là bình phương độ lệch chuẩn của nhiễu). Nếu bạn thực sự không muốn xem xét tiếng ồn, bạn có thể làm cho nó nhỏ như bạn muốn.

Tôi cũng nói thêm rằng cập nhật hiệp phương sai của bạn có vẻ lạ đối với tôi công thức cổ điển là:

P=P - K * jacobian measure * P

Tôi chưa bao giờ thấy công thức của bạn được viết ở bất cứ nơi nào khác, tôi có thể đúng nhưng nếu bạn không chắc chắn về nó, bạn nên kiểm tra nó.


Ah, thủ thuật "muối hiệp phương sai" cũ.
Josh Vander Hook

1

Nếu bạn chỉ cập nhật ma trận con hiệp phương sai liên quan đến robot và mốc (như thông thường), thì nên Kvà cho kích thước trạng thái robot và kích thước mốc . Lưu ý rằng bạn có:P(Nr+Nl)×(Nr+Nl)NrNl

K = P(:, rl) * E_rl' * Z^-1

mà tôi nghĩ nên

(P(rl,rl) * E_rl') * inv(Z).

(xem: phân chia ma trận ). Kiểm tra kích thước của K.

Ngoài ra: Vui lòng cung cấp thêm một chút thông tin: Đi Ksố ít ngay lập tức hay chỉ sau một thời gian?

Điều này làm tôi lo lắng: project(x(r), x(lmk));lmkkhông được xác định.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.