lib

Dependencies:   mbed ros_lib_indigo

Revision:
0:c94b2f0a4409
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Oct 02 11:30:47 2017 +0000
@@ -0,0 +1,2615 @@
+#include "mbed.h"
+#include "led.h"
+#include "uart_send.h"
+#include <ros.h>
+#include <geometry_msgs/Vector3.h>
+#include <geometry_msgs/Twist.h>
+#include "LSM9DS0_SH.h"
+#include <math.h>
+
+#define r_01 ((double)rand()/(RAND_MAX))           // uniform distribution 0 ~ 1
+#define constrain(amt,low,high) ((amt)<(low) ? (low) : ((amt) > (high) ? (high) : (amt)))
+
+// timer 1 : sensor fusion
+#define LOOPTIME  2000                             // 0.002 s
+unsigned long lastMilli = 0;
+// sampling time
+float T = 0.002;
+
+// timer 2 : publish cmd_vel for mag_cor
+#define LOOPTIME2  100000                          // 0.1 s 
+unsigned long lastMilli2 = 0;
+
+// timer 3 : take part of mag data
+#define LOOPTIME3  300000                          // 0.3 s
+unsigned long lastMilli3 = 0;
+
+// timer 5 : extended kalman filter
+#define LOOPTIME5  20000                           // 0.02 s
+unsigned long lastMilli5 = 0;
+// sampling time
+float T2 = 0.02;
+
+// timer 6 : navigation
+#define LOOPTIME6  100000                          // 0.1 s
+unsigned long lastMilli6 = 0;
+
+Timer t;
+
+ros::NodeHandle nh;
+
+geometry_msgs::Twist vel_msg;
+ros::Publisher p("andbot/cmd_vel", &vel_msg);
+unsigned long current_time = 0;
+unsigned long last_time = 0;
+
+// car information
+double wheelRadius = 0.078;
+double wheelSeparation = 0.393;
+double omega_right = 0.0;
+double omega_left = 0.0;
+double omega_z = 0.0;
+double vel_x = 0.0;
+double th = 0.0;
+int th_deg = 0;
+double x = 0.0;
+double y_ = 0.0;
+
+// start car rotation for magnetometer correction flag
+int check_flag = 0;
+
+// magnetometer correction data
+// magnetometer 1
+float magx[100] = {0};
+float magy[100] = {0};
+int ind = 0;
+int ind_ = 0;
+float cal_flag = 0;
+float magx_max = 0;
+float magx_min = 0;
+float magx0 = 0;
+float magy_max = 0;
+float magy_min = 0;
+float magy0 = 0;
+float a = 0.3324;                 // long axis
+float b = 0.3082;                 // short axis
+
+// magnetometer 2
+float magx2[100] = {0};
+float magy2[100] = {0};
+float magx_max2 = 0;
+float magx_min2 = 0;
+float magx02 = 0;
+float magy_max2 = 0;
+float magy_min2 = 0;
+float magy02 = 0;
+float a2 = 0.3366;                // long axis
+float b2 = 0.3312;                // short axis
+
+// vision data
+int px = 0;
+int py = 0;
+int vision_flag = 0;
+// calibration parameter
+float alpha_u = 179.869823;
+float alpha_v = 179.984858;
+float alpha_s = 0;
+float cx = 81.709410;
+float cy = 64.218079;
+// c : camera coordinate
+float Zc = 420;                  // unit : mm
+float Xc = 0;
+float Yc = 0;
+float Theta_c = 0;
+// r : robot coordinate
+float Xr = 0;
+float Yr = 0;
+// from odometry and cross detection to predict map coordinate
+float Xp = 0;
+float Yp = 0;
+
+// subscribe feedback_wheel_angularVel
+void messageCb(const geometry_msgs::Vector3& msg)
+{
+    Y_ = !Y_;
+
+    omega_left = msg.x;
+    omega_right = msg.y;
+
+    omega_z = wheelRadius * (omega_right - omega_left) / wheelSeparation;
+    vel_x = wheelRadius * (omega_right + omega_left) / 2;
+
+    current_time = t.read_ms();
+    double dt = (current_time - last_time) * 0.001;        // from ms to s
+    last_time = current_time;
+
+    double delta_th = omega_z * dt;
+    th += delta_th;
+    
+    double delta_x = vel_x * cos(th) * dt;
+    x += delta_x;
+    
+    double delta_y = vel_x * sin(th) * dt;
+    y_ += delta_y;
+
+    // for mag_cor
+    if(check_flag == 1) 
+    {
+        if(th >= 2*PI) 
+        {
+            check_flag = 0;
+            cal_flag = 1;
+            vel_msg.angular.z = 0.0;
+            p.publish(&vel_msg);
+            th = 0;
+        }
+    }
+}
+
+ros::Subscriber<geometry_msgs::Vector3> s("feedback_wheel_angularVel",messageCb);
+
+int update_source = 0;
+
+// subscribe point
+void messageCb2(const geometry_msgs::Vector3& pp)
+{
+    px = pp.x;
+    py = pp.y;
+    Theta_c = pp.z;
+
+    if(px != 0 || py != 0 || Theta_c != 0)
+        vision_flag = 1;
+    else
+        vision_flag = 0;
+
+    if(vision_flag == 1 && px > 0 && py > 0) 
+    {
+        // from image plane coordinate to camera coordinate    
+        Xc = (Zc/alpha_u)*(px - cx) - ((alpha_s*Zc)/(alpha_u*alpha_v))*(py - cy);
+        Yc = (Zc/alpha_v)*(py - cy);
+
+        // from camera coordinate to robot coordinate
+        Xr = -Yc + 175;
+        Yr = -Xc - 10;
+
+        // change unit to meter                
+        Xr = Xr * 0.001;
+        Yr = Yr * 0.001;
+        
+        update_source = 1;
+    }
+    else if(vision_flag == 1 && px == 0 && py == 0 && ((Theta_c >= 1 && Theta_c <= 89) || (Theta_c >= -89 && Theta_c <= -1)))
+    {
+        update_source = 2;
+    }
+    else 
+    {
+        Xr = 0;
+        Yr = 0;
+        
+        update_source = 0;
+    }
+}
+
+ros::Subscriber<geometry_msgs::Vector3> s2("point",messageCb2);
+
+void read_sensor(void);
+
+float lpf(float input, float output_old, float frequency);
+
+int sensor_flag = 0;                                 // sensor initial flag
+int sensor_count = 0;
+
+// sensor filter correction data
+float Gyro_axis_data_f[3];
+float Gyro_axis_data_f_old[3];
+float Gyro_scale[3];                                 // scale = (data - zero)
+float Gyro_axis_zero[3] = {0,0,0};                   // x,y no use
+
+// sensor 1 (front)
+float Magn_axis_data_f[3];
+float Magn_axis_data_f_old[3];
+float Magn_scale[3];                                 // scale = (data - zero)
+float Magn_axis_zero[3] = {-0.1049,0.1982,0};
+
+// sensor 2 (back)
+float Magn_axis_data_f2[3];
+float Magn_axis_data_f_old2[3];
+float Magn_scale2[3];                                // scale = (data - zero)
+float Magn_axis_zero2[3] = {0.1547,0.2713,0};
+
+float Bex = 0;
+float Bey = 0;
+float Bex2 = 0;
+float Bey2 = 0;
+float Be = 0.9882;          // Be = ( sqrt(Bex*Bex + Bey*Bey) + sqrt(Bex2*Bex2 + Bey2*Bey2) ) / 2
+
+// counter for gyro bias
+int gyro_count = 0;
+int gyro_flag = 0;
+float gyro_init[10] = {0};
+int index_count = 0;
+float gyro_sum = 0;
+
+// sensor data
+// magn
+float phi = 0;
+float phi2 = 0;
+int phi_init_flag = 0;
+int phi_init_count = 0;
+float phi_init = 0;
+float phi_init2 = 0;
+float phi_m = 0;
+float phi_m2 = 0;
+int phi_m_deg = 0;
+int phi_m2_deg = 0;
+int phi_m_deg_1 = 0;
+int phi_m2_deg_1 = 0;
+int phi_m_deg_2 = 0;
+int phi_m2_deg_2 = 0;
+int phi_m_deg_T = 0;
+int phi_m2_deg_T = 0;
+float phi_m_a = 0;
+float phi_m2_a = 0;
+int phi_m_a_deg = 0;
+int phi_m2_a_deg = 0;
+int diff_phi_count = 0;
+int diff_phi_flag = 0;
+int jump_count = 0;
+int jump_count2 = 0;
+float phi_m_a_avg = 0;
+
+// gyro
+float w_s = 0;
+float w_s_d = 0;
+float theta_s = 0;
+int theta_s_deg = 0;
+
+// fusion data for theta
+float theta_fu = 0;
+float theta_fu_old = 0;
+float bias = 0;
+float bias_old = 0;
+float y = 0;
+float L1 = 0;
+float L2 = 0;
+int fusion_flag = 0;
+
+// theta_fu to ROS
+int theta_fu_deg = 0;
+int theta_fu_deg_180 = 0;
+float theta_fu_PI = 0;
+
+// add bias
+int bias_flag = 0;
+float bias_add = 0;
+
+// magnetic field disturbance detect
+// trust index
+float Q = 0;
+// Kalman filter
+float V = 0;                         // measurement noise variance
+float theta_me = 0;
+int theta_me_deg = 0;
+float theta_me_bar = 0;
+float sigma = 0;
+float sigma_bar = 0;
+float K = 0;                         // gain
+float At = 1;
+float Bt = 0.002;                    // sampling time
+float Ct = 1;
+float Rt = 0.001;                    // process noise variance
+float update_distance = 0;
+float update_rotation = 0;
+int update_flag = 0;
+
+// extended kalman filter for localization
+// EKF variables
+// prediction variables
+float mu_bar[3][1] = {0};
+int mu_bar_deg = 0;
+float mu[3][1] = {0};                // state vector
+float Sigma_bar[3][3] = {0};
+float Sigma[3][3] = { {0 , 0 , 0} , {0 , 0 , 0} , {0 , 0 , 0} };   // estimation covariance matrix
+float Sigma_mul_1[3][3] = {0};
+float Sigma_mul_2[3][3] = {0};
+float G[3][3] = {0};                 // state transition matrix
+float GT[3][3] = {0};                // state transition matrix transport
+float R[3][3] = { {0.000001 , 0 , 0} , {0 , 0.000001 , 0} , {0 , 0 , 0.000007} };       // process noise covariance matrix
+
+// encoder odometry
+float th_enc = 0;
+int th_enc_deg = 0;
+float x_enc = 0;
+float y_enc = 0;
+
+// global cross map variables
+float block_length = 0.39;         // m
+float x_crom[4] = {0};
+float y_crom[4] = {0};
+
+// update variables for cross detection
+float Zcro[2][1] = {0};
+float Zr[4] = {0};
+int Za[4] = {0};
+int Zphi[4] = {0};
+int Zphi_deg_180[4] = {0};
+float Zcro_hat[4][2][1] = {0};
+float Zd[4][2][1] = {0};
+float Pcro[4] = {0};
+float Pcro_max = 0;
+int i_Pcro_max = 0;
+float e_r[4] = {0};          
+float mx_x[4] = {0};
+float my_y[4] = {0};         
+float Zcro_hs[2][1] = {0};
+float Hcro[4][2][3] = {0};
+float Hcros[2][3] = {0};
+float HcroT[4][3][2] = {0};
+float HcroTs[3][2] = {0};
+float Qcro[2][2] = {0};
+float Scro[4][2][2] = {0};
+float det_Scro[4] = {0};
+float Scro_inv[4][2][2] = {0};
+float Scro_is[2][2] = {0};
+float Kcro[3][2] = {0};
+
+float Hcro_1[4][2][3] = {0};
+float Hcro_2[4][2][2] = {0};
+float Zcro_delta[2][1] = {0};
+float Kcro_1[3][2] = {0};
+float Kcro_2[3][1] = {0};
+float Icro_1[3][3] = {0};
+float Icro_2[3][3] = {0};
+
+// update variables for line detection
+float Zli = 0;
+float Zli_hat[4] = {0};
+float Zli_diff[4] = {0};
+float Zli_diff_min = 0;
+int ind_diff_min = 0;
+float Qli = 0.001;
+float Sli = 0;
+float Kli[3][1] = {0};
+
+// update occasion
+int camera_flag = 0;
+int update_state = 0;
+int singular_flag = 0;
+int predict_count = 0;
+int predict_flag = 0;
+float up_dis = 0;
+float up_rot = 0;
+int up_check = 0;
+float up_dis_r = 0.002;
+float up_rot_r = PI/60;
+
+// encoder magnetometer gyro odometry
+float th_emg = 0;
+int th_emg_deg = 0;
+float x_emg = 0;
+float y_emg = 0;
+
+// select update source for debugging
+// 0 for no update , 1 for cross update only , 2 for line update only , 3 for cross and line update together
+int select_ups = 3;
+
+// select prediction model for debugging
+// 0 for encoder magnetometer gyro fusion , 1 for encoder only
+int select_pms = 1;
+
+// navigation
+int mu_th_deg = 0;
+int mu_th_deg_180 = 0;
+float mu_th_PI = 0;
+float Pxd = 0;
+float Pyd = 0;
+float Od = 0;
+float delta_Pxd = 0;
+float delta_Pyd = 0;
+float delta_Od = 0;
+float Kv = 0.55;
+float Kw = 0.55;
+float gain_v = 0;
+float gain_w = 0;
+float error_P = 0;
+float error_O = 0;
+int nav_flag = 0;
+int nav_state = 1;
+float distance_error_P = 0;
+int line_tracker = 0;         
+
+
+int main()
+{
+    t.start();
+
+    nh.initNode();
+
+    nh.subscribe(s);
+    nh.subscribe(s2);
+    nh.advertise(p);
+
+    init_uart();
+
+    init_IMU();
+
+    myled = 1;
+
+    while(1) 
+    {
+        // receive labview data
+        if(uart_1.readable() > 0) 
+        {
+            switch(uart_1.getc()) 
+            {
+                case 'a':
+                    check_flag = 1;
+                    BK_ = 0;             // light
+                break;
+                    
+                case 's':
+                    check_flag = 0;
+                    BK_ = 1;             // dark
+                break;
+                    
+                case 'z':
+                    phi_init_flag = 1;
+                    B_ = 0;
+                break;
+                
+                case 'x':
+                    phi_init_flag = 0;
+                    B_ = 1;
+                break;
+                
+                case 'b':
+                    bias_flag = 1;
+                break;
+                
+                case 'n':
+                    bias_flag = 0;
+                break;    
+                
+                case 'c':
+                    camera_flag = 1;
+                break;
+                    
+                case 'v':
+                    camera_flag = 0;
+                break;
+                
+                case 'h':
+                    select_ups = 0;
+                break;
+                
+                case 'j':
+                    select_ups = 1;
+                break;
+                
+                case 'k':
+                    select_ups = 2;
+                break;
+                
+                case 'l':
+                    select_ups = 3;
+                break;
+                
+                case 'y':
+                    nav_flag = 1;
+                break;
+                
+                case 'u':
+                    nav_flag = 0;
+                break;
+                
+                default:
+                    check_flag = 0;
+                    phi_init_flag = 0;
+                    fusion_flag = 0;
+                    bias_flag = 0;
+                    camera_flag = 0;
+                    select_ups = 0;
+                    nav_flag = 0;
+                break;
+            }
+        }
+
+        // timer 1 : sensor fusion
+        if((t.read_us() - lastMilli) >= LOOPTIME)           // 2000 us = 0.002 s
+        {         
+            //myled = !myled;
+
+            lastMilli = t.read_us();
+
+            // sensor initial start
+            if(sensor_flag == 0) 
+            {
+                sensor_count++;
+
+                if(sensor_count >= 100) 
+                {
+                    sensor_flag  = 1;
+                    sensor_count = 0;
+                }
+            } 
+            else 
+            {
+                read_sensor();
+                
+////////////////// uart send data //////////////////////////////////////////////////////////////////////////////////////////////
+                
+                display[0] = 1 * nav_flag;
+                display[1] = 1 * nav_state;
+                display[2] = 1 * up_check;
+                display[3] = 100 * error_P;
+                display[4] = 57.3 * error_O;
+                display[5] = 100 * distance_error_P;
+                display[6] = 100 * mu[0][0];
+                display[7] = 100 * mu[1][0];
+                display[8] = 57.3 * mu[2][0];
+                display[9] = 100 * x_enc;
+                display[10] = 100 * y_enc;
+                display[11] = 57.3 * th_enc;
+                
+//                display[0] = 1000 * Kcro_2[0][0];
+//                display[1] = 1000 * Kcro_2[1][0];
+//                display[2] = up_check;
+//                display[3] = 100 * Zcro[0][0];
+//                display[4] = 100 * Zcro_hat[i_Pcro_max][0][0];
+//                display[5] = i_Pcro_max;
+//                display[6] = 57.3 * Zcro[1][0];
+//                display[7] = 57.3 * Zcro_hat[i_Pcro_max][1][0];
+//                display[8] = Pcro_max;                
+//                display[9] = 100 * mu[0][0];
+//                display[10] = 100 * mu[1][0];
+//                display[11] = 57.3 * mu[2][0];
+
+//                display[0] = 100 * x_crom[0];
+//                display[1] = 100 * y_crom[0];
+//                display[2] = i_Pcro_max;
+//                display[3] = 100 * x_crom[1];
+//                display[4] = 100 * y_crom[1];
+//                display[5] = Pcro_max;
+//                display[6] = 100 * x_crom[2];
+//                display[7] = 100 * y_crom[2];
+//                display[8] = 100 * Xp;                
+//                display[9] = 100 * x_crom[3];
+//                display[10] = 100 * y_crom[3];
+//                display[11] = 100 * Yp;
+
+//                display[0] = 10000 * Magn_axis_zero[0];
+//                display[1] = 10000 * Magn_axis_zero[1];
+//                display[2] = 10000 * a;
+//                display[3] = 10000 * b;
+//                display[4] = 10000 * Magn_axis_zero2[0];
+//                display[5] = 10000 * Magn_axis_zero2[1];
+//                display[6] = 10000 * a2;
+//                display[7] = 10000 * b2;
+//                display[8] = 10000 * Be;
+//                display[9] = 100 * Xr;
+//                display[10] = 100 * Yr;
+//                display[11] = 57.3 * th_enc;
+                
+//                display[0] = 57.3 * phi_m_a;
+//                display[1] = 57.3 * phi_m2_a;
+//                display[2] = 57.3 * (0.5*phi_m_a + 0.5*phi_m2_a);
+//                display[3] = 57.3 * theta_fu;
+//                display[4] = 57.3 * theta_s;
+//                display[5] = 10000 * Q;
+//                display[6] = 57.3 * theta_me;
+//                display[7] = 57.3 * th_enc;
+//                display[8] = 57.3 * phi_m_a_avg;
+//                display[9] = 0;
+//                display[10] = 0;
+//                display[11] = 0;
+                
+////////////////// uart send data //////////////////////////////////////////////////////////////////////////////////////////////
+                
+                uart_send(display);
+            }
+        }
+
+        nh.spinOnce();
+
+        // timer 2 : publish cmd_vel for mag_cor
+        if((t.read_us() - lastMilli2) >= LOOPTIME2)         // 100000 us = 0.1 s
+        {       
+            lastMilli2 = t.read_us();
+
+            if(check_flag == 1) 
+            {
+                vel_msg.angular.z = 0.35;
+                p.publish(&vel_msg);
+            }
+        }
+
+        // timer 3 : take part of mag data
+        if((t.read_us() - lastMilli3) >= LOOPTIME3)         // 300000 us = 0.3 s
+        {       
+            lastMilli3 = t.read_us();
+
+            if(check_flag == 1) 
+            {
+                if(th >= PI/12)         // after magn data stable then take data
+                {       
+                    magx[ind] = Magn_axis_data_f[0];
+                    magy[ind] = Magn_axis_data_f[1];
+
+                    magx2[ind] = Magn_axis_data_f2[0];
+                    magy2[ind] = Magn_axis_data_f2[1];
+
+                    ind++;
+                    if(ind >= 100)
+                        ind = 0;
+
+                    ind_ = ind - 1;    // send data index
+                }
+            }
+        }
+
+////////// timer 5 : extended kalman filter ////////////////////////////////////////////////////////////////////////////////////
+
+        if((t.read_us() - lastMilli5) >= LOOPTIME5)         // 20000 us = 0.02 s
+        {
+            myled = !myled;
+                   
+            lastMilli5 = t.read_us();
+
+            if(fusion_flag == 1) 
+            {
+                // extended kalman filter for robot localization
+                
+                // *** Prediction Start *************************************************************** //
+                
+                // encoder odometry
+                th_enc = th_enc + omega_z*T2;
+                x_enc = x_enc + vel_x*cos(th_enc)*T2;
+                y_enc = y_enc + vel_x*sin(th_enc)*T2;
+                
+                // th_enc_deg range 0~359 deg
+                th_enc_deg = th_enc * 180/PI;
+
+                if(th_enc_deg < 0)
+                    th_enc_deg = th_enc_deg % 360 + 360;
+                else
+                    th_enc_deg = th_enc_deg % 360;
+                    
+                // encoder magnetometer gyro odometry
+                th_emg = theta_fu;
+                x_emg = x_emg + vel_x*cos(th_emg)*T2;
+                y_emg = y_emg + vel_x*sin(th_emg)*T2;
+                
+                // th_emg_deg range 0~359 deg
+                th_emg_deg = th_emg * 180/PI;
+
+                if(th_emg_deg < 0)
+                    th_emg_deg = th_emg_deg % 360 + 360;
+                else
+                    th_emg_deg = th_emg_deg % 360;
+                    
+                // update distance and rotation angle
+                up_dis = up_dis + T2*vel_x;
+                up_rot = up_rot + T2*omega_z;
+                
+                // mu_bar = g(u,mu)
+                switch(select_pms) 
+                {
+                    // 0 for encoder magnetometer gyro fusion
+                    case 0:
+                        mu_bar[0][0] = mu[0][0] + vel_x*cos(mu[2][0])*T2;         
+                        mu_bar[1][0] = mu[1][0] + vel_x*sin(mu[2][0])*T2;
+                        mu_bar[2][0] = theta_fu;
+                
+                        mu_bar_deg = theta_fu_deg;
+                    break;
+    
+                    // 1 for encoder only
+                    case 1:                
+                        mu_bar[0][0] = mu[0][0] + vel_x*cos(mu[2][0])*T2;         
+                        mu_bar[1][0] = mu[1][0] + vel_x*sin(mu[2][0])*T2;
+                        mu_bar[2][0] = mu[2][0] + omega_z*T2;
+                
+                        // mu_bar_deg range 0~359 deg
+                        mu_bar_deg = mu_bar[2][0] * 180/PI;
+
+                        if(mu_bar_deg < 0)
+                            mu_bar_deg = mu_bar_deg % 360 + 360;
+                        else
+                            mu_bar_deg = mu_bar_deg % 360;
+                    break;
+                }                
+                
+                // covariance prediction accumulation timing
+                if(vel_x != 0 || omega_z != 0)
+                {
+                    predict_count++;
+                }
+                
+                if(predict_count >= 25)
+                {
+                    predict_flag = 1;
+                    
+                    predict_count = 0;
+                }
+
+                if(predict_flag == 1)
+                {
+                    // Sigma_bar = G*Sigma*G^T + R
+                    G[0][0] = 1;
+                    G[1][1] = 1;
+                    G[2][2] = 1;
+                    G[0][2] = -vel_x*sin(mu[2][0])*T2;
+                    G[1][2] = vel_x*cos(mu[2][0])*T2;
+                
+                    // get GT
+                    GT[0][0] = 1;
+                    GT[1][1] = 1;
+                    GT[2][2] = 1;
+                    GT[2][0] = G[0][2];
+                    GT[2][1] = G[1][2];
+                
+                    // G*Sigma = Sigma_mul_1
+                    Sigma_mul_1[0][0] = G[0][0]*Sigma[0][0] + G[0][1]*Sigma[1][0] + G[0][2]*Sigma[2][0];
+                    Sigma_mul_1[0][1] = G[0][0]*Sigma[0][1] + G[0][1]*Sigma[1][1] + G[0][2]*Sigma[2][1];
+                    Sigma_mul_1[0][2] = G[0][0]*Sigma[0][2] + G[0][1]*Sigma[1][2] + G[0][2]*Sigma[2][2];
+                    Sigma_mul_1[1][0] = G[1][0]*Sigma[0][0] + G[1][1]*Sigma[1][0] + G[1][2]*Sigma[2][0];
+                    Sigma_mul_1[1][1] = G[1][0]*Sigma[0][1] + G[1][1]*Sigma[1][1] + G[1][2]*Sigma[2][1];
+                    Sigma_mul_1[1][2] = G[1][0]*Sigma[0][2] + G[1][1]*Sigma[1][2] + G[1][2]*Sigma[2][2];
+                    Sigma_mul_1[2][0] = G[2][0]*Sigma[0][0] + G[2][1]*Sigma[1][0] + G[2][2]*Sigma[2][0];
+                    Sigma_mul_1[2][1] = G[2][0]*Sigma[0][1] + G[2][1]*Sigma[1][1] + G[2][2]*Sigma[2][1];
+                    Sigma_mul_1[2][2] = G[2][0]*Sigma[0][2] + G[2][1]*Sigma[1][2] + G[2][2]*Sigma[2][2];
+                
+                    // G*Sigma * GT = Sigma_mul_1 * GT = Sigma_mul_2
+                    Sigma_mul_2[0][0] = Sigma_mul_1[0][0]*GT[0][0] + Sigma_mul_1[0][1]*GT[1][0] + Sigma_mul_1[0][2]*GT[2][0];
+                    Sigma_mul_2[0][1] = Sigma_mul_1[0][0]*GT[0][1] + Sigma_mul_1[0][1]*GT[1][1] + Sigma_mul_1[0][2]*GT[2][1];
+                    Sigma_mul_2[0][2] = Sigma_mul_1[0][0]*GT[0][2] + Sigma_mul_1[0][1]*GT[1][2] + Sigma_mul_1[0][2]*GT[2][2];
+                    Sigma_mul_2[1][0] = Sigma_mul_1[1][0]*GT[0][0] + Sigma_mul_1[1][1]*GT[1][0] + Sigma_mul_1[1][2]*GT[2][0];
+                    Sigma_mul_2[1][1] = Sigma_mul_1[1][0]*GT[0][1] + Sigma_mul_1[1][1]*GT[1][1] + Sigma_mul_1[1][2]*GT[2][1];
+                    Sigma_mul_2[1][2] = Sigma_mul_1[1][0]*GT[0][2] + Sigma_mul_1[1][1]*GT[1][2] + Sigma_mul_1[1][2]*GT[2][2];
+                    Sigma_mul_2[2][0] = Sigma_mul_1[2][0]*GT[0][0] + Sigma_mul_1[2][1]*GT[1][0] + Sigma_mul_1[2][2]*GT[2][0];
+                    Sigma_mul_2[2][1] = Sigma_mul_1[2][0]*GT[0][1] + Sigma_mul_1[2][1]*GT[1][1] + Sigma_mul_1[2][2]*GT[2][1];
+                    Sigma_mul_2[2][2] = Sigma_mul_1[2][0]*GT[0][2] + Sigma_mul_1[2][1]*GT[1][2] + Sigma_mul_1[2][2]*GT[2][2];
+                
+                    // G*Sigma*GT + R = Sigma_mul_2 + R = Sigma_bar
+                    Sigma_bar[0][0] = Sigma_mul_2[0][0] + R[0][0];
+                    Sigma_bar[0][1] = Sigma_mul_2[0][1] + R[0][1];
+                    Sigma_bar[0][2] = Sigma_mul_2[0][2] + R[0][2];
+                    Sigma_bar[1][0] = Sigma_mul_2[1][0] + R[1][0];
+                    Sigma_bar[1][1] = Sigma_mul_2[1][1] + R[1][1];
+                    Sigma_bar[1][2] = Sigma_mul_2[1][2] + R[1][2];
+                    Sigma_bar[2][0] = Sigma_mul_2[2][0] + R[2][0];
+                    Sigma_bar[2][1] = Sigma_mul_2[2][1] + R[2][1];
+                    Sigma_bar[2][2] = Sigma_mul_2[2][2] + R[2][2];
+                    
+                    predict_flag = 0;
+                }
+                
+                // *** Prediction End ***************************************************************** //
+
+                // *** Update Start ******************************************************************* //
+                
+                if(vision_flag == 1 && camera_flag == 1)
+                {
+                    if(update_source == 1 && singular_flag == 0)                // cross detection
+                    {
+                        // global cross map
+                        Xp = mu_bar[0][0] + cos(mu_bar[2][0])*Xr - sin(mu_bar[2][0])*Yr;
+                        Yp = mu_bar[1][0] + sin(mu_bar[2][0])*Xr + cos(mu_bar[2][0])*Yr;
+        
+                        if(Xp >= 0 && Yp >= 0)
+                        {
+                            // left down (0,0)
+                            x_crom[0] = ((int)(Xp/block_length) + 0) * block_length;
+                            y_crom[0] = ((int)(Yp/block_length) + 0) * block_length;
+                            // right down (1,0)
+                            x_crom[1] = ((int)(Xp/block_length) + 1) * block_length;
+                            y_crom[1] = ((int)(Yp/block_length) + 0) * block_length;
+                            // right up (1,1)
+                            x_crom[2] = ((int)(Xp/block_length) + 1) * block_length;
+                            y_crom[2] = ((int)(Yp/block_length) + 1) * block_length;
+                            // left up (0,1)
+                            x_crom[3] = ((int)(Xp/block_length) + 0) * block_length;
+                            y_crom[3] = ((int)(Yp/block_length) + 1) * block_length;
+                        }
+                        else if(Xp < 0 && Yp >= 0)
+                        {
+                            // left down (-1,0)
+                            x_crom[0] = ((int)(Xp/block_length) - 1) * block_length;
+                            y_crom[0] = ((int)(Yp/block_length) + 0) * block_length;
+                            // right down (0,0)
+                            x_crom[1] = ((int)(Xp/block_length) + 0) * block_length;
+                            y_crom[1] = ((int)(Yp/block_length) + 0) * block_length;
+                            // right up (0,1)
+                            x_crom[2] = ((int)(Xp/block_length) + 0) * block_length;
+                            y_crom[2] = ((int)(Yp/block_length) + 1) * block_length;
+                            // left up (-1,1)
+                            x_crom[3] = ((int)(Xp/block_length) - 1) * block_length;
+                            y_crom[3] = ((int)(Yp/block_length) + 1) * block_length;
+                        }
+                        else if(Xp < 0 && Yp < 0)
+                        {
+                            // left down (-1,-1)
+                            x_crom[0] = ((int)(Xp/block_length) - 1) * block_length;
+                            y_crom[0] = ((int)(Yp/block_length) - 1) * block_length;
+                            // right down (0,-1)
+                            x_crom[1] = ((int)(Xp/block_length) + 0) * block_length;
+                            y_crom[1] = ((int)(Yp/block_length) - 1) * block_length;
+                            // right up (0,0)
+                            x_crom[2] = ((int)(Xp/block_length) + 0) * block_length;
+                            y_crom[2] = ((int)(Yp/block_length) + 0) * block_length;
+                            // left up (-1,0)
+                            x_crom[3] = ((int)(Xp/block_length) - 1) * block_length;
+                            y_crom[3] = ((int)(Yp/block_length) + 0) * block_length;
+                        }
+                        else if(Xp >= 0 && Yp < 0)
+                        {
+                            // left down (0,-1)
+                            x_crom[0] = ((int)(Xp/block_length) + 0) * block_length;
+                            y_crom[0] = ((int)(Yp/block_length) - 1) * block_length;
+                            // right down (1,-1)
+                            x_crom[1] = ((int)(Xp/block_length) + 1) * block_length;
+                            y_crom[1] = ((int)(Yp/block_length) - 1) * block_length;
+                            // right up (1,0)
+                            x_crom[2] = ((int)(Xp/block_length) + 1) * block_length;
+                            y_crom[2] = ((int)(Yp/block_length) + 0) * block_length;
+                            // left up (0,0)
+                            x_crom[3] = ((int)(Xp/block_length) + 0) * block_length;
+                            y_crom[3] = ((int)(Yp/block_length) + 0) * block_length;
+                        }
+                        
+                        // cross relative distance measurement , polar coordinates : (Zcro[0][0] , Zcro[1][0])
+                        Zcro[0][0] = sqrt(pow(Xr,2) + pow(Yr,2));
+                        Zcro[1][0] = atan2(Yr,Xr);
+                        
+                        // cross relative distance prediction , polar coordinates : (Zr[i] , Zphi[i])                        
+                        for(int i = 0 ; i < 4 ; i++)
+                        {
+                            Zr[i] = sqrt(pow((x_crom[i] - mu_bar[0][0]),2) + pow((y_crom[i] - mu_bar[1][0]),2));
+                                    
+                            Za[i] = atan2((y_crom[i] - mu_bar[1][0]),(x_crom[i] - mu_bar[0][0])) * 180/PI;
+                                    
+                            // Za[i] range 0~359 deg
+                            if(Za[i] < 0)
+                                Za[i] = Za[i] % 360 + 360;
+                            else
+                                Za[i] = Za[i] % 360;
+                                        
+                            Zphi[i] = Za[i] - mu_bar_deg;
+                                    
+                            // Zphi[i] range 0~359 deg
+                            if(Zphi[i] < 0)
+                                Zphi[i] = Zphi[i] % 360 + 360;
+                            else
+                                Zphi[i] = Zphi[i] % 360;
+                            
+                            // Zphi_deg_180[i] range -179~180 deg
+                            if(Zphi[i] > 180)
+                                Zphi_deg_180[i] = Zphi[i] - 360;
+                            else
+                                Zphi_deg_180[i] = Zphi[i];
+                            
+                            Zcro_hat[i][0][0] = Zr[i];
+                            Zcro_hat[i][1][0] = Zphi_deg_180[i] * PI/180;
+                        }
+                        
+                        // cross measurement likelihood
+                        for(int i = 0 ; i < 4 ; i++)
+                        {
+                            // measurement transition matrix element            
+                            if(Zr[i] != 0)
+                            {
+                                e_r[i] = 1 / Zr[i];
+                                            
+                                singular_flag = 0;
+                            }
+                            else
+                            {
+                                singular_flag = 1;
+                            }
+                                            
+                            mx_x[i] = x_crom[i] - mu_bar[0][0];
+                            my_y[i] = y_crom[i] - mu_bar[1][0];
+                                
+                            Hcro[i][0][0] = -mx_x[i] * e_r[i];
+                            Hcro[i][1][0] = my_y[i] * pow(e_r[i],2);
+                            Hcro[i][0][1] = -my_y[i] * e_r[i];
+                            Hcro[i][1][1] = -mx_x[i] * pow(e_r[i],2);
+                            Hcro[i][0][2] = 0;
+                            Hcro[i][1][2] = -1;
+                                
+                            // get HcroT
+                            HcroT[i][0][0] = Hcro[i][0][0];
+                            HcroT[i][1][0] = Hcro[i][0][1];
+                            HcroT[i][2][0] = Hcro[i][0][2];
+                            HcroT[i][0][1] = Hcro[i][1][0];
+                            HcroT[i][1][1] = Hcro[i][1][1];
+                            HcroT[i][2][1] = Hcro[i][1][2];
+                                
+                            // H*Sigma_bar = Hcro_1
+                            Hcro_1[i][0][0] = Hcro[i][0][0]*Sigma_bar[0][0] + Hcro[i][0][1]*Sigma_bar[1][0] + Hcro[i][0][2]*Sigma_bar[2][0];
+                            Hcro_1[i][0][1] = Hcro[i][0][0]*Sigma_bar[0][1] + Hcro[i][0][1]*Sigma_bar[1][1] + Hcro[i][0][2]*Sigma_bar[2][1];
+                            Hcro_1[i][0][2] = Hcro[i][0][0]*Sigma_bar[0][2] + Hcro[i][0][1]*Sigma_bar[1][2] + Hcro[i][0][2]*Sigma_bar[2][2];
+                            Hcro_1[i][1][0] = Hcro[i][1][0]*Sigma_bar[0][0] + Hcro[i][1][1]*Sigma_bar[1][0] + Hcro[i][1][2]*Sigma_bar[2][0];
+                            Hcro_1[i][1][1] = Hcro[i][1][0]*Sigma_bar[0][1] + Hcro[i][1][1]*Sigma_bar[1][1] + Hcro[i][1][2]*Sigma_bar[2][1];
+                            Hcro_1[i][1][2] = Hcro[i][1][0]*Sigma_bar[0][2] + Hcro[i][1][1]*Sigma_bar[1][2] + Hcro[i][1][2]*Sigma_bar[2][2];
+                                
+                            // H*Sigma_bar * HT = Hcro_1 * HT = Hcro_2
+                            Hcro_2[i][0][0] = Hcro_1[i][0][0]*HcroT[i][0][0] + Hcro_1[i][0][1]*HcroT[i][1][0] + Hcro_1[i][0][2]*HcroT[i][2][0];
+                            Hcro_2[i][0][1] = Hcro_1[i][0][0]*HcroT[i][0][1] + Hcro_1[i][0][1]*HcroT[i][1][1] + Hcro_1[i][0][2]*HcroT[i][2][1];
+                            Hcro_2[i][1][0] = Hcro_1[i][1][0]*HcroT[i][0][0] + Hcro_1[i][1][1]*HcroT[i][1][0] + Hcro_1[i][1][2]*HcroT[i][2][0];
+                            Hcro_2[i][1][1] = Hcro_1[i][1][0]*HcroT[i][0][1] + Hcro_1[i][1][1]*HcroT[i][1][1] + Hcro_1[i][1][2]*HcroT[i][2][1];
+                            
+                            Qcro[0][0] = 0.0001;
+                            Qcro[1][1] = 0.001;
+                                
+                            // H*Sigma_bar*HT + Q = Hcro_2 + Q = Scro
+                            Scro[i][0][0] = Hcro_2[i][0][0] + Qcro[0][0];
+                            Scro[i][0][1] = Hcro_2[i][0][1] + Qcro[0][1];
+                            Scro[i][1][0] = Hcro_2[i][1][0] + Qcro[1][0];
+                            Scro[i][1][1] = Hcro_2[i][1][1] + Qcro[1][1];
+                                
+                            det_Scro[i] = Scro[i][0][0]*Scro[i][1][1] - Scro[i][0][1]*Scro[i][1][0];
+                                        
+                            if(det_Scro[i] != 0)
+                            {
+                                Scro_inv[i][0][0] = Scro[i][1][1] / det_Scro[i];
+                                Scro_inv[i][0][1] = -Scro[i][0][1] / det_Scro[i];
+                                Scro_inv[i][1][0] = -Scro[i][1][0] / det_Scro[i];
+                                Scro_inv[i][1][1] = Scro[i][0][0] / det_Scro[i];
+                                            
+                                singular_flag = 0;
+                            }
+                            else
+                            {
+                                singular_flag = 1;
+                            }
+                            
+                            // measurement difference
+                            Zd[i][0][0] = Zcro[0][0] - Zcro_hat[i][0][0];
+                            Zd[i][1][0] = Zcro[1][0] - Zcro_hat[i][1][0];
+                                    
+                            // measurement likelihood
+                            Pcro[i] = (1/sqrt(4*PI*PI*det_Scro[i]))*exp(-0.5*((Zd[i][0][0]*Scro_inv[i][0][0]+Zd[i][1][0]*Scro_inv[i][1][0])*Zd[i][0][0]+(Zd[i][0][0]*Scro[i][0][1]+Zd[i][1][0]*Scro_inv[i][1][1])*Zd[i][1][0]));
+                        }
+                        
+                        // find the maximum likelihood and index
+                        Pcro_max = Pcro[0];
+                        i_Pcro_max = 0;
+                                
+                        for(int j = 1 ; j < 4 ; j++)
+                        {
+                            if(Pcro[j] > Pcro_max)
+                            {
+                                Pcro_max = Pcro[j];
+                                i_Pcro_max = j;
+                            } 
+                        }
+                        
+                        // Z_hat select
+                        Zcro_hs[0][0] = Zcro_hat[i_Pcro_max][0][0];
+                        Zcro_hs[1][0] = Zcro_hat[i_Pcro_max][1][0];
+                            
+                        // H select
+                        Hcros[0][0] = Hcro[i_Pcro_max][0][0];
+                        Hcros[0][1] = Hcro[i_Pcro_max][0][1];
+                        Hcros[0][2] = Hcro[i_Pcro_max][0][2];
+                        Hcros[1][0] = Hcro[i_Pcro_max][1][0];
+                        Hcros[1][1] = Hcro[i_Pcro_max][1][1];
+                        Hcros[1][2] = Hcro[i_Pcro_max][1][2];
+                            
+                        // HT select
+                        HcroTs[0][0] = HcroT[i_Pcro_max][0][0];
+                        HcroTs[0][1] = HcroT[i_Pcro_max][0][1];
+                        HcroTs[1][0] = HcroT[i_Pcro_max][1][0];
+                        HcroTs[1][1] = HcroT[i_Pcro_max][1][1];
+                        HcroTs[2][0] = HcroT[i_Pcro_max][2][0];
+                        HcroTs[2][1] = HcroT[i_Pcro_max][2][1];
+                            
+                        // S^-1 select
+                        Scro_is[0][0] = Scro_inv[i_Pcro_max][0][0];
+                        Scro_is[0][1] = Scro_inv[i_Pcro_max][0][1];
+                        Scro_is[1][0] = Scro_inv[i_Pcro_max][1][0];
+                        Scro_is[1][1] = Scro_inv[i_Pcro_max][1][1];
+                            
+                        // get (Z-Z_hat)
+                        Zcro_delta[0][0] = Zcro[0][0] - Zcro_hs[0][0];
+                        Zcro_delta[1][0] = Zcro[1][0] - Zcro_hs[1][0];
+                            
+                        // Sigma_bar*HT = Kcro_1     
+                        Kcro_1[0][0] = Sigma_bar[0][0]*HcroTs[0][0] + Sigma_bar[0][1]*HcroTs[1][0] + Sigma_bar[0][2]*HcroTs[2][0];
+                        Kcro_1[0][1] = Sigma_bar[0][0]*HcroTs[0][1] + Sigma_bar[0][1]*HcroTs[1][1] + Sigma_bar[0][2]*HcroTs[2][1];
+                        Kcro_1[1][0] = Sigma_bar[1][0]*HcroTs[0][0] + Sigma_bar[1][1]*HcroTs[1][0] + Sigma_bar[1][2]*HcroTs[2][0];
+                        Kcro_1[1][1] = Sigma_bar[1][0]*HcroTs[0][1] + Sigma_bar[1][1]*HcroTs[1][1] + Sigma_bar[1][2]*HcroTs[2][1];
+                        Kcro_1[2][0] = Sigma_bar[2][0]*HcroTs[0][0] + Sigma_bar[2][1]*HcroTs[1][0] + Sigma_bar[2][2]*HcroTs[2][0];
+                        Kcro_1[2][1] = Sigma_bar[2][0]*HcroTs[0][1] + Sigma_bar[2][1]*HcroTs[1][1] + Sigma_bar[2][2]*HcroTs[2][1];
+                            
+                        // Sigma_bar*HT * S^-1 = Kcro_1 * S^-1 = Kcro          
+                        Kcro[0][0] = Kcro_1[0][0]*Scro_is[0][0] + Kcro_1[0][1]*Scro_is[1][0];
+                        Kcro[0][1] = Kcro_1[0][0]*Scro_is[0][1] + Kcro_1[0][1]*Scro_is[1][1];
+                        Kcro[1][0] = Kcro_1[1][0]*Scro_is[0][0] + Kcro_1[1][1]*Scro_is[1][0];
+                        Kcro[1][1] = Kcro_1[1][0]*Scro_is[0][1] + Kcro_1[1][1]*Scro_is[1][1];
+                        Kcro[2][0] = Kcro_1[2][0]*Scro_is[0][0] + Kcro_1[2][1]*Scro_is[1][0];
+                        Kcro[2][1] = Kcro_1[2][0]*Scro_is[0][1] + Kcro_1[2][1]*Scro_is[1][1];
+                            
+                        // K*(Z-Z_hat) = Kcro_2
+                        Kcro_2[0][0] = Kcro[0][0]*Zcro_delta[0][0] + Kcro[0][1]*Zcro_delta[1][0];
+                        Kcro_2[1][0] = Kcro[1][0]*Zcro_delta[0][0] + Kcro[1][1]*Zcro_delta[1][0];
+                        Kcro_2[2][0] = Kcro[2][0]*Zcro_delta[0][0] + Kcro[2][1]*Zcro_delta[1][0];
+                            
+                        // K*H = Icro_1
+                        Icro_1[0][0] = Kcro[0][0]*Hcros[0][0] + Kcro[0][1]*Hcros[1][0];
+                        Icro_1[0][1] = Kcro[0][0]*Hcros[0][1] + Kcro[0][1]*Hcros[1][1];
+                        Icro_1[0][2] = Kcro[0][0]*Hcros[0][2] + Kcro[0][1]*Hcros[1][2];
+                        Icro_1[1][0] = Kcro[1][0]*Hcros[0][0] + Kcro[1][1]*Hcros[1][0];
+                        Icro_1[1][1] = Kcro[1][0]*Hcros[0][1] + Kcro[1][1]*Hcros[1][1];
+                        Icro_1[1][2] = Kcro[1][0]*Hcros[0][2] + Kcro[1][1]*Hcros[1][2];
+                        Icro_1[2][0] = Kcro[2][0]*Hcros[0][0] + Kcro[2][1]*Hcros[1][0];
+                        Icro_1[2][1] = Kcro[2][0]*Hcros[0][1] + Kcro[2][1]*Hcros[1][1];
+                        Icro_1[2][2] = Kcro[2][0]*Hcros[0][2] + Kcro[2][1]*Hcros[1][2];
+                            
+                        // (I - K*H) = (I - Icro_1) = Icro_2
+                        Icro_2[0][0] = 1 - Icro_1[0][0];
+                        Icro_2[0][1] = 0 - Icro_1[0][1];
+                        Icro_2[0][2] = 0 - Icro_1[0][2];
+                        Icro_2[1][0] = 0 - Icro_1[1][0];
+                        Icro_2[1][1] = 1 - Icro_1[1][1];
+                        Icro_2[1][2] = 0 - Icro_1[1][2];
+                        Icro_2[2][0] = 0 - Icro_1[2][0];
+                        Icro_2[2][1] = 0 - Icro_1[2][1];
+                        Icro_2[2][2] = 1 - Icro_1[2][2];
+                            
+                        update_state = 1;                   
+                    }
+                    // if(update_source == 1) end
+                    else if(update_source == 2)                                 // line detection
+                    {
+                        // line angle measurement
+                        Zli = Theta_c;
+                        
+                        // measurement prediction covariance                        
+                        Sli = Sigma_bar[2][2] + Qli;
+                        
+                        // measurement likelihood (simplified method)
+                        Zli_hat[0] = mu_bar_deg - 90;
+                        Zli_hat[1] = mu_bar_deg - 180;
+                        Zli_hat[2] = mu_bar_deg - 270;
+                        Zli_hat[3] = mu_bar_deg - 360;
+                        if(Zli_hat[3] < -270)
+                            Zli_hat[3] = Zli_hat[3] + 360;
+                                    
+                        // measurement difference square
+                        Zli_diff[0] = (Zli - Zli_hat[0]) * (Zli - Zli_hat[0]);
+                        Zli_diff[1] = (Zli - Zli_hat[1]) * (Zli - Zli_hat[1]);
+                        Zli_diff[2] = (Zli - Zli_hat[2]) * (Zli - Zli_hat[2]);
+                        Zli_diff[3] = (Zli - Zli_hat[3]) * (Zli - Zli_hat[3]);
+                                
+                        // find the minimum measurement difference square and index
+                        Zli_diff_min = Zli_diff[0];
+                        ind_diff_min = 0;
+                                    
+                        for(int j = 1 ; j < 4 ; j++)
+                        {
+                            if(Zli_diff[j] < Zli_diff_min)
+                            {
+                                Zli_diff_min = Zli_diff[j];
+                                ind_diff_min = j;
+                            } 
+                        }
+                        
+                        if(Zli_diff_min <= 150)
+                        {
+                            // Kli = Sigma_bar * HT * S^-1
+                            Kli[2][0] = Sigma_bar[2][2] / Sli;
+                            
+                            update_state = 2;
+                        }
+                        else
+                        {
+                            update_state = 0;
+                        }
+                    }
+                    // else if(update_source == 2) end
+                    else
+                    {
+                        update_state = 0;
+                    }
+                }
+                
+                // *** Update End ********************************************************************* //
+                
+                if(up_dis >= up_dis_r) 
+                {
+                    // update
+                    if(update_state == 1) 
+                    {
+                        switch(select_ups) 
+                        {
+                            // 0 for no update
+                            case 0:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;                   
+                            break;
+                            
+                            // 1 for cross update only
+                            case 1:                
+                                // mu_bar + K*(Z-Z_hat) = mu
+                                mu_bar[0][0] = mu_bar[0][0] + Kcro_2[0][0];
+                                mu_bar[1][0] = mu_bar[1][0] + Kcro_2[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kcro_2[2][0];
+                                
+                                // (I - K*H) * Sigma_bar = Icro_2 * Sigma_bar = Sigma
+                                Sigma_bar[0][0] = Icro_2[0][0]*Sigma_bar[0][0] + Icro_2[0][1]*Sigma_bar[1][0] + Icro_2[0][2]*Sigma_bar[2][0];
+                                Sigma_bar[0][1] = Icro_2[0][0]*Sigma_bar[0][1] + Icro_2[0][1]*Sigma_bar[1][1] + Icro_2[0][2]*Sigma_bar[2][1];
+                                Sigma_bar[0][2] = Icro_2[0][0]*Sigma_bar[0][2] + Icro_2[0][1]*Sigma_bar[1][2] + Icro_2[0][2]*Sigma_bar[2][2];
+                                Sigma_bar[1][0] = Icro_2[1][0]*Sigma_bar[0][0] + Icro_2[1][1]*Sigma_bar[1][0] + Icro_2[1][2]*Sigma_bar[2][0];
+                                Sigma_bar[1][1] = Icro_2[1][0]*Sigma_bar[0][1] + Icro_2[1][1]*Sigma_bar[1][1] + Icro_2[1][2]*Sigma_bar[2][1];
+                                Sigma_bar[1][2] = Icro_2[1][0]*Sigma_bar[0][2] + Icro_2[1][1]*Sigma_bar[1][2] + Icro_2[1][2]*Sigma_bar[2][2];
+                                Sigma_bar[2][0] = Icro_2[2][0]*Sigma_bar[0][0] + Icro_2[2][1]*Sigma_bar[1][0] + Icro_2[2][2]*Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Icro_2[2][0]*Sigma_bar[0][1] + Icro_2[2][1]*Sigma_bar[1][1] + Icro_2[2][2]*Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Icro_2[2][0]*Sigma_bar[0][2] + Icro_2[2][1]*Sigma_bar[1][2] + Icro_2[2][2]*Sigma_bar[2][2];
+                                
+                                up_check = 1;
+                            break;
+                            
+                            // 2 for line update only
+                            case 2:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;
+                            break;
+                            
+                            // 3 for cross and line update together
+                            case 3:
+                                // mu_bar + K*(Z-Z_hat) = mu
+                                mu_bar[0][0] = mu_bar[0][0] + Kcro_2[0][0];
+                                mu_bar[1][0] = mu_bar[1][0] + Kcro_2[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kcro_2[2][0];
+                                
+                                // (I - K*H) * Sigma_bar = Icro_2 * Sigma_bar = Sigma
+                                Sigma_bar[0][0] = Icro_2[0][0]*Sigma_bar[0][0] + Icro_2[0][1]*Sigma_bar[1][0] + Icro_2[0][2]*Sigma_bar[2][0];
+                                Sigma_bar[0][1] = Icro_2[0][0]*Sigma_bar[0][1] + Icro_2[0][1]*Sigma_bar[1][1] + Icro_2[0][2]*Sigma_bar[2][1];
+                                Sigma_bar[0][2] = Icro_2[0][0]*Sigma_bar[0][2] + Icro_2[0][1]*Sigma_bar[1][2] + Icro_2[0][2]*Sigma_bar[2][2];
+                                Sigma_bar[1][0] = Icro_2[1][0]*Sigma_bar[0][0] + Icro_2[1][1]*Sigma_bar[1][0] + Icro_2[1][2]*Sigma_bar[2][0];
+                                Sigma_bar[1][1] = Icro_2[1][0]*Sigma_bar[0][1] + Icro_2[1][1]*Sigma_bar[1][1] + Icro_2[1][2]*Sigma_bar[2][1];
+                                Sigma_bar[1][2] = Icro_2[1][0]*Sigma_bar[0][2] + Icro_2[1][1]*Sigma_bar[1][2] + Icro_2[1][2]*Sigma_bar[2][2];
+                                Sigma_bar[2][0] = Icro_2[2][0]*Sigma_bar[0][0] + Icro_2[2][1]*Sigma_bar[1][0] + Icro_2[2][2]*Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Icro_2[2][0]*Sigma_bar[0][1] + Icro_2[2][1]*Sigma_bar[1][1] + Icro_2[2][2]*Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Icro_2[2][0]*Sigma_bar[0][2] + Icro_2[2][1]*Sigma_bar[1][2] + Icro_2[2][2]*Sigma_bar[2][2];
+                                
+                                up_check = 1;
+                            break;
+                        }
+                    }
+                    else if(update_state == 2)
+                    {
+                        switch(select_ups) 
+                        {
+                            // 0 for no update
+                            case 0:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;                   
+                            break;
+                            
+                            // 1 for cross update only
+                            case 1:                
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;
+                            break;
+                            
+                            // 2 for line update only
+                            case 2:
+                                // mu = mu_bar + K*(Z-Z_hat)
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kli[2][0]*(Zli - Zli_hat[ind_diff_min])*PI/180;
+                                        
+                                // Sigma = (I - K*H) * Sigma_bar
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2] - Kli[2][0]*Sigma_bar[2][2];
+                                
+                                up_check = 2;
+                            break;
+                            
+                            // 3 for cross and line update together
+                            case 3:
+                                // mu = mu_bar + K*(Z-Z_hat)
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kli[2][0]*(Zli - Zli_hat[ind_diff_min])*PI/180;
+                                        
+                                // Sigma = (I - K*H) * Sigma_bar
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2] - Kli[2][0]*Sigma_bar[2][2];
+                                
+                                up_check = 2;
+                            break;
+                        }
+                    }
+                    else 
+                    {
+                        mu_bar[0][0] = mu_bar[0][0];         
+                        mu_bar[1][0] = mu_bar[1][0];
+                        mu_bar[2][0] = mu_bar[2][0];
+                        
+                        Sigma_bar[0][0] = Sigma_bar[0][0];
+                        Sigma_bar[0][1] = Sigma_bar[0][1];
+                        Sigma_bar[0][2] = Sigma_bar[0][2];
+                        Sigma_bar[1][0] = Sigma_bar[1][0];
+                        Sigma_bar[1][1] = Sigma_bar[1][1];
+                        Sigma_bar[1][2] = Sigma_bar[1][2];
+                        Sigma_bar[2][0] = Sigma_bar[2][0];
+                        Sigma_bar[2][1] = Sigma_bar[2][1];
+                        Sigma_bar[2][2] = Sigma_bar[2][2];
+                        
+                        up_check = 0;
+                    }
+                    
+                    up_dis = 0;
+                } 
+                else if(up_dis <= -up_dis_r) 
+                {
+                    // update
+                    if(update_state == 1) 
+                    {
+                        switch(select_ups) 
+                        {
+                            // 0 for no update
+                            case 0:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;                   
+                            break;
+                            
+                            // 1 for cross update only
+                            case 1:                
+                                // mu_bar + K*(Z-Z_hat) = mu
+                                mu_bar[0][0] = mu_bar[0][0] + Kcro_2[0][0];
+                                mu_bar[1][0] = mu_bar[1][0] + Kcro_2[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kcro_2[2][0];
+                                
+                                // (I - K*H) * Sigma_bar = Icro_2 * Sigma_bar = Sigma
+                                Sigma_bar[0][0] = Icro_2[0][0]*Sigma_bar[0][0] + Icro_2[0][1]*Sigma_bar[1][0] + Icro_2[0][2]*Sigma_bar[2][0];
+                                Sigma_bar[0][1] = Icro_2[0][0]*Sigma_bar[0][1] + Icro_2[0][1]*Sigma_bar[1][1] + Icro_2[0][2]*Sigma_bar[2][1];
+                                Sigma_bar[0][2] = Icro_2[0][0]*Sigma_bar[0][2] + Icro_2[0][1]*Sigma_bar[1][2] + Icro_2[0][2]*Sigma_bar[2][2];
+                                Sigma_bar[1][0] = Icro_2[1][0]*Sigma_bar[0][0] + Icro_2[1][1]*Sigma_bar[1][0] + Icro_2[1][2]*Sigma_bar[2][0];
+                                Sigma_bar[1][1] = Icro_2[1][0]*Sigma_bar[0][1] + Icro_2[1][1]*Sigma_bar[1][1] + Icro_2[1][2]*Sigma_bar[2][1];
+                                Sigma_bar[1][2] = Icro_2[1][0]*Sigma_bar[0][2] + Icro_2[1][1]*Sigma_bar[1][2] + Icro_2[1][2]*Sigma_bar[2][2];
+                                Sigma_bar[2][0] = Icro_2[2][0]*Sigma_bar[0][0] + Icro_2[2][1]*Sigma_bar[1][0] + Icro_2[2][2]*Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Icro_2[2][0]*Sigma_bar[0][1] + Icro_2[2][1]*Sigma_bar[1][1] + Icro_2[2][2]*Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Icro_2[2][0]*Sigma_bar[0][2] + Icro_2[2][1]*Sigma_bar[1][2] + Icro_2[2][2]*Sigma_bar[2][2];
+                                
+                                up_check = 1;
+                            break;
+                            
+                            // 2 for line update only
+                            case 2:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;
+                            break;
+                            
+                            // 3 for cross and line update together
+                            case 3:
+                                // mu_bar + K*(Z-Z_hat) = mu
+                                mu_bar[0][0] = mu_bar[0][0] + Kcro_2[0][0];
+                                mu_bar[1][0] = mu_bar[1][0] + Kcro_2[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kcro_2[2][0];
+                                
+                                // (I - K*H) * Sigma_bar = Icro_2 * Sigma_bar = Sigma
+                                Sigma_bar[0][0] = Icro_2[0][0]*Sigma_bar[0][0] + Icro_2[0][1]*Sigma_bar[1][0] + Icro_2[0][2]*Sigma_bar[2][0];
+                                Sigma_bar[0][1] = Icro_2[0][0]*Sigma_bar[0][1] + Icro_2[0][1]*Sigma_bar[1][1] + Icro_2[0][2]*Sigma_bar[2][1];
+                                Sigma_bar[0][2] = Icro_2[0][0]*Sigma_bar[0][2] + Icro_2[0][1]*Sigma_bar[1][2] + Icro_2[0][2]*Sigma_bar[2][2];
+                                Sigma_bar[1][0] = Icro_2[1][0]*Sigma_bar[0][0] + Icro_2[1][1]*Sigma_bar[1][0] + Icro_2[1][2]*Sigma_bar[2][0];
+                                Sigma_bar[1][1] = Icro_2[1][0]*Sigma_bar[0][1] + Icro_2[1][1]*Sigma_bar[1][1] + Icro_2[1][2]*Sigma_bar[2][1];
+                                Sigma_bar[1][2] = Icro_2[1][0]*Sigma_bar[0][2] + Icro_2[1][1]*Sigma_bar[1][2] + Icro_2[1][2]*Sigma_bar[2][2];
+                                Sigma_bar[2][0] = Icro_2[2][0]*Sigma_bar[0][0] + Icro_2[2][1]*Sigma_bar[1][0] + Icro_2[2][2]*Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Icro_2[2][0]*Sigma_bar[0][1] + Icro_2[2][1]*Sigma_bar[1][1] + Icro_2[2][2]*Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Icro_2[2][0]*Sigma_bar[0][2] + Icro_2[2][1]*Sigma_bar[1][2] + Icro_2[2][2]*Sigma_bar[2][2];
+                                
+                                up_check = 1;
+                            break;
+                        }
+                    }
+                    else if(update_state == 2)
+                    {
+                        switch(select_ups) 
+                        {
+                            // 0 for no update
+                            case 0:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;                   
+                            break;
+                            
+                            // 1 for cross update only
+                            case 1:                
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;
+                            break;
+                            
+                            // 2 for line update only
+                            case 2:
+                                // mu = mu_bar + K*(Z-Z_hat)
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kli[2][0]*(Zli - Zli_hat[ind_diff_min])*PI/180;
+                                        
+                                // Sigma = (I - K*H) * Sigma_bar
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2] - Kli[2][0]*Sigma_bar[2][2];
+                                
+                                up_check = 2;
+                            break;
+                            
+                            // 3 for cross and line update together
+                            case 3:
+                                // mu = mu_bar + K*(Z-Z_hat)
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kli[2][0]*(Zli - Zli_hat[ind_diff_min])*PI/180;
+                                        
+                                // Sigma = (I - K*H) * Sigma_bar
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2] - Kli[2][0]*Sigma_bar[2][2];
+                                
+                                up_check = 2;
+                            break;
+                        }
+                    }
+                    else 
+                    {
+                        mu_bar[0][0] = mu_bar[0][0];         
+                        mu_bar[1][0] = mu_bar[1][0];
+                        mu_bar[2][0] = mu_bar[2][0];
+                        
+                        Sigma_bar[0][0] = Sigma_bar[0][0];
+                        Sigma_bar[0][1] = Sigma_bar[0][1];
+                        Sigma_bar[0][2] = Sigma_bar[0][2];
+                        Sigma_bar[1][0] = Sigma_bar[1][0];
+                        Sigma_bar[1][1] = Sigma_bar[1][1];
+                        Sigma_bar[1][2] = Sigma_bar[1][2];
+                        Sigma_bar[2][0] = Sigma_bar[2][0];
+                        Sigma_bar[2][1] = Sigma_bar[2][1];
+                        Sigma_bar[2][2] = Sigma_bar[2][2];
+                        
+                        up_check = 0;
+                    }
+                    
+                    up_dis = 0;
+                } 
+                else if(up_rot >= up_rot_r) 
+                {
+                    // update
+                    if(update_state == 1) 
+                    {
+                        switch(select_ups) 
+                        {
+                            // 0 for no update
+                            case 0:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;                   
+                            break;
+                            
+                            // 1 for cross update only
+                            case 1:                
+                                // mu_bar + K*(Z-Z_hat) = mu
+                                mu_bar[0][0] = mu_bar[0][0] + Kcro_2[0][0];
+                                mu_bar[1][0] = mu_bar[1][0] + Kcro_2[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kcro_2[2][0];
+                                
+                                // (I - K*H) * Sigma_bar = Icro_2 * Sigma_bar = Sigma
+                                Sigma_bar[0][0] = Icro_2[0][0]*Sigma_bar[0][0] + Icro_2[0][1]*Sigma_bar[1][0] + Icro_2[0][2]*Sigma_bar[2][0];
+                                Sigma_bar[0][1] = Icro_2[0][0]*Sigma_bar[0][1] + Icro_2[0][1]*Sigma_bar[1][1] + Icro_2[0][2]*Sigma_bar[2][1];
+                                Sigma_bar[0][2] = Icro_2[0][0]*Sigma_bar[0][2] + Icro_2[0][1]*Sigma_bar[1][2] + Icro_2[0][2]*Sigma_bar[2][2];
+                                Sigma_bar[1][0] = Icro_2[1][0]*Sigma_bar[0][0] + Icro_2[1][1]*Sigma_bar[1][0] + Icro_2[1][2]*Sigma_bar[2][0];
+                                Sigma_bar[1][1] = Icro_2[1][0]*Sigma_bar[0][1] + Icro_2[1][1]*Sigma_bar[1][1] + Icro_2[1][2]*Sigma_bar[2][1];
+                                Sigma_bar[1][2] = Icro_2[1][0]*Sigma_bar[0][2] + Icro_2[1][1]*Sigma_bar[1][2] + Icro_2[1][2]*Sigma_bar[2][2];
+                                Sigma_bar[2][0] = Icro_2[2][0]*Sigma_bar[0][0] + Icro_2[2][1]*Sigma_bar[1][0] + Icro_2[2][2]*Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Icro_2[2][0]*Sigma_bar[0][1] + Icro_2[2][1]*Sigma_bar[1][1] + Icro_2[2][2]*Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Icro_2[2][0]*Sigma_bar[0][2] + Icro_2[2][1]*Sigma_bar[1][2] + Icro_2[2][2]*Sigma_bar[2][2];
+                                
+                                up_check = 1;
+                            break;
+                            
+                            // 2 for line update only
+                            case 2:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;
+                            break;
+                            
+                            // 3 for cross and line update together
+                            case 3:
+                                // mu_bar + K*(Z-Z_hat) = mu
+                                mu_bar[0][0] = mu_bar[0][0] + Kcro_2[0][0];
+                                mu_bar[1][0] = mu_bar[1][0] + Kcro_2[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kcro_2[2][0];
+                                
+                                // (I - K*H) * Sigma_bar = Icro_2 * Sigma_bar = Sigma
+                                Sigma_bar[0][0] = Icro_2[0][0]*Sigma_bar[0][0] + Icro_2[0][1]*Sigma_bar[1][0] + Icro_2[0][2]*Sigma_bar[2][0];
+                                Sigma_bar[0][1] = Icro_2[0][0]*Sigma_bar[0][1] + Icro_2[0][1]*Sigma_bar[1][1] + Icro_2[0][2]*Sigma_bar[2][1];
+                                Sigma_bar[0][2] = Icro_2[0][0]*Sigma_bar[0][2] + Icro_2[0][1]*Sigma_bar[1][2] + Icro_2[0][2]*Sigma_bar[2][2];
+                                Sigma_bar[1][0] = Icro_2[1][0]*Sigma_bar[0][0] + Icro_2[1][1]*Sigma_bar[1][0] + Icro_2[1][2]*Sigma_bar[2][0];
+                                Sigma_bar[1][1] = Icro_2[1][0]*Sigma_bar[0][1] + Icro_2[1][1]*Sigma_bar[1][1] + Icro_2[1][2]*Sigma_bar[2][1];
+                                Sigma_bar[1][2] = Icro_2[1][0]*Sigma_bar[0][2] + Icro_2[1][1]*Sigma_bar[1][2] + Icro_2[1][2]*Sigma_bar[2][2];
+                                Sigma_bar[2][0] = Icro_2[2][0]*Sigma_bar[0][0] + Icro_2[2][1]*Sigma_bar[1][0] + Icro_2[2][2]*Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Icro_2[2][0]*Sigma_bar[0][1] + Icro_2[2][1]*Sigma_bar[1][1] + Icro_2[2][2]*Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Icro_2[2][0]*Sigma_bar[0][2] + Icro_2[2][1]*Sigma_bar[1][2] + Icro_2[2][2]*Sigma_bar[2][2];
+                                
+                                up_check = 1;
+                            break;
+                        }
+                    }
+                    else if(update_state == 2)
+                    {
+                        switch(select_ups) 
+                        {
+                            // 0 for no update
+                            case 0:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;                   
+                            break;
+                            
+                            // 1 for cross update only
+                            case 1:                
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;
+                            break;
+                            
+                            // 2 for line update only
+                            case 2:
+                                // mu = mu_bar + K*(Z-Z_hat)
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kli[2][0]*(Zli - Zli_hat[ind_diff_min])*PI/180;
+                                        
+                                // Sigma = (I - K*H) * Sigma_bar
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2] - Kli[2][0]*Sigma_bar[2][2];
+                                
+                                up_check = 2;
+                            break;
+                            
+                            // 3 for cross and line update together
+                            case 3:
+                                // mu = mu_bar + K*(Z-Z_hat)
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kli[2][0]*(Zli - Zli_hat[ind_diff_min])*PI/180;
+                                        
+                                // Sigma = (I - K*H) * Sigma_bar
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2] - Kli[2][0]*Sigma_bar[2][2];
+                                
+                                up_check = 2;
+                            break;
+                        }
+                    }
+                    else 
+                    {
+                        mu_bar[0][0] = mu_bar[0][0];         
+                        mu_bar[1][0] = mu_bar[1][0];
+                        mu_bar[2][0] = mu_bar[2][0];
+                        
+                        Sigma_bar[0][0] = Sigma_bar[0][0];
+                        Sigma_bar[0][1] = Sigma_bar[0][1];
+                        Sigma_bar[0][2] = Sigma_bar[0][2];
+                        Sigma_bar[1][0] = Sigma_bar[1][0];
+                        Sigma_bar[1][1] = Sigma_bar[1][1];
+                        Sigma_bar[1][2] = Sigma_bar[1][2];
+                        Sigma_bar[2][0] = Sigma_bar[2][0];
+                        Sigma_bar[2][1] = Sigma_bar[2][1];
+                        Sigma_bar[2][2] = Sigma_bar[2][2];
+                        
+                        up_check = 0;
+                    }
+                    
+                    up_rot = 0;
+                } 
+                else if(up_rot <= -up_rot_r) 
+                {
+                    // update
+                    if(update_state == 1) 
+                    {
+                        switch(select_ups) 
+                        {
+                            // 0 for no update
+                            case 0:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;                   
+                            break;
+                            
+                            // 1 for cross update only
+                            case 1:                
+                                // mu_bar + K*(Z-Z_hat) = mu
+                                mu_bar[0][0] = mu_bar[0][0] + Kcro_2[0][0];
+                                mu_bar[1][0] = mu_bar[1][0] + Kcro_2[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kcro_2[2][0];
+                                
+                                // (I - K*H) * Sigma_bar = Icro_2 * Sigma_bar = Sigma
+                                Sigma_bar[0][0] = Icro_2[0][0]*Sigma_bar[0][0] + Icro_2[0][1]*Sigma_bar[1][0] + Icro_2[0][2]*Sigma_bar[2][0];
+                                Sigma_bar[0][1] = Icro_2[0][0]*Sigma_bar[0][1] + Icro_2[0][1]*Sigma_bar[1][1] + Icro_2[0][2]*Sigma_bar[2][1];
+                                Sigma_bar[0][2] = Icro_2[0][0]*Sigma_bar[0][2] + Icro_2[0][1]*Sigma_bar[1][2] + Icro_2[0][2]*Sigma_bar[2][2];
+                                Sigma_bar[1][0] = Icro_2[1][0]*Sigma_bar[0][0] + Icro_2[1][1]*Sigma_bar[1][0] + Icro_2[1][2]*Sigma_bar[2][0];
+                                Sigma_bar[1][1] = Icro_2[1][0]*Sigma_bar[0][1] + Icro_2[1][1]*Sigma_bar[1][1] + Icro_2[1][2]*Sigma_bar[2][1];
+                                Sigma_bar[1][2] = Icro_2[1][0]*Sigma_bar[0][2] + Icro_2[1][1]*Sigma_bar[1][2] + Icro_2[1][2]*Sigma_bar[2][2];
+                                Sigma_bar[2][0] = Icro_2[2][0]*Sigma_bar[0][0] + Icro_2[2][1]*Sigma_bar[1][0] + Icro_2[2][2]*Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Icro_2[2][0]*Sigma_bar[0][1] + Icro_2[2][1]*Sigma_bar[1][1] + Icro_2[2][2]*Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Icro_2[2][0]*Sigma_bar[0][2] + Icro_2[2][1]*Sigma_bar[1][2] + Icro_2[2][2]*Sigma_bar[2][2];
+                                
+                                up_check = 1;
+                            break;
+                            
+                            // 2 for line update only
+                            case 2:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;
+                            break;
+                            
+                            // 3 for cross and line update together
+                            case 3:
+                                // mu_bar + K*(Z-Z_hat) = mu
+                                mu_bar[0][0] = mu_bar[0][0] + Kcro_2[0][0];
+                                mu_bar[1][0] = mu_bar[1][0] + Kcro_2[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kcro_2[2][0];
+                                
+                                // (I - K*H) * Sigma_bar = Icro_2 * Sigma_bar = Sigma
+                                Sigma_bar[0][0] = Icro_2[0][0]*Sigma_bar[0][0] + Icro_2[0][1]*Sigma_bar[1][0] + Icro_2[0][2]*Sigma_bar[2][0];
+                                Sigma_bar[0][1] = Icro_2[0][0]*Sigma_bar[0][1] + Icro_2[0][1]*Sigma_bar[1][1] + Icro_2[0][2]*Sigma_bar[2][1];
+                                Sigma_bar[0][2] = Icro_2[0][0]*Sigma_bar[0][2] + Icro_2[0][1]*Sigma_bar[1][2] + Icro_2[0][2]*Sigma_bar[2][2];
+                                Sigma_bar[1][0] = Icro_2[1][0]*Sigma_bar[0][0] + Icro_2[1][1]*Sigma_bar[1][0] + Icro_2[1][2]*Sigma_bar[2][0];
+                                Sigma_bar[1][1] = Icro_2[1][0]*Sigma_bar[0][1] + Icro_2[1][1]*Sigma_bar[1][1] + Icro_2[1][2]*Sigma_bar[2][1];
+                                Sigma_bar[1][2] = Icro_2[1][0]*Sigma_bar[0][2] + Icro_2[1][1]*Sigma_bar[1][2] + Icro_2[1][2]*Sigma_bar[2][2];
+                                Sigma_bar[2][0] = Icro_2[2][0]*Sigma_bar[0][0] + Icro_2[2][1]*Sigma_bar[1][0] + Icro_2[2][2]*Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Icro_2[2][0]*Sigma_bar[0][1] + Icro_2[2][1]*Sigma_bar[1][1] + Icro_2[2][2]*Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Icro_2[2][0]*Sigma_bar[0][2] + Icro_2[2][1]*Sigma_bar[1][2] + Icro_2[2][2]*Sigma_bar[2][2];
+                                
+                                up_check = 1;
+                            break;
+                        }
+                    }
+                    else if(update_state == 2)
+                    {
+                        switch(select_ups) 
+                        {
+                            // 0 for no update
+                            case 0:
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;                   
+                            break;
+                            
+                            // 1 for cross update only
+                            case 1:                
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0];
+                        
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2];
+                                
+                                up_check = 0;
+                            break;
+                            
+                            // 2 for line update only
+                            case 2:
+                                // mu = mu_bar + K*(Z-Z_hat)
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kli[2][0]*(Zli - Zli_hat[ind_diff_min])*PI/180;
+                                        
+                                // Sigma = (I - K*H) * Sigma_bar
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2] - Kli[2][0]*Sigma_bar[2][2];
+                                
+                                up_check = 2;
+                            break;
+                            
+                            // 3 for cross and line update together
+                            case 3:
+                                // mu = mu_bar + K*(Z-Z_hat)
+                                mu_bar[0][0] = mu_bar[0][0];         
+                                mu_bar[1][0] = mu_bar[1][0];
+                                mu_bar[2][0] = mu_bar[2][0] + Kli[2][0]*(Zli - Zli_hat[ind_diff_min])*PI/180;
+                                        
+                                // Sigma = (I - K*H) * Sigma_bar
+                                Sigma_bar[0][0] = Sigma_bar[0][0];
+                                Sigma_bar[0][1] = Sigma_bar[0][1];
+                                Sigma_bar[0][2] = Sigma_bar[0][2];
+                                Sigma_bar[1][0] = Sigma_bar[1][0];
+                                Sigma_bar[1][1] = Sigma_bar[1][1];
+                                Sigma_bar[1][2] = Sigma_bar[1][2];
+                                Sigma_bar[2][0] = Sigma_bar[2][0];
+                                Sigma_bar[2][1] = Sigma_bar[2][1];
+                                Sigma_bar[2][2] = Sigma_bar[2][2] - Kli[2][0]*Sigma_bar[2][2];
+                                
+                                up_check = 2;
+                            break;
+                        }
+                    }
+                    else 
+                    {
+                        mu_bar[0][0] = mu_bar[0][0];         
+                        mu_bar[1][0] = mu_bar[1][0];
+                        mu_bar[2][0] = mu_bar[2][0];
+                        
+                        Sigma_bar[0][0] = Sigma_bar[0][0];
+                        Sigma_bar[0][1] = Sigma_bar[0][1];
+                        Sigma_bar[0][2] = Sigma_bar[0][2];
+                        Sigma_bar[1][0] = Sigma_bar[1][0];
+                        Sigma_bar[1][1] = Sigma_bar[1][1];
+                        Sigma_bar[1][2] = Sigma_bar[1][2];
+                        Sigma_bar[2][0] = Sigma_bar[2][0];
+                        Sigma_bar[2][1] = Sigma_bar[2][1];
+                        Sigma_bar[2][2] = Sigma_bar[2][2];
+                        
+                        up_check = 0;
+                    }
+                    
+                    up_rot = 0;
+                } 
+                else 
+                {
+                    mu_bar[0][0] = mu_bar[0][0];         
+                    mu_bar[1][0] = mu_bar[1][0];
+                    mu_bar[2][0] = mu_bar[2][0];
+                    
+                    Sigma_bar[0][0] = Sigma_bar[0][0];
+                    Sigma_bar[0][1] = Sigma_bar[0][1];
+                    Sigma_bar[0][2] = Sigma_bar[0][2];
+                    Sigma_bar[1][0] = Sigma_bar[1][0];
+                    Sigma_bar[1][1] = Sigma_bar[1][1];
+                    Sigma_bar[1][2] = Sigma_bar[1][2];
+                    Sigma_bar[2][0] = Sigma_bar[2][0];
+                    Sigma_bar[2][1] = Sigma_bar[2][1];
+                    Sigma_bar[2][2] = Sigma_bar[2][2];
+                    
+                    up_check = 0;
+                }
+                
+                mu[0][0] = mu_bar[0][0];         
+                mu[1][0] = mu_bar[1][0];
+                mu[2][0] = mu_bar[2][0];
+                    
+                Sigma[0][0] = Sigma_bar[0][0];
+                Sigma[0][1] = Sigma_bar[0][1];
+                Sigma[0][2] = Sigma_bar[0][2];
+                Sigma[1][0] = Sigma_bar[1][0];
+                Sigma[1][1] = Sigma_bar[1][1];
+                Sigma[1][2] = Sigma_bar[1][2];
+                Sigma[2][0] = Sigma_bar[2][0];
+                Sigma[2][1] = Sigma_bar[2][1];
+                Sigma[2][2] = Sigma_bar[2][2];
+            }
+            // if(fusion_flag == 1) end
+        }
+        
+////////// timer 5 : extended kalman filter ////////////////////////////////////////////////////////////////////////////////////
+        
+        // timer 6 : navigation
+        if((t.read_us() - lastMilli6) >= LOOPTIME6)         // 100000 us = 0.1 s
+        {       
+            lastMilli6 = t.read_us();
+            
+            // range 0~359 deg
+            mu_th_deg = mu[2][0] * 180/PI;
+
+            if(mu_th_deg < 0)
+                mu_th_deg = mu_th_deg % 360 + 360;
+            else
+                mu_th_deg = mu_th_deg % 360;
+            
+            // range -179~180 deg
+            if(mu_th_deg > 180)
+                mu_th_deg_180 = mu_th_deg - 360;
+            else
+                mu_th_deg_180 = mu_th_deg;
+            
+            mu_th_PI = (float)mu_th_deg_180 * PI/180;
+            
+            int turn_point = 33;
+            int end_point = turn_point + 22;
+            
+            if(nav_state == 1)
+            {
+                Pxd = turn_point*1*block_length;
+                Pyd = 0*1*block_length;                 
+                Od = 0;
+            }
+            else if(nav_state == 2)
+            {
+                Pxd = turn_point*1*block_length;
+                Pyd = 0*1*block_length;            
+                Od = PI/2;
+            }
+            else if(nav_state == 3)
+            {
+                Pxd = turn_point*1*block_length;
+                Pyd = (1)*(end_point - turn_point)*1*block_length;
+                Od = PI/2;
+            }
+            else if(nav_state == 4)
+            {
+                Pxd = turn_point*1*block_length;
+                Pyd = (1)*(end_point - turn_point)*1*block_length;
+                Od = PI;
+            }
+            
+            delta_Pxd = mu[0][0] - Pxd;
+            delta_Pyd = mu[1][0] - Pyd;
+            delta_Od = mu_th_PI - Od;
+            
+            distance_error_P = sqrt(pow(delta_Pxd,2) + pow(delta_Pyd,2));
+            error_O = delta_Od;
+            
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
+
+            if((Theta_c >= 70 && Theta_c <= 89) && (Theta_c >= -89 && Theta_c <= -70) && nav_flag == 1 && update_source == 2 && update_source == 1)
+            {
+                line_tracker = 1;
+            }
+            else
+            {
+                line_tracker = 0;
+            }
+            
+            if(nav_state == 2)
+            {
+                line_tracker = 0;
+            }
+
+            if(line_tracker == 1)
+            {
+                float K_line_tracker = 0.02;
+    
+                if(Theta_c >= 60)    {gain_w = -K_line_tracker*(Theta_c - 90);}
+                else if(Theta_c <= -60)  {gain_w = -K_line_tracker*(90 + Theta_c);}
+            
+                if(distance_error_P >= 0.39)
+                {
+                    gain_v = 0.15;
+                }
+                else
+                {
+                    gain_v = -Kv*(delta_Pxd*cos(mu_th_PI) + delta_Pyd*sin(mu_th_PI));
+                }
+                
+                vel_msg.linear.x = gain_v;
+                vel_msg.angular.z = gain_w;
+                p.publish(&vel_msg);
+                
+                gain_v = -Kv*(delta_Pxd*cos(mu_th_PI) + delta_Pyd*sin(mu_th_PI));
+                gain_w = -Kw*delta_Od;
+                
+                if(gain_v >= 0)
+                    error_P = gain_v;
+                else
+                    error_P = -gain_v;
+                    
+                if(gain_w >= 0)
+                    error_O = gain_w;
+                else
+                    error_O = -gain_w;
+            }
+            else
+            {
+                if(distance_error_P >= 0.39)
+                {
+                    gain_v = 0.15;
+                    gain_w = -Kw*delta_Od;
+                }
+                else
+                {
+                    gain_v = -Kv*(delta_Pxd*cos(mu_th_PI) + delta_Pyd*sin(mu_th_PI));
+                    gain_w = -Kw*delta_Od;
+                }
+                
+                if(gain_v >= 0)
+                    error_P = gain_v;
+                else
+                    error_P = -gain_v;
+            
+                if(gain_w >= 0)
+                    error_O = gain_w;
+                else
+                    error_O = -gain_w;
+                          
+                if(nav_flag == 1) 
+                {
+                    vel_msg.linear.x = gain_v;
+                    vel_msg.angular.z = gain_w;
+                    p.publish(&vel_msg);
+                }
+               
+            }
+            
+            if(error_P < 0.01 && error_O < PI/90)
+            {
+                vel_msg.linear.x = 0;
+                vel_msg.angular.z = 0;
+                p.publish(&vel_msg);
+                        
+                nav_state++;
+                            
+                if(nav_state >= 5)
+                {
+                    nav_flag = 0;
+                    nav_state = 0;
+                }
+            }
+        }
+        
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//    
+            
+        // magnetometer correction
+        if(cal_flag == 1) 
+        {
+            magx_max =  magx[0];
+            magx_min =  magx[0];
+            magy_max =  magy[0];
+            magy_min =  magy[0];
+
+            magx_max2 =  magx2[0];
+            magx_min2 =  magx2[0];
+            magy_max2 =  magy2[0];
+            magy_min2 =  magy2[0];
+
+            for(int i = 1 ; i < ind ; i++) 
+            {
+                if(magx[i] > magx_max)      // find x max
+                    magx_max = magx[i];
+                if(magx[i] < magx_min)      // find x min
+                    magx_min = magx[i];
+                if(magy[i] > magy_max)      // find y max
+                    magy_max = magy[i];
+                if(magy[i] < magy_min)      // find y min
+                    magy_min = magy[i];
+
+                if(magx2[i] > magx_max2)    // find x max
+                    magx_max2 = magx2[i];
+                if(magx2[i] < magx_min2)    // find x min
+                    magx_min2 = magx2[i];
+                if(magy2[i] > magy_max2)    // find y max
+                    magy_max2 = magy2[i];
+                if(magy2[i] < magy_min2)    // find y min
+                    magy_min2 = magy2[i];
+            }
+
+            magx0 = (magx_max + magx_min) / 2;        // center x
+            magy0 = (magy_max + magy_min) / 2;        // center y
+
+            magx02 = (magx_max2 + magx_min2) / 2;     // center x
+            magy02 = (magy_max2 + magy_min2) / 2;     // center y
+
+            Magn_axis_zero[0] = magx0;
+            Magn_axis_zero[1] = magy0;
+
+            Magn_axis_zero2[0] = magx02;
+            Magn_axis_zero2[1] = magy02;
+
+            a = (magx_max - magx_min) / 2;            // long axis
+            b = (magy_max - magy_min) / 2;            // short axis
+
+            a2 = (magx_max2 - magx_min2) / 2;         // long axis
+            b2 = (magy_max2 - magy_min2) / 2;         // short axis
+
+            Bex = (Magn_axis_data_f[0] - Magn_axis_zero[0]) / a;
+            Bey = (Magn_axis_data_f[1] - Magn_axis_zero[1]) / b;
+
+            Bex2 = (Magn_axis_data_f2[0] - Magn_axis_zero2[0]) / a2;
+            Bey2 = (Magn_axis_data_f2[1] - Magn_axis_zero2[1]) / b2;
+
+            Be = (sqrt(Bex*Bex + Bey*Bey) + sqrt(Bex2*Bex2 + Bey2*Bey2)) / 2;
+
+            cal_flag = 0;                          // calculate finish
+            th = 0;
+            ind = 0;
+            ind_ = 0;
+            BK_ = 1;
+        }
+    }   // while(1) end
+}   // int main() end
+
+// Kalman filter and observer //////////////////////////////////////////////////////////////////////////////////////////////
+
+void read_sensor(void)
+{
+    // read sensor raw data from LSM9DS0_SH.h
+    read_IMU();
+
+    // sensor filter data
+    // gyro z
+    Gyro_axis_data_f[2] = lpf(Wz,Gyro_axis_data_f_old[2],10);
+    Gyro_axis_data_f_old[2] = Gyro_axis_data_f[2];
+
+    // magn x , magn y , magn z
+    Magn_axis_data_f[0] = lpf(Mx,Magn_axis_data_f_old[0],12);
+    Magn_axis_data_f_old[0] = Magn_axis_data_f[0];
+    Magn_axis_data_f[1] = lpf(My,Magn_axis_data_f_old[1],12);
+    Magn_axis_data_f_old[1] = Magn_axis_data_f[1];
+
+    Magn_axis_data_f2[0] = lpf(M2x,Magn_axis_data_f_old2[0],12);
+    Magn_axis_data_f_old2[0] = Magn_axis_data_f2[0];
+    Magn_axis_data_f2[1] = lpf(M2y,Magn_axis_data_f_old2[1],12);
+    Magn_axis_data_f_old2[1] = Magn_axis_data_f2[1];
+
+    // sensor after correction
+    // gyro z
+    Gyro_scale[2] = (Gyro_axis_data_f[2] - Gyro_axis_zero[2]);
+    w_s = Gyro_scale[2];
+
+    // magn x , magn y
+    Magn_scale[0] = (Magn_axis_data_f[0] - Magn_axis_zero[0]) / a;
+    Magn_scale[1] = (Magn_axis_data_f[1] - Magn_axis_zero[1]) / b;
+
+    Magn_scale2[0] = (Magn_axis_data_f2[0] - Magn_axis_zero2[0]) / a2;
+    Magn_scale2[1] = (Magn_axis_data_f2[1] - Magn_axis_zero2[1]) / b2;
+
+    // trust index
+    Q = (Magn_scale[0]*Magn_scale2[0] + Magn_scale[1]*Magn_scale2[1]) / (Be * Be);
+    Q = Q - 1;
+
+    // magnetometer angle
+    if(Magn_scale[0]>0 && Magn_scale[1]>0)
+        phi = 2*PI - atan((Magn_scale[1])/(Magn_scale[0]));
+    else if(Magn_scale[0]<0 && Magn_scale[1]>0)
+        phi = 2*PI - (PI - atan(-(Magn_scale[1])/(Magn_scale[0])));
+    else if(Magn_scale[0]<0 && Magn_scale[1]<0)
+        phi = 2*PI - (PI + atan((Magn_scale[1])/(Magn_scale[0])));
+    else if(Magn_scale[0]>0 && Magn_scale[1]<0)
+        phi = 2*PI - (2*PI - atan(-(Magn_scale[1])/(Magn_scale[0])));
+
+    if(Magn_scale2[0]>0 && Magn_scale2[1]>0)
+        phi2 = 2*PI - atan((Magn_scale2[1])/(Magn_scale2[0]));
+    else if(Magn_scale2[0]<0 && Magn_scale2[1]>0)
+        phi2 = 2*PI - (PI - atan(-(Magn_scale2[1])/(Magn_scale2[0])));
+    else if(Magn_scale2[0]<0 && Magn_scale2[1]<0)
+        phi2 = 2*PI - (PI + atan((Magn_scale2[1])/(Magn_scale2[0])));
+    else if(Magn_scale2[0]>0 && Magn_scale2[1]<0)
+        phi2 = 2*PI - (2*PI - atan(-(Magn_scale2[1])/(Magn_scale2[0])));
+
+    // gyro bias average
+    if(gyro_flag == 0) 
+    {
+        gyro_count++;
+
+        if(gyro_count == 150) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            index_count++;
+        } 
+        else if(gyro_count == 155) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            index_count++;
+        } 
+        else if(gyro_count == 160) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            index_count++;
+        } 
+        else if(gyro_count == 165) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            index_count++;
+        } 
+        else if(gyro_count == 170) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            index_count++;
+        } 
+        else if(gyro_count == 175) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            index_count++;
+        } 
+        else if(gyro_count == 180) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            index_count++;
+        } 
+        else if(gyro_count == 185) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            index_count++;
+        } 
+        else if(gyro_count == 190) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            index_count++;
+        } 
+        else if(gyro_count >= 195) 
+        {
+            gyro_init[index_count] = Gyro_axis_data_f[2];
+            int z = 0;
+            for(z=0 ; z<10 ; z++)
+                gyro_sum = gyro_sum + gyro_init[z];
+
+            Gyro_axis_zero[2] = gyro_sum / 10;
+            index_count = 0;
+            gyro_count = 0;
+            gyro_flag = 1;
+        }
+    }
+
+    if(gyro_flag == 1) 
+    {
+        // w_s deadzone
+        int flag_d_1 = 0;
+        int flag_d_2 = 0;
+        flag_d_1 = w_s <= 0.006;
+        flag_d_2 = w_s >= -0.006;
+
+        if((flag_d_1 + flag_d_2) == 2)
+            w_s_d = 0;
+        else
+            w_s_d = w_s;
+
+        // w_s_d integral
+        theta_s = theta_s + T*w_s_d;
+
+        // theta_s_deg range 0~359 deg
+        theta_s_deg = theta_s * 180/PI;
+
+        if(theta_s_deg < 0)
+            theta_s_deg = theta_s_deg % 360 + 360;
+        else
+            theta_s_deg = theta_s_deg % 360;
+    }
+
+    // phi initialize
+    if(phi_init_flag == 1) 
+    {
+        phi_init_count++;
+
+        if(phi_init_count >= 200) 
+        {
+            // take current phi data for reseting absolute orientation to zero
+            phi_init = phi;
+            phi_init2 = phi2;
+
+            // reset KF and observer data
+            phi_m_a_deg = 0;
+            phi_m2_a_deg = 0;
+            jump_count = 0;
+            jump_count2 = 0;
+            phi_m_deg_1 = 0;
+            phi_m2_deg_1 = 0;
+            phi_m_deg_2 = 0;
+            phi_m2_deg_2 = 0;
+            phi_m_a_avg = 0;
+            theta_s = 0;
+            theta_me = 0;
+            theta_fu = 0;
+            theta_fu_old = 0;
+            bias = 0;
+            bias_old = 0;
+            y = 0;
+            
+            // encoder odometry reset
+            x = 0;
+            y_ = 0;
+            th = 0;
+            x_enc = 0;
+            y_enc = 0;
+            th_enc = 0;
+            x_emg = 0;
+            y_emg = 0;
+            th_emg = 0;
+            
+            // reset EKF data
+            for(int i = 0 ; i < 3 ; i++)
+            {
+                mu_bar[i][0] = 0;
+                mu[i][0] = 0;
+                
+                for(int j = 0 ; j < 3 ; j++)
+                {
+                    Sigma_bar[i][j] = 0;
+                    Sigma[i][j] = 0;
+                }
+            }
+
+            // stop initialization
+            phi_init_count = 0;
+            phi_init_flag = 0;
+
+            // start fusion
+            fusion_flag = 1;
+            B_ = 1;                 // dark
+        }
+    }
+
+    // phi_m_deg range 0~359 deg
+    phi_m = phi - phi_init;
+    phi_m_deg = phi_m * 180/PI;
+
+    if(phi_m_deg < 0)
+        phi_m_deg = phi_m_deg % 360 + 360;
+    else
+        phi_m_deg = phi_m_deg % 360;
+
+    phi_m2 = phi2 - phi_init2;
+    phi_m2_deg = phi_m2 * 180/PI;
+
+    if(phi_m2_deg < 0)
+        phi_m2_deg = phi_m2_deg % 360 + 360;
+    else
+        phi_m2_deg = phi_m2_deg % 360;
+
+    // phi_m_a accumulate form
+    diff_phi_count++;
+
+    if(diff_phi_flag == 0) 
+    {
+        phi_m_deg_1 = phi_m_deg;
+        phi_m2_deg_1 = phi_m2_deg;
+        diff_phi_flag = 1;
+    } 
+    else if(diff_phi_flag == 1) 
+    {
+        if(diff_phi_count >= 2) 
+        {
+            phi_m_deg_2 = phi_m_deg + 360*jump_count;
+            phi_m_deg_T = phi_m_deg_2 - phi_m_deg_1;
+
+            if(phi_m_deg_T <= -300) 
+            {
+                phi_m_a_deg = phi_m_deg_2 + 360;
+                phi_m_deg_1 = phi_m_a_deg;
+                jump_count++;
+            } 
+            else if(phi_m_deg_T >= 300) 
+            {
+                phi_m_a_deg = phi_m_deg_2 - 360;
+                phi_m_deg_1 = phi_m_a_deg;
+                jump_count--;
+            } 
+            else 
+            {
+                phi_m_a_deg = phi_m_deg_2;
+                phi_m_deg_1 = phi_m_a_deg;
+            }
+
+            phi_m_a = phi_m_a_deg * PI/180;
+
+            ////////////////////////////////////////////////////////////////////
+
+            phi_m2_deg_2 = phi_m2_deg + 360*jump_count2;
+            phi_m2_deg_T = phi_m2_deg_2 - phi_m2_deg_1;
+
+            if(phi_m2_deg_T <= -300) 
+            {
+                phi_m2_a_deg = phi_m2_deg_2 + 360;
+                phi_m2_deg_1 = phi_m2_a_deg;
+                jump_count2++;
+            } 
+            else if(phi_m2_deg_T >= 300) 
+            {
+                phi_m2_a_deg = phi_m2_deg_2 - 360;
+                phi_m2_deg_1 = phi_m2_a_deg;
+                jump_count2--;
+            } 
+            else 
+            {
+                phi_m2_a_deg = phi_m2_deg_2;
+                phi_m2_deg_1 = phi_m2_a_deg;
+            }
+
+            phi_m2_a = phi_m2_a_deg * PI/180;
+
+            phi_m_a_avg = 0.7*phi_m_a + 0.3*phi_m2_a;
+
+            diff_phi_count = 0;
+        }
+    }
+
+    // theta_me Kalman filter
+    // prediction
+    theta_me_bar = At*theta_me + Bt*omega_z;
+    sigma_bar = At*sigma*At + Rt;
+
+    if(Q >= -0.009 && Q <= 0.009) 
+    {
+        if(Q >= 0)
+            V = 0.74*Q;
+        else
+            V = -1.13*Q;
+
+        update_flag = 1;
+        G_ = 0;
+    } 
+    else 
+    {
+        update_flag = 0;
+        G_ = 1;
+    }
+
+    // update distance
+    update_distance = update_distance + T*vel_x;
+    update_rotation = update_rotation + T*omega_z;
+
+    if(update_distance >= 0.1) 
+    {
+        // update
+        if(update_flag == 1) 
+        {
+            K = sigma_bar*Ct / (Ct*sigma_bar*Ct + V);
+            theta_me = theta_me_bar + K*(phi_m_a_avg - Ct*theta_me_bar);
+            sigma = (1 - K*Ct)*sigma_bar;
+        } 
+        else 
+        {
+            theta_me = theta_me_bar;
+            sigma = sigma_bar;
+        }
+
+        update_distance = 0;
+    } 
+    else if(update_distance <= -0.1) 
+    {
+        // update
+        if(update_flag == 1) 
+        {
+            K = sigma_bar*Ct / (Ct*sigma_bar*Ct + V);
+            theta_me = theta_me_bar + K*(phi_m_a_avg - Ct*theta_me_bar);
+            sigma = (1 - K*Ct)*sigma_bar;
+        } 
+        else 
+        {
+            theta_me = theta_me_bar;
+            sigma = sigma_bar;
+        }
+
+        update_distance = 0;
+    } 
+    else if(update_rotation >= PI/8) 
+    {
+        // update
+        if(update_flag == 1) 
+        {
+            K = sigma_bar*Ct / (Ct*sigma_bar*Ct + V);
+            theta_me = theta_me_bar + K*(phi_m_a_avg - Ct*theta_me_bar);
+            sigma = (1 - K*Ct)*sigma_bar;
+        } 
+        else 
+        {
+            theta_me = theta_me_bar;
+            sigma = sigma_bar;
+        }
+
+        update_rotation = 0;
+    } 
+    else if(update_rotation <= -PI/8) 
+    {
+        // update
+        if(update_flag == 1) 
+        {
+            K = sigma_bar*Ct / (Ct*sigma_bar*Ct + V);
+            theta_me = theta_me_bar + K*(phi_m_a_avg - Ct*theta_me_bar);
+            sigma = (1 - K*Ct)*sigma_bar;
+        } 
+        else 
+        {
+            theta_me = theta_me_bar;
+            sigma = sigma_bar;
+        }
+
+        update_rotation = 0;
+    } 
+    else 
+    {
+        theta_me = theta_me_bar;
+        sigma = sigma_bar;
+    }
+
+    // theta_me_deg range 0~359 deg
+    theta_me_deg = theta_me * 180/PI;
+
+    if(theta_me_deg < 0)
+        theta_me_deg = theta_me_deg % 360 + 360;
+    else
+        theta_me_deg = theta_me_deg % 360;
+
+    // theta_e_deg range 0~359 deg
+    th_deg = th * 180/PI;
+
+    if(th_deg < 0)
+        th_deg = th_deg % 360 + 360;
+    else
+        th_deg = th_deg % 360;
+
+    if(fusion_flag == 1) 
+    {
+        // Kalman filter
+        L1 = 7;
+        L2 = 13;
+
+        y = theta_me;
+
+        if(bias_flag == 1) 
+            bias_add = bias_add - r_01*r_01*0.000001 + r_01*0.000000000001;
+        else
+            bias_add = 0;
+
+        // sensor fusion algorithm
+        theta_fu = (theta_fu_old + T*(w_s_d + bias_add) + L1*T*y + T*bias) / (1 + L1*T);
+        theta_fu_old = theta_fu;
+
+        bias = bias_old + L2*T*(y - theta_fu);
+        bias_old = bias;
+
+        // theta_fu_deg range 0~359 deg
+        theta_fu_deg = theta_fu * 180/PI;
+
+        if(theta_fu_deg < 0)
+            theta_fu_deg = theta_fu_deg % 360 + 360;
+        else
+            theta_fu_deg = theta_fu_deg % 360;
+
+        // theta_fu_deg_180 range -179~180 deg
+        if(theta_fu_deg > 180)
+            theta_fu_deg_180 = theta_fu_deg - 360;
+        else
+            theta_fu_deg_180 = theta_fu_deg;
+
+        theta_fu_PI = (float)theta_fu_deg_180 * PI/180; 
+    }   // if(fusion_flag == 1) end
+}
+
+// Kalman filter and observer //////////////////////////////////////////////////////////////////////////////////////////////
+
+float lpf(float input, float output_old, float frequency)
+{
+    float output = 0;
+
+    output = (output_old + frequency*T*input) / (1 + frequency*T);
+
+    return output;
+}