www.gusucode.com > matlab编程实现平台的slam模拟器源码程序 > matlab编程实现平台的slam模拟器源码程序/ekf-slam-matlab-master/Robot.m

    % Author: Jai Juneja
% Date: 13/02/2013
%
% Robot class contains properties and functions relating to the robot.
classdef Robot < handle
    properties
        % Robot properties
        wheelbase       % Width of wheel base (dist. between opposite wheels)
        length          % Length of robot
        R               % True pose [x y a]
        r               % Estimated pose [x y a]
        q               % True system noise
        u               % Control vector [dx da]
        maxspeed        % Maximum speed (m/s)
        min_turn_rad    % Turning radius (m)
        curr_wpt        % Current waypoint reached
    end
    
    methods
        
        function rob = Robot                        % Constructor method
            % Default values
            rob.wheelbase	=   1;
            rob.length      =   1.5;
            rob.R           =   [0, 0, 0]';
            rob.r           =   rob.R;
            rob.q           =   [0.02;pi/180];       % 2cm, 1 deg
            rob.u           =   [0.1; 0.02];
            rob.maxspeed    =   1.4;                % 1.4m/s ~ 5km/h
            rob.min_turn_rad=   0.5;
            rob.curr_wpt    =   1;
        end

        % Move the robot and obtain new pose and Jacobians.
        %
        % Inputs:
        %   rob             :   Robot object
        %   n               :   Noise (n = [nx na]')
        %   Optional:
        %       strRobType  :   Robot pose to move (true or estimated)
        %
        % Outputs:
        %   r_new           :   New position
        %   RNEW_r          :   Jacobian of r_new wrt. r
        %   RNEW_u          :   Jacobian of r_new wrt. u
        function [r_new, RNEW_r, RNEW_u] = move(rob, n, strRobType)
            
            if nargin < 3
                % Robot position (p = [x y]') and orientation (a):
                pose = rob.r; a = rob.r(3);
            elseif strcmp(strRobType, 'true')
                pose = rob.R; a = rob.R(3);
            else
                error('strRobType can only take the value "true"');
            end

            % Control input:
            dx = rob.u(1) + n(1);
            da = rob.u(2) + n(2);
            dp = [dx; 0];

            % Determine new orientation
            a_new = a + da;    
            % Ensure that angle is between -pi and pi
            a_new = getPiToPi(a_new);

            if nargout == 1
                % Translate robot to new position in global frame
                p_new = transToGlobal(pose, dp);

            else    % Get Jacobians

                % Translate robot to new position in global frame
                [p_new, PNEW_r, PNEW_dp] = transToGlobal(pose, dp);

                % Jacobians of r_a_new:
                ANEW_a = 1;
                ANEW_da = 1;

                % Hence, Jacobians of r_new:
                RNEW_r = [PNEW_r; 0 0 ANEW_a];

                % We define the perturbation such that it is in the same space
                % as control u. This means that there is uncertainty in how much
                % the robot advances and how much it turns. This means that the
                % Jacobians of RNEW with respect to u are the same as the Jacobian
                % of RNEW with respect to n. Less coding necessary, so a good
                % option.

                RNEW_u = [PNEW_dp(:, 1) zeros(2, 1); 0 ANEW_da];

            end

            r_new = [p_new; a_new];
            
        end

        % Return the vertices of a triangle of dimensions base*length, 
        % centred at (x, y) and with orientation a.
        %
        % Inputs:
        %   r = [x y a]'        :   local co-ordinate frame of robot
        %   base                :   size of triangle base
        %   length              :   length of triangle
        %
        % Outputs:
        %   p = [x1 x2 x3 x4;
        %        y1 y2 y3 y4]	:   vertices of resulting triangle
        function p = computeTriangle(rob, strRobType, r_pos)
            
            if nargin < 2
                pose = rob.r;
            elseif nargin < 3 && strcmp(strRobType, 'true')
                pose = rob.R;
            elseif nargin < 4
                pose = r_pos;
            else
                error('strRobType can only take the value "True"');
            end
            
            p = zeros(2, 4);

            p(:, 1) = [-rob.length/3; -rob.wheelbase/2];
            p(:, 2) = [2*rob.length/3; 0];
            p(:, 3) = [-rob.length/3; rob.wheelbase/2;];

            for i = 1:3
                p(:, i) = transToGlobal(pose, p(:, i));
            end

            % We include a fourth point that is equal to the first point in the
            % triangle. This allows us to 'close' the triangle when plotting it
            % using the line function.
            p(:, 4) = p(:, 1);

        end
        
        function steer(rob, Wpts)
            % Determine if current waypoint reached
            wpt = Wpts(:, rob.curr_wpt);
            % Distance from current waypoint
            dist = sqrt((wpt(1)-rob.R(1))^2 + (wpt(2)-rob.R(2))^2);
            if dist < rob.min_turn_rad
                if rob.curr_wpt < size(Wpts, 2)
                    rob.curr_wpt = rob.curr_wpt + 1;
                else
                    rob.curr_wpt = 1; % Go back to the start
                end
                wpt = Wpts(:, rob.curr_wpt);
            end
            % Change in robot orientation to face current waypoint
            da = getPiToPi(atan2(wpt(2)-rob.R(2), wpt(1)-rob.R(1))-rob.R(3));
            % Amount by which to perturb current robot control:
            dda = da - rob.u(2);
            du = [0; dda];
            rob.setControl(du);
        end

        % Perturb control vector by an amount du = [accel_x; accel_a].
        function u = setControl(rob, du)
            u = rob.u + du;
            % Make sure that angular control is between -pi and pi
            u(2) = getPiToPi(u(2));
            if abs(u(1)) > rob.maxspeed
                % Adjust speed so that max speed isn't exceeded
                u(1) = sign(u(1)) * rob.maxspeed;
            end
            turning_radius = u(1)/u(2);     % Using formula v = omega * r
            if abs(turning_radius) < rob.min_turn_rad
                % Adjust angular velocity so that min turning radius isn't
                % exceeded
            	u(2) = sign(u(2)) * abs(u(1)) / rob.min_turn_rad;
            end
            
            rob.u = u;
        end
    end
end