LDSC_Robotics_TAs / Mbed 2 deprecated car20170828

Dependencies:   mbed ros_lib_indigo

Files at this revision

API Documentation at this revision

Comitter:
tea5062001
Date:
Mon Oct 02 11:30:47 2017 +0000
Commit message:
lib

Changed in this revision

lib/LSM9DS0_SH.cpp Show annotated file Show diff for this revision Revisions of this file
lib/LSM9DS0_SH.h Show annotated file Show diff for this revision Revisions of this file
lib/led.cpp Show annotated file Show diff for this revision Revisions of this file
lib/led.h Show annotated file Show diff for this revision Revisions of this file
lib/uart_send.cpp Show annotated file Show diff for this revision Revisions of this file
lib/uart_send.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
ros_lib_indigo.lib Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r c94b2f0a4409 lib/LSM9DS0_SH.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/LSM9DS0_SH.cpp	Mon Oct 02 11:30:47 2017 +0000
@@ -0,0 +1,209 @@
+#include "LSM9DS0_SH.h"
+
+//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓GPIO registor↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
+//~~~IMU_SPI~~~//
+DigitalOut  SPI_CSG(D7,1);      // low for GYRO enable
+DigitalOut  SPI_CSXM(D6,1);     // low for ACC/MAG enable
+DigitalOut  SPI_CSXM2(D8,1);    // low for ACC/MAG enable
+
+SPI spi(D4, D5, D3);            // MOSI MISO SCLK
+//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑end of GPIO registor↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑//
+
+
+
+//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓Varible registor↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
+//~~~IMU_SPI~~~//
+short low_byte = 0x00;
+short high_byte = 0x00;
+short Buff = 0x00;
+
+float Wx = 0.0;
+float Wy = 0.0;
+float Wz = 0.0;
+
+float Ax = 0.0;
+float Ay = 0.0;
+float Az = 0.0;
+
+float Mx = 0.0;
+float My = 0.0;
+float Mz = 0.0;
+
+float M2x = 0.0;
+float M2y = 0.0;
+float M2z = 0.0;
+//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑end of Varible registor↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑//
+
+
+
+//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓init_IMU funtion↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
+void init_IMU(void)                 //initialize
+{
+    // gloable config
+    SPI_CSXM = 1;                   // high as init for disable SPI
+    SPI_CSXM2 = 1;
+    SPI_CSG = 1;
+    spi.format(8,3);                // byte width, spi mode
+    spi.frequency(2000000);         // 2MHz
+
+    // for GYRO config
+    SPI_CSG = 0;                    // start spi talking
+    spi.write(CTRL_REG1_G);
+    spi.write(0xFF);                // data rate 760 Hz / cut off 100 Hz
+    SPI_CSG = 1;                    // end spi talking
+
+    SPI_CSG = 0;                    // start spi talking
+    spi.write(CTRL_REG4_G);
+    spi.write(0x10);                // Scle 500dps
+    SPI_CSG = 1;                    // end spi talking
+
+    // for ACC config
+    SPI_CSXM = 0;                   // start spi talking
+    spi.write(CTRL_REG1_XM);
+    spi.write(0x87);                // data rate 400 Hz / Enable
+    SPI_CSXM = 1;                   // end spi talking
+
+    SPI_CSXM = 0;                   // start spi talking
+    spi.write(CTRL_REG2_XM);
+    spi.write(0xC8);                // cut off 50 Hz / Scale +-4g
+    SPI_CSXM = 1;                   // end spi talking
+
+    // for MAG config
+    SPI_CSXM = 0;                   // start spi talking
+    spi.write(CTRL_REG5_XM);
+    spi.write(0x10);                // low resolution / data rate 50Hz
+    SPI_CSXM = 1;                   // end spi talking
+
+    SPI_CSXM = 0;                   // start spi talking
+    spi.write(CTRL_REG6_XM);
+    spi.write(0x00);                // scale +-2 gauss
+    SPI_CSXM = 1;                   // end spi talking
+
+    SPI_CSXM = 0;                   // start spi talking
+    spi.write(CTRL_REG7_XM);
+    spi.write(0x00);                // power on
+    SPI_CSXM = 1;                   // end spi talking
+
+    // for MAG2 config
+    SPI_CSXM2 = 0;                  // start spi talking
+    spi.write(CTRL_REG5_XM);
+    spi.write(0x10);                // low resolution / data rate 50Hz
+    SPI_CSXM2 = 1;                  // end spi talking
+
+    SPI_CSXM2 = 0;                  // start spi talking
+    spi.write(CTRL_REG6_XM);
+    spi.write(0x00);                // scale +-2 gauss
+    SPI_CSXM2 = 1;                  // end spi talking
+
+    SPI_CSXM2 = 0;                  // start spi talking
+    spi.write(CTRL_REG7_XM);
+    spi.write(0x00);                // power on
+    SPI_CSXM2 = 1;                  // end spi talking
+}
+//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑end of init_IMU funtion↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑//
+
+
+
+//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓read_IMU funtion↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓//
+void read_IMU(void)                     // read IMU data give raw data
+{
+    // Wx
+    SPI_CSG = 0;                        // start spi talking Wx
+    spi.write(0xE8);                    // read B11101000 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSG = 1;                        // end spi talking
+    Buff = high_byte << 8 | low_byte; 
+    Wx = Buff * Gpx;
+    // Wy
+    SPI_CSG = 0;                        // start spi talking Wy
+    spi.write(0xEA);                    // read B11101010 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSG = 1;                        // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    Wy = Buff * Gpy;
+    // Wz
+    SPI_CSG = 0;                        // start spi talking Wz
+    spi.write(0xEC);                    // read B11101100 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSG = 1;                        // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    Wz = Buff * Gpz;
+    // Ax
+    SPI_CSXM = 0;                       // start spi talking Ax
+    spi.write(0xE8);                    // read B11101000 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSXM = 1;                       // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    Ax = Buff * Apx;
+    // Ay
+    SPI_CSXM = 0;                       // start spi talking Ay
+    spi.write(0xEA);                    // read B11101010 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSXM = 1;                       // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    Ay = Buff * Apy;
+    // Az
+    SPI_CSXM = 0;                       // start spi talking Az
+    spi.write(0xEC);                    // read B11101100 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSXM = 1;                       // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    Az = Buff * Apz;
+    // Mx
+    SPI_CSXM = 0;                       // start spi talking Mx
+    spi.write(0xC8);                    // read B11001000 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSXM = 1;                       // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    Mx = Buff * Mp;
+    // My
+    SPI_CSXM = 0;                       // start spi talking My
+    spi.write(0xCA);                    // read B11001010 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSXM = 1;                       // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    My = Buff * Mp;
+    // Mz
+    SPI_CSXM = 0;                       // start spi talking Mz
+    spi.write(0xCC);                    // read B11001100 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSXM = 1;                       // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    Mz = Buff * Mp;
+
+    // M2x
+    SPI_CSXM2 = 0;                      // start spi talking M2x
+    spi.write(0xC8);                    // read B11001000 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSXM2 = 1;                      // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    M2x = Buff * Mp;
+    // M2y
+    SPI_CSXM2 = 0;                      // start spi talking M2y
+    spi.write(0xCA);                    // read B11001010 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSXM2 = 1;                      // end spi talking
+    Buff = high_byte << 8 | low_byte;
+    M2y = Buff * Mp;
+    // M2z
+    SPI_CSXM2 = 0;                      // start spi talking M2z
+    spi.write(0xCC);                    // read B11001100 read / multi / address
+    low_byte = spi.write(0);
+    high_byte = spi.write(0);
+    SPI_CSXM2 = 1;                      // end spi talking
+    Buff = high_byte << 8 |low_byte;
+    M2z = Buff * Mp;
+}
+//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑end of read_IMU funtion↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑//
+
diff -r 000000000000 -r c94b2f0a4409 lib/LSM9DS0_SH.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/LSM9DS0_SH.h	Mon Oct 02 11:30:47 2017 +0000
@@ -0,0 +1,100 @@
+#ifndef LSM9DS0_SH_H
+#define LSM9DS0_SH_H
+
+#include "mbed.h"
+
+// IMU gain //
+#define Gpx 3.054e-4f       
+#define Gpy 3.054e-4f       
+#define Gpz 3.054e-4f       
+
+#define Apx -1.197e-3f      
+#define Apy -1.197e-3f
+#define Apz -1.197e-3f
+
+#define Mp 8e-5f
+
+#define PI 3.14159
+
+//~~~IMU_SPI~~~//
+extern DigitalOut  SPI_CSG;      // low for GYRO enable
+extern DigitalOut  SPI_CSXM;     // low for ACC/MAG enable
+extern DigitalOut  SPI_CSXM2;    // low for ACC/MAG enable
+
+extern SPI spi;                  // MOSI MISO SCLK
+
+//~~~IMU_SPI~~~//
+extern short low_byte;
+extern short high_byte;
+extern short Buff;
+
+extern float Wx;
+extern float Wy;
+extern float Wz;
+
+extern float Ax;
+extern float Ay;
+extern float Az;
+
+extern float Mx;
+extern float My;
+extern float Mz;
+
+extern float M2x;
+extern float M2y;
+extern float M2z;
+
+extern void init_IMU();             // initialize IMU
+extern void read_IMU();             // read IMU data give raw data
+
+// LSM9DS0 Gyro Registers //
+#define WHO_AM_I_G          0x0F    // r     // WHO_G
+#define CTRL_REG1_G         0x20    // rw    // GYRO Data-rate/LPF/Enable
+#define CTRL_REG2_G         0x21    // rw
+#define CTRL_REG3_G         0x22    // rw
+#define CTRL_REG4_G         0x23    // rw    // GYRO Scale
+#define CTRL_REG5_G         0x24    // rw
+#define REFERENCE_G         0x25    // rw
+#define STATUS_REG_G        0x27    // r
+#define OUT_X_L_G           0x28    // r     // GYRO Data
+#define OUT_X_H_G           0x29    // r     // GYRO Data
+#define OUT_Y_L_G           0x2A    // r     // GYRO Data
+#define OUT_Y_H_G           0x2B    // r     // GYRO Data
+#define OUT_Z_L_G           0x2C    // r     // GYRO Data
+#define OUT_Z_H_G           0x2D    // r     // GYRO Data
+
+// LSM9DS0 Accel/Magneto (XM) Registers //
+#define OUT_TEMP_L_XM       0x05    // r     // TEMP Data
+#define OUT_TEMP_H_XM       0x06    // r     // TEMP Data
+#define STATUS_REG_M        0x07    // r
+#define OUT_X_L_M           0x08    // r     // MAG Data
+#define OUT_X_H_M           0x09    // r     // MAG Data
+#define OUT_Y_L_M           0x0A    // r     // MAG Data
+#define OUT_Y_H_M           0x0B    // r     // MAG Data
+#define OUT_Z_L_M           0x0C    // r     // MAG Data
+#define OUT_Z_H_M           0x0D    // r     // MAG Data
+#define WHO_AM_I_XM         0x0F    // r     // WHO_XM
+#define OFFSET_X_L_M        0x16    // rw    // MAG Data_Offset
+#define OFFSET_X_H_M        0x17    // rw    // MAG Data_Offset
+#define OFFSET_Y_L_M        0x18    // rw    // MAG Data_Offset
+#define OFFSET_Y_H_M        0x19    // rw    // MAG Data_Offset
+#define OFFSET_Z_L_M        0x1A    // rw    // MAG Data_Offset
+#define OFFSET_Z_H_M        0x1B    // rw    // MAG Data_Offset
+#define CTRL_REG0_XM        0x1F    // rw
+#define CTRL_REG1_XM        0x20    // rw    // ACC Data-rate/Enable
+#define CTRL_REG2_XM        0x21    // rw    // ACC LPF/Scale
+#define CTRL_REG3_XM        0x22    // rw
+#define CTRL_REG4_XM        0x23    // rw
+#define CTRL_REG5_XM        0x24    // rw    // TEMP Enable, MAG Data-rate
+#define CTRL_REG6_XM        0x25    // rw    // MAG Scale
+#define CTRL_REG7_XM        0x26    // rw
+#define STATUS_REG_A        0x27    // r
+#define OUT_X_L_A           0x28    // r     // ACC Data
+#define OUT_X_H_A           0x29    // r     // ACC Data
+#define OUT_Y_L_A           0x2A    // r     // ACC Data
+#define OUT_Y_H_A           0x2B    // r     // ACC Data
+#define OUT_Z_L_A           0x2C    // r     // ACC Data
+#define OUT_Z_H_A           0x2D    // r     // ACC Data
+
+#endif  // LSM9DS0_SH_H
+
diff -r 000000000000 -r c94b2f0a4409 lib/led.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/led.cpp	Mon Oct 02 11:30:47 2017 +0000
@@ -0,0 +1,12 @@
+#include "led.h"
+
+// LED IO
+DigitalInOut BK_(A0, PIN_OUTPUT, OpenDrain, 1);      // 1 : dark
+DigitalInOut B_(A1, PIN_OUTPUT, OpenDrain, 1);
+DigitalInOut W_(A2, PIN_OUTPUT, OpenDrain, 1);
+DigitalInOut Y_(A3, PIN_OUTPUT, OpenDrain, 1);
+DigitalInOut G_(A4, PIN_OUTPUT, OpenDrain, 1);
+DigitalInOut R_(A5, PIN_OUTPUT, OpenDrain, 1);
+
+// measure timer length
+DigitalOut myled(D13);
diff -r 000000000000 -r c94b2f0a4409 lib/led.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/led.h	Mon Oct 02 11:30:47 2017 +0000
@@ -0,0 +1,15 @@
+#ifndef LED_H
+#define LED_H
+
+#include "mbed.h"
+
+extern DigitalInOut BK_;      
+extern DigitalInOut B_;
+extern DigitalInOut W_;
+extern DigitalInOut Y_;
+extern DigitalInOut G_;
+extern DigitalInOut R_;
+
+extern DigitalOut myled;
+
+#endif       // LED_H
diff -r 000000000000 -r c94b2f0a4409 lib/uart_send.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/uart_send.cpp	Mon Oct 02 11:30:47 2017 +0000
@@ -0,0 +1,64 @@
+#include "uart_send.h"
+
+Serial uart_1(D10,D2);            // TX : D10     RX : D2           // serial 1
+//Serial uart_2(PC_10,PC_11);       // TX : PC_10   RX : PC_11        // serial 3
+
+// uart send data
+int display[12] = {0};
+char num[26] = {254,255,0};       // char num[0] , num[1] : 2 start byte
+int i = 0;
+
+void init_uart(void)
+{
+    uart_1.baud(230400);      
+//    uart_2.baud(230400);
+}
+
+void uart_send(int display[12])
+{
+    num[2] = display[0] >> 8;           // HSB(8bit)
+    num[3] = display[0] & 0x00ff;       // LSB(8bit)
+    num[4] = display[1] >> 8;
+    num[5] = display[1] & 0x00ff;
+    num[6] = display[2] >> 8;
+    num[7] = display[2] & 0x00ff;
+    num[8] = display[3] >> 8;
+    num[9] = display[3] & 0x00ff;
+    num[10] = display[4] >> 8;
+    num[11] = display[4] & 0x00ff;
+    num[12] = display[5] >> 8;
+    num[13] = display[5] & 0x00ff;
+    num[14] = display[6] >> 8;
+    num[15] = display[6] & 0x00ff;
+    num[16] = display[7] >> 8;
+    num[17] = display[7] & 0x00ff;
+    num[18] = display[8] >> 8;
+    num[19] = display[8] & 0x00ff;
+    num[20] = display[9] >> 8;
+    num[21] = display[9] & 0x00ff;
+    num[22] = display[10] >> 8;
+    num[23] = display[10] & 0x00ff;
+    num[24] = display[11] >> 8;
+    num[25] = display[11] & 0x00ff;
+
+    int j = 0;
+    int k = 1;
+    while(k) 
+    {
+        if(uart_1.writeable()) 
+        {
+            uart_1.putc(num[i]);
+            i++;
+            j++;
+        }
+
+        if(j>5) 
+        {                   // send 6 bytes
+            k = 0;
+            j = 0;
+        }
+    }
+
+    if(i>25)
+        i = 0;
+}
diff -r 000000000000 -r c94b2f0a4409 lib/uart_send.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/uart_send.h	Mon Oct 02 11:30:47 2017 +0000
@@ -0,0 +1,16 @@
+#ifndef UART_SEND_H
+#define UART_SEND_H
+
+#include "mbed.h"
+
+extern Serial uart_1;            
+//extern Serial uart_2;
+
+extern int display[12];
+extern char num[26];
+extern int i;
+
+extern void init_uart(void);
+extern void uart_send(int display[12]);
+
+#endif       // UART_SEND_H
diff -r 000000000000 -r c94b2f0a4409 main.cpp
--- /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;
+}
diff -r 000000000000 -r c94b2f0a4409 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Oct 02 11:30:47 2017 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/mbed_official/code/mbed/builds/e2bfab296f20
\ No newline at end of file
diff -r 000000000000 -r c94b2f0a4409 ros_lib_indigo.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ros_lib_indigo.lib	Mon Oct 02 11:30:47 2017 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/garyservin/code/ros_lib_indigo/#fd24f7ca9688