diff --git a/matlab/GNSSaidedINS_data.mat b/matlab/GNSSaidedINS_data.mat
new file mode 100644
index 0000000000000000000000000000000000000000..60b9f6e1c6b916a1fe14c166240399021974081c
Binary files /dev/null and b/matlab/GNSSaidedINS_data.mat differ
diff --git a/matlab/GPSaidedINS.m b/matlab/GPSaidedINS.m
new file mode 100644
index 0000000000000000000000000000000000000000..6d7a3474e526f41d4cac46099ac6d46cc26cdecd
--- /dev/null
+++ b/matlab/GPSaidedINS.m
@@ -0,0 +1,286 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% function call: out_data=GPSaidedINS(in_data,settings)
+%
+% This function integrates GNSS and IMU data. The data fusion
+% is based upon a loosely-coupled feedback GNSS-aided INS approach.
+%
+% Input struct:
+% in_data.GNSS.pos_ned      GNSS-receiver position estimates in NED
+%                           coordinates [m]
+% in_data.GNSS.t            Time of GNSS measurements [s]
+% (in_data.GNSS.HDOP        GNSS Horizontal Dilution of Precision [-]) 
+% (in_data.GNSS.VDOP        GNSS Vertical Dilution of Precision [-]) 
+% in_data.IMU.acc           Accelerometer measurements [m/s^2]
+% in_data.IMU.gyro          Gyroscope measurements [rad/s]
+% in_data.IMU.t             Time of IMU measurements [s]
+%
+% Output struct:
+% out_data.x_h              Estimated navigation state vector [position; velocity; attitude]
+% out_data.delta_u_h        Estimated IMU biases [accelerometers; gyroscopes]
+% out_data.diag_P           Diagonal elements of the Kalman filter state
+%                           covariance matrix.
+%
+%
+% Edit: Isaac Skog (skog@kth.se), 2016-09-06
+% Revised: Bo Bernhardsson, 2018-01-01
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function out_data=GPSaidedINS(in_data,settings)
+
+
+% Copy data to variables with shorter name
+u=[in_data.IMU.acc;in_data.IMU.gyro];
+t=in_data.IMU.t;
+
+%% Initialization
+% Initialize the navigation state
+x_h=init_navigation_state(u,settings);
+
+% Initialize the sensor bias estimate
+delta_u_h=zeros(6,1);
+
+% Initialize the Kalman filter
+[P,Q1,Q2,~,~]=init_filter(settings);
+
+
+% Allocate memory for the output data
+N=size(u,2);
+out_data.x_h=zeros(10,N);
+out_data.x_h(:,1)=x_h;
+out_data.diag_P=zeros(15,N);
+out_data.diag_P(:,1)=diag(P);
+out_data.delta_u_h=zeros(6,N);
+
+%% Information fusion
+ctr_gnss_data=1;
+GPS_position=true;
+
+%% Initialize GPS sensor 
+sensor.state='warm_start_available';
+sensor.howLong=0;
+sensor.ephExp=1800.0;
+sensor.fp=0;
+sensor.eph=5;
+turn=true;
+power=400;
+energy=0;
+
+pre_state='startup';
+a=0;
+
+for k=2:N
+    
+    % Sampling period
+    Ts=t(k)-t(k-1);
+    
+    %%%%%%%%%%%%%%%%%
+    %% GPS sensor  %%
+    %%%%%%%%%%%%%%%%%
+    %number of visible satellites
+    sv=5;
+    %control action
+    a=[a,sum(sqrt(out_data.diag_P(1:3,k-1)))];
+    if sum(sqrt(out_data.diag_P(1:3,k-1)))<1.0
+        turn=false;
+    else
+        turn=true;
+    end
+    %update sensor state
+    pre_state=sensor.state;
+    sensor=gps(t(k),sensor,turn,sv);
+    %determine if GPS position is available
+    GPS_position=strcmp(sensor.state,'position_available');
+    %compute power consumption
+    if ~(strcmp(sensor.state,'no_info')||strcmp(sensor.state,'warm_start_available'))
+        energy=energy+power*Ts;
+    end
+    
+%     %print new state and current time if it changes
+%     if ~strcmp(pre_state, sensor.state)
+%         sensor.state
+%         t(k)
+%     end
+    
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    
+    % Calibrate the sensor measurements using current sensor bias estimate.
+    u_h=u(:,k)+delta_u_h;
+    
+    % Update the INS navigation state
+    x_h=Nav_eq(x_h,u_h,Ts);
+    
+    % Get state space model matrices
+    [F,G]=state_space_model(x_h,u_h,Ts);
+    
+    % Time update of the Kalman filter state covariance.
+    P=F*P*F'+G*blkdiag(Q1,Q2)*G';
+    
+    % Defualt measurement observation matrix  and measurement covariance
+    % matrix
+    
+    y = in_data.GNSS.pos_ned(:,ctr_gnss_data);      
+    H = [eye(3) zeros(3,12)]; 
+    R = settings.sigma_gps^2*eye(3);
+    
+    ind = zeros(1,6);  % index vector, describing available measurements
+    % Check if GNSS measurement is available
+    if t(k)==in_data.GNSS.t(ctr_gnss_data) 
+       if GPS_position
+            ind(1:3)=1;
+       end
+        % Update GNSS data counter
+        ctr_gnss_data=min(ctr_gnss_data+1,length(in_data.GNSS.t));
+    end
+    
+    ind=logical(ind);
+    H=H(ind,:);
+    y=y(ind);
+    R=R(ind,ind);
+    
+    % Calculate the Kalman filter gain.
+    K=(P*H')/(H*P*H'+R);
+    
+    % Update the perturbation state estimate.
+    z=[zeros(9,1); delta_u_h]+K*(y-H(:,1:6)*x_h(1:6));
+    
+    % Correct the navigation states using current perturbation estimates.
+    x_h(1:6)=x_h(1:6)+z(1:6);
+    x_h(7:10)=Gamma(x_h(7:10),z(7:9));
+    delta_u_h=z(10:15);
+    
+    % Update the Kalman filter state covariance.
+    P=(eye(15)-K*H)*P;
+    
+    % Save the data to the output data structure
+    out_data.x_h(:,k)=x_h;
+    out_data.diag_P(:,k)=diag(P);
+    out_data.delta_u_h(:,k)=delta_u_h;
+    
+end
+figure(11)
+plot(a),grid
+energy
+end
+
+
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%                          SUB-FUNCTIONS                                %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%       Init filter          %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function [P,Q1,Q2,R,H]=init_filter(settings)
+
+
+% Kalman filter state matrix
+P=zeros(15);
+P(1:3,1:3)=settings.factp(1)^2*eye(3);
+P(4:6,4:6)=settings.factp(2)^2*eye(3);
+P(7:9,7:9)=diag(settings.factp(3:5)).^2;
+P(10:12,10:12)=settings.factp(6)^2*eye(3);
+P(13:15,13:15)=settings.factp(7)^2*eye(3);
+
+% Process noise covariance
+Q1=zeros(6);
+Q1(1:3,1:3)=diag(settings.sigma_acc).^2;
+Q1(4:6,4:6)=diag(settings.sigma_gyro).^2;
+
+Q2=zeros(6);
+Q2(1:3,1:3)=settings.sigma_acc_bias^2*eye(3);
+Q2(4:6,4:6)=settings.sigma_gyro_bias^2*eye(3);
+
+% GNSS-receiver position measurement noise
+R=settings.sigma_gps^2*eye(3);
+
+% Observation matrix
+H=[eye(3) zeros(3,12)];
+
+end
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%  Init navigation state     %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function x_h=init_navigation_state(u,settings)
+
+
+% Calculate the roll and pitch
+f=mean(u(:,1:100),2);
+roll=atan2(-f(2),-f(3));
+pitch=atan2(f(1),norm(f(2:3)));
+
+% Initial coordinate rotation matrix
+Rb2t=Rt2b([roll pitch settings.init_heading])';
+
+% Calculate quaternions
+q=dcm2q(Rb2t);
+
+% Initial navigation state vector
+x_h=[zeros(6,1); q];
+
+end
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%  State transition matrix   %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function [F,G]=state_space_model(x,u,Ts)
+
+% Convert quaternion to DCM
+Rb2t=q2dcm(x(7:10));
+
+% Transform measured force to force in
+% the tangent plane coordinate system.
+f_t=Rb2t*u(1:3);
+St=[0 -f_t(3) f_t(2); f_t(3) 0 -f_t(1); -f_t(2) f_t(1) 0];
+
+% Only the standard errors included
+O=zeros(3);
+I=eye(3);
+Fc=[O I O O O;
+    O O St Rb2t O;
+    O O O O -Rb2t;
+    O O O O O;
+    O O O O O];
+
+% Approximation of the discret
+% time state transition matrix
+F=eye(15)+Ts*Fc;
+
+% Noise gain matrix
+G=Ts*[O O O O; Rb2t O O O; O -Rb2t O O; O O I O; O O O I];
+end
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%     Error correction of quaternion    %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function q=Gamma(q,epsilon)
+
+% Convert quaternion to DCM
+R=q2dcm(q);
+
+% Construct skew symetric matrx
+OMEGA=[0 -epsilon(3) epsilon(2); epsilon(3) 0 -epsilon(1); -epsilon(2) epsilon(1) 0];
+
+% Correct the DCM matrix
+R=(eye(3)-OMEGA)*R;
+
+% Calculte the corrected quaternions
+q=dcm2q(R);
+end
+
+
+
+
+
+
+
diff --git a/matlab/Nav_eq.m b/matlab/Nav_eq.m
new file mode 100644
index 0000000000000000000000000000000000000000..3c0a3c4d91b472384714de47a6194ef7a39053ff
--- /dev/null
+++ b/matlab/Nav_eq.m
@@ -0,0 +1,71 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% function call: x=Nav_eq(x,u,dt)
+%
+% Function that implements the navigation equations of an INS.
+%
+% Inputs:
+% x         Current navigation state [position (NED), velocity (NED), attitude (Quaternion)]
+% u         Measured inertial quantities [Specific force (m/s^2), Angular velocity (rad/s)]
+% dt        Sampling period (s)
+%
+% Output:
+% x         Updated navigation state [position (NED), velocity (NED), attitude (Quaternion)]
+%
+% Edit: Isaac Skog (skog@kth.se), 2016-09-06
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function x=Nav_eq(x,u,dt)
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%          Position and velocity        %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Gravity vector (This should depend on the current location, but
+% since moving in a small area it is approximatly constant).
+g_t=gravity(59,0);
+
+f_t=q2dcm(x(7:10))*u(1:3);
+
+% Subtract gravity, to obtain accelerations in tangent plane coordinates
+acc_t=f_t-g_t;
+
+% state space model matrices
+A=eye(6);
+A(1,4)=dt;
+A(2,5)=dt;
+A(3,6)=dt;
+
+B=[(dt^2)/2*eye(3);dt*eye(3)];
+
+% Position and velocity update
+x(1:6)=A*x(1:6)+B*acc_t;
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%        Attitude Quaternion            %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Quaternion algorithm according to Farrel, pp 49.
+
+w_tb=u(4:6);
+
+P=w_tb(1)*dt;
+Q=w_tb(2)*dt;
+R=w_tb(3)*dt;
+
+
+OMEGA=zeros(4);
+OMEGA(1,1:4)=0.5*[0 R -Q P];
+OMEGA(2,1:4)=0.5*[-R 0 P Q];
+OMEGA(3,1:4)=0.5*[Q -P 0 R];
+OMEGA(4,1:4)=0.5*[-P -Q -R 0];
+
+v=norm(w_tb)*dt;
+
+if v~=0
+    x(7:10)=(cos(v/2)*eye(4)+2/v*sin(v/2)*OMEGA )*x(7:10);
+end
+return
\ No newline at end of file
diff --git a/matlab/Rt2b.m b/matlab/Rt2b.m
new file mode 100644
index 0000000000000000000000000000000000000000..4fd56a24655a35229655911aede8f438a938af16
--- /dev/null
+++ b/matlab/Rt2b.m
@@ -0,0 +1,21 @@
+function R=Rt2b(ang)
+% function for calculation of the rotation matrix for
+% rotaion from tangent frame to body frame.
+% function R=Rt2b[roll,pitch,yaw];
+% v_b=[u v d]'
+% v_t=[N E D]'
+
+cr=cos(ang(1));
+sr=sin(ang(1));
+
+cp=cos(ang(2));
+sp=sin(ang(2));
+
+cy=cos(ang(3));
+sy=sin(ang(3));
+
+R=[cy*cp sy*cp -sp; 
+    -sy*cr+cy*sp*sr cy*cr+sy*sp*sr cp*sr; 
+    sy*sr+cy*sp*cr -cy*sr+sy*sp*cr cp*cr];
+
+
diff --git a/matlab/dcm2q.m b/matlab/dcm2q.m
new file mode 100644
index 0000000000000000000000000000000000000000..5a64b2ed9cfd839b2c426b647f2e1a68733d6bdd
--- /dev/null
+++ b/matlab/dcm2q.m
@@ -0,0 +1,19 @@
+function q=dcm2q(R)
+%
+% function q=dcm2q(R)
+% Function for transformation from directional cosine matrix to quaternions 
+% From Farrel pp 42.
+% Edit: Isaac Skog, 2007-05-24
+
+
+
+q=zeros(4,1);
+
+q(4)=0.5*sqrt(1+sum(diag(R)));
+
+q(1)=(R(3,2)-R(2,3))/(4*q(4));
+
+q(2)=(R(1,3)-R(3,1))/(4*q(4));
+
+q(3)=(R(2,1)-R(1,2))/(4*q(4));
+
diff --git a/matlab/get_settings.m b/matlab/get_settings.m
new file mode 100644
index 0000000000000000000000000000000000000000..f4946dd13c4a7cfbeb180a9eb158b2099c7f1bc3
--- /dev/null
+++ b/matlab/get_settings.m
@@ -0,0 +1,50 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Function that outputs a struct "settings" with the settings used in the
+% GNSS-aided INS
+% 
+% Edit: Isaac Skog (skog@kth.se), 2016-09-01 
+% Revised: Bo Bernhardsson 2018-01-01
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function settings=get_settings()
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%              GENERAL PARAMETERS         %% 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%settings.non_holonomic = 'off';
+%settings.speed_aiding = 'off';
+
+settings.init_heading = 320*pi/180;
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%             FILTER PARAMETERS           %% 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Process noise covariance (Q)
+% Standard deviations, need to be squared
+settings.sigma_acc = 0.05; % [m/s^2]
+settings.sigma_gyro = 0.1*pi/180; % [rad/s]
+settings.sigma_acc_bias = 0.0001; % [m/s^2.5]
+settings.sigma_gyro_bias = 0.01*pi/180; % [rad/s^1.5]
+
+
+% GNSS position measurement noise covariance (R)
+% Standard deviations, need to be squared
+settings.sigma_gps = 3/sqrt(3); %[m] 
+
+% Initial Kalman filter uncertainties (standard deviations)  
+settings.factp(1) = 10;                                 % Position [m]
+settings.factp(2) = 5;                                  % Velocity [m/s]
+settings.factp(3:5) = (pi/180*[1 1 20]');               % Attitude (roll,pitch,yaw) [rad]
+settings.factp(6) = 0.02;                               % Accelerometer biases [m/s^2]
+settings.factp(7) = (0.05*pi/180);                      % Gyro biases [rad/s]                               
+
+      
+end
+
+
+
+
diff --git a/matlab/gps.m b/matlab/gps.m
new file mode 100644
index 0000000000000000000000000000000000000000..32d14cbbc3638794ea0fe6e39e3ec9ef22bbf9b8
--- /dev/null
+++ b/matlab/gps.m
@@ -0,0 +1,163 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% GPS sensor dynamics %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%STATE  is a struct (called sensor) with the following fields
+%  state   -[string]the current proceural state: no_info, cold_start, read_ephemeris, position_available, warm_start_avaialable, warm_start
+%  howLong -[double]when the current procedural state has been entered 
+%  ephExp  -[double]expiration time of ephemeris data
+%  fp      -[int]number of tracked satelliets
+%  eph     -[int]number of satellites for which ephemeris data are available
+
+%INPUTS
+%  -time
+%  -state
+%  -turn on/off (true=turn_ON, false=turn_OFF)
+%  -visible satellites
+
+%OUTPUTS
+%  -state
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function sensor=gps(time,sensor_in,turn,sv)
+
+%% parameters
+%define how many satellites you need to track given the accuracy requirements
+required_sv= 4;
+%define how long ephemeris data last
+ephDuration=1800.0;
+%define how much time is required to read the ephemeris data
+ttge=59.0;
+%define how much time is required to fetch the satellites signal
+ttfs=0.01;
+
+%% initialize output
+sensor = sensor_in;
+
+%% equations
+%you cannot track satellites that you dont see
+sensor.fp=min(sensor_in.fp,sv);
+sensor.eph=min(sensor_in.eph,sv);
+
+%% events
+ephemeris_expired=(time>sensor.ephExp)||(sensor.eph<required_sv);   %ephemeris data are expired
+lost_visibility=(sensor_in.fp~=sensor.fp)&&(sensor.fp<required_sv);
+fetch_fp=(time-sensor_in.howLong)>=ttfs;
+get_ephemeris=(time-sensor_in.howLong)>ttge;
+
+%% transitions and updates
+%for each of the states handle eventual transitions and updates
+%(i)if any transition is fired, always update the time the surrent state was entered
+%(ii)other updates depend on the spefic transition that is fired
+if strcmp(sensor_in.state,'no_info')
+    if(turn)
+        sensor.state='cold_start';
+        sensor.howLong=time;
+    end
+end
+if strcmp(sensor_in.state,'position_available')
+    if(get_ephemeris)
+        sensor.state='position_available';
+        sensor.howLong=time;
+        sensor.eph=sv;
+        sensor.ephExp=time+ephDuration;
+    end
+    if(~turn)
+        sensor.state='warm_start_available';
+        sensor.howLong=time;
+        sensor.fp=0;
+    end
+    if(lost_visibility)
+        sensor.state='warm_start';
+        sensor.howLong=time;
+        %might have to go on to cold_start
+            if(ephemeris_expired)
+                sensor.state='cold_start';
+                sensor.howLong=time;
+                sensor.eph=0;
+            end
+    end
+    if(ephemeris_expired)
+        sensor.state='read_ephemeris';
+        sensor.howLong=time;
+        sensor.eph=0;
+        %might have to go on to cold_start
+            if(lost_visibility)
+                sensor.state='cold_start';
+                sensor.howLong=time;
+            end
+    end
+end
+if strcmp(sensor_in.state,'read_ephemeris')
+    if(get_ephemeris)
+        sensor.state='position_available';
+        sensor.howLong=time;
+        sensor.eph=sv;
+        sensor.ephExp=time+ephDuration;
+    end
+    if(~turn)
+        sensor.state='no_info';
+        sensor.howLong=time;
+        sensor.fp=0;
+    end
+    if(lost_visibility)
+        sensor.state='cold_start';
+        sensor.howLong=time;
+    end
+end
+if strcmp(sensor_in.state,'warm_start')
+    if(lost_visibility)
+        sensor.state='warm_start';
+        sensor.howLong=time;
+    end
+    if(fetch_fp)
+        sensor.state='position_available';
+        sensor.howLong=time;
+        sensor.fp=sv;
+    end
+    if(ephemeris_expired)
+        sensor.state='cold_start';
+        sensor.howLong=time;
+        sensor.eph=0;
+    end
+    if(~turn)
+        sensor.state='warm_start_available';
+        sensor.howLong=time;
+        sensor.fp=0;
+    end
+end
+if strcmp(sensor_in.state,'cold_start')
+    if(fetch_fp)
+        sensor.state='read_ephemeris';
+        sensor.howLong=time;
+        sensor.fp=sv;
+    end
+    if(lost_visibility)
+        sensor.state='cold_start';
+        sensor.howLong=time;
+    end
+    if(~turn)
+        sensor.state='no_info';
+        sensor.howLong=time;
+        sensor.fp=0;
+    end
+end
+if strcmp(sensor_in.state,'warm_start_available')
+    if(turn)
+        sensor.state='warm_start';
+        sensor.howLong=time;
+    end
+    if(ephemeris_expired)
+        sensor.state='no_info';
+        sensor.howLong=time;
+        sensor.eph=0;
+    end
+end
+
+end
+
+
+
+
+
diff --git a/matlab/gravity.m b/matlab/gravity.m
new file mode 100644
index 0000000000000000000000000000000000000000..d403f400a5d2978136617be65365d0da80f36288
--- /dev/null
+++ b/matlab/gravity.m
@@ -0,0 +1,29 @@
+function g=gravity(lambda,h)
+% function g=gravity(lambda,h)
+%
+% function for calculation of the local gravity vector, in
+% the geographic reference frame (same as tangent plane is 
+% stationary).
+%
+% Based upon the WGS_84 Geodetic and Gravity model. For more 
+% info see [pp 222-223,1].
+%
+% lambda -> Latitude [degrees]
+% h -> Altitude [m]
+% g 
+%
+% edit: Isaac Skog, 2006-08-17
+
+% degrees to radians
+lambda=pi/180*lambda;
+
+gamma=9.780327*(1+0.0053024*sin(lambda)^2-0.0000058*sin(2*lambda)^2);
+
+g=gamma-((3.0877e-6)-(0.004e-6)*sin(lambda)^2)*h+(0.072e-12)*h^2;
+
+g=[0 0 -g]';
+return;
+
+
+
+
diff --git a/matlab/main.m b/matlab/main.m
new file mode 100644
index 0000000000000000000000000000000000000000..1308da4dea72e45e08e222a270f731917ad86f05
--- /dev/null
+++ b/matlab/main.m
@@ -0,0 +1,21 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Main script for pAN_ powe aware navigation with sensor fusion 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+%% Load data
+disp('Loads data')
+load('GNSSaidedINS_data.mat');
+
+%% Load filter settings
+disp('Loads settings')
+settings=get_settings();
+
+%% Run the GNSS-aided INS
+disp('Runs the GNSS-aided INS')
+out_data=GPSaidedINS(in_data,settings);
+
+%% Plot the data 
+disp('Plot data')
+plot_data(in_data,out_data,'True');drawnow
+
diff --git a/matlab/plot_data.m b/matlab/plot_data.m
new file mode 100644
index 0000000000000000000000000000000000000000..0a37b18d983ecfb633af1f63640fad07059c7b19
--- /dev/null
+++ b/matlab/plot_data.m
@@ -0,0 +1,144 @@
+function plot_data(in_data,out_data,holdon)
+
+if nargin < 3; holdon = 'False'; end
+    
+h=zeros(1,3);
+figure(2)
+if ~holdon clf; end
+plot(in_data.GNSS.pos_ned(2,:),in_data.GNSS.pos_ned(1,:),'b-');
+hold on
+h(1)=plot(in_data.GNSS.pos_ned(2,:),in_data.GNSS.pos_ned(1,:),'b.');
+h(2)=plot(out_data.x_h(2,:),out_data.x_h(1,:),'r');
+h(3)=plot(in_data.GNSS.pos_ned(2,1),in_data.GNSS.pos_ned(1,1),'ks');
+title('Trajectory')
+ylabel('North [m]')
+xlabel('East [m]')
+legend(h,'GNSS position estimate','GNSS aided INS trajectory','Start point')
+axis equal
+grid on
+
+h=zeros(1,3);
+figure(3)
+if ~holdon clf; end
+h(1)=plot(in_data.GNSS.t,-in_data.GNSS.pos_ned(3,:),'b.');
+hold on
+h(2)=plot(in_data.IMU.t,-out_data.x_h(3,:),'r');
+h(3)=plot(in_data.IMU.t,3*sqrt(out_data.diag_P(3,:))-out_data.x_h(3,:),'k--');
+plot(in_data.IMU.t,-3*sqrt(out_data.diag_P(3,:))-out_data.x_h(3,:),'k--')
+title('Height versus time')
+ylabel('Height [m]')
+xlabel('Time [s]')
+grid on
+legend(h,'GNSS estimate','GNSS aided INS estimate','3\sigma bound')
+
+h=zeros(1,2);
+figure(4)
+if ~holdon clf; end
+h(1)=plot(in_data.IMU.t,sqrt(sum(out_data.x_h(4:6,:).^2)),'r');
+hold on
+sigma=sqrt(sum(out_data.diag_P(4:6,:)));
+speed=sqrt(sum(out_data.x_h(4:6,:).^2));
+h(2)=plot(in_data.IMU.t,3*sigma+speed,'k--');
+plot(in_data.IMU.t,-3*sigma+speed,'k--')
+title('Speed versus time')
+ylabel('Speed [m/s]')
+xlabel('Time [s]')
+grid on
+legend(h,'GNSS aided INS estimate','3\sigma bound')
+
+N=length(in_data.IMU.t);
+attitude=zeros(3,N);
+
+for n=1:N
+    Rb2t=q2dcm(out_data.x_h(7:10,n));
+    
+    %Get the roll, pitch and yaw
+    %roll
+    attitude(1,n)=atan2(Rb2t(3,2),Rb2t(3,3))*180/pi;
+    
+    %pitch
+    attitude(2,n)=-atan(Rb2t(3,1)/sqrt(1-Rb2t(3,1)^2))*180/pi;
+    
+    %yaw
+    attitude(3,n)=atan2(Rb2t(2,1),Rb2t(1,1))*180/pi;
+end
+
+ylabels={'Roll [deg]','Pitch [deg]','Yaw [deg]'};
+figure(5)
+if ~holdon clf; end
+h=zeros(1,2);
+for k=1:3
+    subplot(3,1,k)
+    h(1)=plot(in_data.IMU.t,attitude(k,:),'r');
+    hold on
+    plot(in_data.IMU.t,3*180/pi*sqrt(out_data.diag_P(6+k,:))+attitude(k,:),'k--')
+    h(2)=plot(in_data.IMU.t,-3*180/pi*sqrt(out_data.diag_P(6+k,:))+attitude(k,:),'k--');
+    grid on
+    ylabel(ylabels{k})
+    if k==1
+        title('Attitude versus time')
+    end
+end
+xlabel('Time [s]')
+legend(h,'GNSS aided INS estimate','3\sigma bound')
+
+
+figure(6)
+if ~holdon clf; end
+ylabels={'X-axis bias [m/s^2]','Y-axis bias [m/s^2]','Z-axis bias [m/s^2]'};
+h=zeros(1,2);
+for k=1:3
+    subplot(3,1,k)
+    h(1)=plot(in_data.IMU.t,out_data.delta_u_h(k,:),'r');
+    hold on
+    h(2)=plot(in_data.IMU.t,3*sqrt(out_data.diag_P(9+k,:))+out_data.delta_u_h(k,:),'k--');
+    plot(in_data.IMU.t,-3*sqrt(out_data.diag_P(9+k,:))+out_data.delta_u_h(k,:),'k--')
+    grid on
+    ylabel(ylabels{k})
+    if k==1
+        title('Accelerometer bias estimate versus time')
+    end
+end
+xlabel('Time [s]')
+legend(h,'GNSS aided INS estimate','3\sigma bound')
+
+
+figure(7)
+if ~holdon clf; end
+ylabels={'X-axis bias [deg/s]','Y-axis bias [deg/s]','Z-axis bias [deg/s]'};
+h=zeros(1,2);
+for k=1:3
+    subplot(3,1,k)
+    h(1)=plot(in_data.IMU.t,180/pi*out_data.delta_u_h(3+k,:),'r');
+    hold on
+    h(2)=plot(in_data.IMU.t,3*180/pi*sqrt(out_data.diag_P(12+k,:))+180/pi*out_data.delta_u_h(3+k,:),'k--');
+    plot(in_data.IMU.t,-3*180/pi*sqrt(out_data.diag_P(12+k,:))+180/pi*out_data.delta_u_h(3+k,:),'k--')
+    grid on
+    ylabel(ylabels{k})
+    if k==1
+        title('Gyroscope bias estimate versus time')
+    end
+end
+xlabel('Time [s]')
+legend(h,'GNSS aided INS estimate','3\sigma bound')
+
+figure(8)
+if ~holdon clf; end
+xest = out_data.x_h(2,:);
+yest = out_data.x_h(1,:);
+xgps = interp1(in_data.GNSS.t,in_data.GNSS.pos_ned(2,:),in_data.IMU.t,'linear','extrap')';
+ygps = interp1(in_data.GNSS.t,in_data.GNSS.pos_ned(1,:),in_data.IMU.t,'linear','extrap')';
+xerr = xest - xgps; 
+yerr = yest - ygps;
+plot(in_data.IMU.t,xerr)
+grid on
+hold on
+plot(in_data.IMU.t,yerr)
+xlabel('time [s]')
+ylabel('position difference [m]')
+legend('x', 'y')
+
+positionerr_RMS = sqrt(mean(xerr.^2+yerr.^2))
+figure(2)
+end
+
diff --git a/matlab/q2dcm.m b/matlab/q2dcm.m
new file mode 100644
index 0000000000000000000000000000000000000000..3f36a5d144e27b250e5380a26c5ec79628ef3095
--- /dev/null
+++ b/matlab/q2dcm.m
@@ -0,0 +1,56 @@
+function R=q2dcm(q)
+% function R=q2dcm(q)
+% Function for transformation from quaternions to directional cosine matrix
+% Farell pp.41
+% Edit: Isaac Skog, 2007-05-24
+
+p=zeros(6,1);
+
+p(1:4)=q.^2;
+
+p(5)=p(2)+p(3);
+
+if p(1)+p(4)+p(5)~=0
+   p(6)=2/(p(1)+p(4)+p(5)); 
+else
+   p(6)=0;
+end
+
+R(1,1)=1-p(6)*p(5);
+R(2,2)=1-p(6)*(p(1)+p(3));
+R(3,3)=1-p(6)*(p(1)+p(2));
+
+p(1)=p(6)*q(1); 
+p(2)=p(6)*q(2);
+p(5)=p(6)*q(3)*q(4);
+p(6)=p(1)*q(2);
+
+R(1,2)=p(6)-p(5);
+R(2,1)=p(6)+p(5);
+
+p(5)=p(2)*q(4);
+p(6)=p(1)*q(3);
+
+R(1,3)=p(6)+p(5);
+R(3,1)=p(6)-p(5);
+
+p(5)=p(1)*q(4);
+p(6)=p(2)*q(3);
+
+R(2,3)=p(6)-p(5);
+R(3,2)=p(6)+p(5);
+
+% R(1,2)=2*(q(1)*q(2)-q(3)*q(4));
+% R(1,3)=2*(q(1)*q(3)+q(2)*q(4));
+% 
+% % Row 2
+% R(2,1)=2*(q(1)*q(2)+q(3)*q(4));
+% R(2,2)=q(2)^2+q(4)^2-q(1)^2-q(3)^2;
+% R(2,3)=2*(q(2)*q(3)-q(1)*q(4));
+% 
+% % Row 3
+% R(3,1)=2*(q(1)*q(3)-q(2)*q(4));
+% R(3,2)=2*(q(2)*q(3)+q(1)*q(4));
+% R(3,3)=q(3)^2+q(4)^2-q(1)^2-q(2)^2;
+% 
+% % Okej, men kan f�rb�trras, se pp 41 Farrel
\ No newline at end of file