This program is made for the GPS Robot Car contest 2014

Dependencies:   Servo TextLCD USBHost mbed

/media/uploads/hayama/gpsrobotcar-small.jpg

Presentation for Geospatial EXPO 2014. /media/uploads/hayama/presen.pdf

Revision:
0:c2262bac9aa6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Nov 13 15:33:47 2014 +0000
@@ -0,0 +1,1296 @@
+#include "mbed.h"
+#include "TextLCD.h"
+#include "Servo.h"
+#include "USBHostSerial.h"
+
+#define POSC 0.5
+#define KANG    5      // factor of gyro output to angle rot right + val  
+#define GYROADJ (-0.0001)   
+#define FSMTHS  1      // smoothing factor for sensors
+
+// 各種定数または初期値の設定
+#define PI 3.14159                      // pai
+#define DEF_TNUM    1
+
+// メニュー関係
+int nmenu=36;
+const char *menuS[36]={       // メニューの文字列       
+    "Disp GPS        ","Set way point   ","Disp way point  ","Clear way point ","Read way point  ",
+    "Write way point ","Set team number ","Set QZSS Wp ","Read QZSS Wp    ","Write QZSS Wp   ",
+    "Disp QZSS Msg   ","Clear QZSS Msg  ","Read QZSS Msg   ","Write QZSS Msg  ","Run GPS no Gyro ",
+    "Run GPS use Gyro","Run QZSS no Gyro","Run QZSS use Gyr","Test servo      ","Test motor      ",
+    "Init neutral    ","Init steer min  ","Set steer max   ","Init WP radius  ","Init Ks         ",
+    "Init KsGyro     ","Init PosH       ","Init PosL       ","Init Speed H    ","Init Speed L    ",
+    "Test Run        ","Write parameter ","Read Parameter  ","Test encoder    ","Test Gyro       ",
+    "Test Compus     "
+}; 
+
+const double arrayCompus[]={180,225,45,0,135,270,90,315};
+volatile double dirCompus;
+double rdCpy, dirCompusCpy;
+
+int pmode=0;
+volatile int recvGPS=0;
+volatile int recvQZSS=0;
+volatile long encR=0, encRB=0;
+volatile long encL=0, encLB=0;
+volatile int  cntR=0; 
+volatile int  cntL=0;
+volatile int  cntC=0;  // center both cntR and cntL
+volatile int  cntE=0;  // timing counter for cntR/L read
+
+// gyro sensor  
+volatile float gyro, gyItg, gyOff;  
+volatile float angle; 
+
+// ウェイポイント設定(基準点からのN,E方向への座標)、最高16ポイント
+int np=0;  // soukoutyuu目標ポイントナンバー
+int wp=0;  // number of waypoint, initial value read from file of "waypoint.txt"
+double wy[16]={0};  // latitude of waypoints
+double wx[16]={0};  // longitude of waypoints
+
+// QZSS-ウェイポイント設定(基準点からのN,E方向への座標)、最高16ポイント
+int  npQ=0;                              // 目標ポイントナンバー
+int  wpQ=0;                              // wp:0-15まで,ウェイポイントの数 -1
+double wyQ11,wxQ11;
+double wyQ[8][8]={0};   // index 1 to 7,  wyQ[A],[B]
+double wxQ[8][8]={0};   // index 1 to 7,  wxQ[A],[B]
+
+double xQ11,yQ11,xQ71,yQ71,xQ17,yQ17,xQ77,yQ77,dxQ71,dyQ71,dxQ17,dyQ17;
+double theta;
+double magx,magy;
+  
+
+// 走行処理関係変数
+double gy, gx;                          // 北緯,東経を原点からの距離(メートル)に数値化
+double ry, rx, rv, rd;                  // 北緯(正規化),東経(正規化),速度(ノット),方向(単位:度)の数値化
+double dy, dx, dr, dd;                  // ウェイポイントに対する北緯,東経の差分(m),距離の差分,方位の差分
+double ddCpy;                           // 走行中にddの保存
+
+double wr;                              // ウェイポイントの半径
+double ks;                              // ステアリング切れ角比例係数
+double ksg;                             // ステアリング切れ角比例係数, with gyro
+
+float strn;                               // ニュートラルの位置 
+float posSteer;                           // ステアリングの位置
+float strmin;                           // ステアリングの最小値
+float strmax;                           // ステアリングの最大値
+float posH, posL;                       // servo position for high/low speed of motor
+int spdH,spdL;                         // スピード, count of encoder per 100ms
+
+
+// GPS受信用変数,ポインタ
+char str[200];                          // GPSほか読み取りのための文字列バッファ
+char *header;
+char *latitude, *longitude, *knot, *direct;   
+double latit, longit, kn;               // 緯度,経度,ノット保存用の変数
+double latitB, longitB, rdB;            // 差分で方位計算する時に前の座標保持用, 方位保管用
+double dy2, dx2, rd2;                   // 一つ前の値との北緯,東経の差分(m),差分で求めた方位
+
+// QZSS
+char strtmp[10];
+char *messages;
+long teamNum,year,numA,sizeA,numB,sizeB,numT;
+long startA, startB;
+long targetA[20];
+long targetB[20];
+long tNum=0;
+
+InterruptIn ptR(p5);
+InterruptIn ptL(p6);
+//DigitalIn S3(p7)-S4(p8);
+
+DigitalIn resetSW(p13);
+DigitalIn setSW(p14);
+DigitalIn startSW(p9);
+DigitalOut led(p21);
+
+AnalogIn gyroOut(p15); 
+//AnalogIn A2(p16)-(p20);
+
+Servo strServo(p26);
+Servo motorAmp(p25);
+//Servo servoC3(p24)-(p21);
+
+BusIn compus(p18, p19, p20);        // compus, 3bit 8 direction 
+BusOut  leds( LED3, LED2, LED1);            // for LED display
+TextLCD lcd(p11, p12, p27, p28, p29, p30);  // rs, e, d4-d7
+Ticker timerS;                              // defince interval timer 
+Timer timer;
+Serial pc(USBTX, USBRX);
+LocalFileSystem local("local"); 
+
+
+//-------------------------------------------------------------------------- 
+// 走行パラメータを読み書き
+//-------------------------------------------------------------------------- 
+void writeParam(){
+    FILE *fp = fopen("/local/param.txt","w");  
+        fprintf(fp, "%f\n",wr);
+        fprintf(fp, "%f\n",ks);
+        fprintf(fp, "%f\n",ksg);
+        fprintf(fp, "%f\n",strmin);
+        fprintf(fp, "%f\n",strmax);
+        fprintf(fp, "%f\n",strn);
+        fprintf(fp, "%f\n",posH);
+        fprintf(fp, "%f\n",posL);
+        fprintf(fp, "%d\n",spdH);
+        fprintf(fp, "%d\n",spdL);
+    fclose(fp);
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000); 
+}
+
+void readParam(){  
+    char st[20];
+    FILE *fp = fopen("/local/param.txt","r");                      
+        fgets(st,20,fp); wr=atof(st);
+        fgets(st,20,fp); ks=atof(st);
+        fgets(st,20,fp); ksg=atof(st);
+        fgets(st,20,fp); strmin=atof(st);
+        fgets(st,20,fp); strmax=atof(st);
+        fgets(st,20,fp); strn=atof(st);
+        fgets(st,20,fp); posH=atof(st);
+        fgets(st,20,fp); posL=atof(st);
+        fgets(st,20,fp); spdH=atoi(st);
+        fgets(st,20,fp); spdL=atoi(st);
+    fclose(fp);
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000); 
+}
+
+//-------------------------------------------------------------------------- 
+// ウェイポイントの保管と読み出し
+//-------------------------------------------------------------------------- 
+void writeWp(){
+    FILE *fp = fopen("/local/waypoint.txt","w");  
+    fprintf(fp, "%d\n",wp);
+    for(int i=0;i<wp;i++){
+        fprintf(fp,"%f\n",wy[i]);
+        fprintf(fp,"%f\n",wx[i]);
+    }
+    fclose(fp);
+    
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000); 
+}
+    
+void readWp(){
+    char st[20];
+    FILE *fp = fopen("/local/waypoint.txt","r");                      
+    fgets(st,20,fp); wp=atof(st);
+    for(int i=0;i<wp;i++){
+        fgets(st,20,fp); wy[i]=atof(st);
+        fgets(st,20,fp); wx[i]=atof(st);
+    } 
+    fclose(fp);
+    
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000); 
+}
+
+// QZSS message file out            
+void writeQmsg(){
+    FILE *fp = fopen("/local/QZmsg.txt","w");  
+    fprintf(fp, "%d\n",year);
+    fprintf(fp, "%d\n",teamNum);
+    fprintf(fp, "%d\n",numA);
+    fprintf(fp, "%d\n",sizeA);
+    fprintf(fp, "%d\n",numB);
+    fprintf(fp, "%d\n",sizeB);
+    fprintf(fp, "%d\n",numT);
+    fprintf(fp, "%d\n",startA);
+    fprintf(fp, "%d\n",startB);
+    for(int i=0; i<numT; i++){
+        fprintf(fp,"%d\n",targetA[i]); // 座標のインデックスは1から、配列のインデックスは0から
+        fprintf(fp,"%d\n",targetB[i]);
+    }
+    fprintf(fp, "%d\n",recvQZSS);
+    fclose(fp); 
+    
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000);                
+}
+
+// QZSS message file in    
+void readQmsg(){
+    char st[20];
+    FILE *fp = fopen("/local/QZmsg.txt","r");                     
+    fgets(st,20,fp); year=atoi(st);
+    fgets(st,20,fp); teamNum=atoi(st); 
+    fgets(st,20,fp); numA=atoi(st);
+    fgets(st,20,fp); sizeA=atoi(st);
+    fgets(st,20,fp); numB=atoi(st);
+    fgets(st,20,fp); sizeB=atoi(st);
+    fgets(st,20,fp); numT=atoi(st);
+    fgets(st,20,fp); startA=atoi(st);
+    fgets(st,20,fp); startB=atoi(st);
+    for(int i=0; i<numT; i++){
+        fgets(st,20,fp); targetA[i]=atof(st);  // 座標のインデックスは1から、配列のインデックスは0から
+        fgets(st,20,fp); targetB[i]=atof(st);
+    }     
+    fgets(st,20,fp); recvQZSS=atoi(st); 
+    if (recvQZSS==1) tNum=teamNum;
+    fclose(fp);
+    
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000); 
+}
+
+//-------------------------------------------------------------------------- 
+//  ウェイポイントの設定   
+//  (GPSが受信できてない時はポイント追加できない)
+//-------------------------------------------------------------------------- 
+void setWp(){
+  lcd.locate(0,1); lcd.printf("present WP: %d   ",wp); // ウェイポイント番号を進表示
+  while (resetSW==1){      // STARTスイッチが押されたら抜ける
+    
+    // start-swが押されたらウェイポイントを記録   
+    if (startSW==0) {      
+      Thread::wait(10);                   
+      while(startSW==0);      // チャタリング防止
+      Thread::wait(10);   
+
+      // GPRMCを受信できて値が正常であるまで待つ 
+      while(recvGPS==0 || (latit==0) || (longit==0));  
+
+      wy[wp] = latit; 
+      wx[wp] = longit;
+      lcd.locate(0,1); lcd.printf("set WP: %d      ",wp);
+      Thread::wait(2000); 
+      lcd.locate(0,0); lcd.printf("wy[%d]=%f   \n", wp, wy[wp]);
+      lcd.locate(0,1); lcd.printf("wx[%d]=%f   \n", wp, wx[wp]);   
+      Thread::wait(2000);             
+      wp++; if (wp>15) wp=15;  // 次のウェイポイント入力状態にするウェイポイントの追加は15まで、0からで計16個        
+      // ウェイポイント追加
+    }
+
+    // set-swが押されたらウェイポイントdecrement   
+    if (setSW==0) {      
+      Thread::wait(10);                   
+      while(setSW==0);      // チャタリング防止
+      Thread::wait(10); 
+      wp--; if (wp<0) wp=0; 
+      wy[wp] =0;
+      wx[wp] =0; 
+      lcd.locate(0,1); lcd.printf("delete WP: %d     ",wp);
+      Thread::wait(2000); 
+      lcd.locate(0,0); lcd.printf("wy[%d]=%f   \n", wp, wy[wp]);
+      lcd.locate(0,1); lcd.printf("wx[%d]=%f   \n", wp, wx[wp]);   
+      Thread::wait(2000);  
+    }
+        
+    lcd.cls();
+    lcd.printf("LA=%f \n", latit);
+    lcd.printf("LO=%f \n", longit);
+    Thread::wait(200); 
+  }
+}
+
+//-------------------------------------------------------------------------- 
+//  display way point
+//-------------------------------------------------------------------------- 
+void dispWp(){
+    if(wp==0){
+        lcd.locate(0,1); lcd.printf("no way point !!  "); 
+        return;
+    }
+    int i=0;
+    lcd.cls();
+    while(resetSW==1){
+        if (setSW==0){               
+            Thread::wait(10); 
+            while (setSW==0);
+            Thread::wait(10);  
+            i--; if (i<0) i=wp-1;         
+        }
+        if (startSW==0){               
+            Thread::wait(10); 
+            while (startSW==0);
+            Thread::wait(10);  
+            i++; if (i==wp) i=0;        
+        }
+        lcd.locate(0,0); lcd.printf("wy[%d]=%f   \n", i, wy[i]);
+        lcd.locate(0,1); lcd.printf("wx[%d]=%f   \n", i, wx[i]); 
+        Thread::wait(200); 
+    }
+    Thread::wait(200); 
+}
+//-------------------------------------------------------------------------- 
+//  ウェイポイントの消去
+//-------------------------------------------------------------------------- 
+void clearWp(){
+  wp=0;
+  for(int i=0;i<16;i++){ wy[i]=0; wx[i]=0; }
+  lcd.locate(0,1); lcd.printf("Completed!      "); 
+  Thread::wait(1000); 
+}
+
+//-------------------------------------------------------------------------- 
+//  QZSS display way point
+//-------------------------------------------------------------------------- 
+void dispQmsg(){
+    int i=0;
+    
+    if (recvQZSS==1){
+        lcd.locate(0,1); lcd.printf("QZSS message OK!"); 
+    } else { 
+        lcd.locate(0,1); lcd.printf("QZSS no message "); 
+    }
+    Thread::wait(3000); 
+    
+    while(resetSW==1){
+        if (setSW==0){               
+            Thread::wait(10); 
+            while (setSW==0);
+            Thread::wait(10);  
+            i--; if (i<0) i=24;
+        }
+        if (startSW==0){               
+            Thread::wait(10); 
+            while (startSW==0);
+            Thread::wait(10);  
+            i++; if (i>24) i=0;
+        }
+        switch (i){
+            case 0: lcd.locate(0,1); lcd.printf("year=%d          \n", year); break;
+            case 1: lcd.locate(0,1); lcd.printf("teamNum=%d       \n", teamNum); break;
+            case 2: lcd.locate(0,1); lcd.printf("numA=%d          \n", numA); break;
+            case 3: lcd.locate(0,1); lcd.printf("sizeA=%d         \n", sizeA); break;
+            case 4: lcd.locate(0,1); lcd.printf("numB=%d          \n", numB); break;
+            case 5: lcd.locate(0,1); lcd.printf("sizeB=%d         \n", sizeB); break;
+            case 6: lcd.locate(0,1); lcd.printf("numT=%d          \n", numT); break;
+            case 7: lcd.locate(0,1); lcd.printf("startA=%d        \n", startA); break;
+            case 8: lcd.locate(0,1); lcd.printf("startB=%d        \n", startB); break;
+            case 9: lcd.locate(0,1); lcd.printf("targetA[1]=%d    \n", targetA[0]); break;  // 座標のインデックスは1から、配列のインデックスは0から
+            case 10: lcd.locate(0,1); lcd.printf("targetB[1]=%d   \n", targetB[0]); break;
+            case 11: lcd.locate(0,1); lcd.printf("targetA[2]=%d   \n", targetA[1]); break;
+            case 12: lcd.locate(0,1); lcd.printf("targetB[2]=%d   \n", targetB[1]); break;
+            case 13: lcd.locate(0,1); lcd.printf("targetA[3]=%d   \n", targetA[2]); break;
+            case 14: lcd.locate(0,1); lcd.printf("targetB[3]=%d   \n", targetB[2]); break;
+            case 15: lcd.locate(0,1); lcd.printf("targetA[4]=%d   \n", targetA[3]); break;
+            case 16: lcd.locate(0,1); lcd.printf("targetB[4]=%d   \n", targetB[3]); break;
+            case 17: lcd.locate(0,1); lcd.printf("targetA[5]=%d   \n", targetA[4]); break;
+            case 18: lcd.locate(0,1); lcd.printf("targetB[5]=%d   \n", targetB[4]); break;
+            case 19: lcd.locate(0,1); lcd.printf("targetA[6]=%d   \n", targetA[5]); break;
+            case 20: lcd.locate(0,1); lcd.printf("targetB[6]=%d   \n", targetB[5]); break;
+            case 21: lcd.locate(0,1); lcd.printf("targetA[7]=%d   \n", targetA[6]); break;
+            case 22: lcd.locate(0,1); lcd.printf("targetB[7]=%d   \n", targetB[6]); break;
+            case 23: lcd.locate(0,1); lcd.printf("targetA[8]=%d   \n", targetA[7]); break;
+            case 24: lcd.locate(0,1); lcd.printf("targetB[8]=%d   \n", targetB[7]); break;
+        }
+        Thread::wait(100); 
+    }
+    Thread::wait(200); 
+}
+
+//-------------------------------------------------------------------------- 
+//  QZSS ウェイポイントの消去
+//-------------------------------------------------------------------------- 
+void clearQmsg(){
+    for(int i=0;i<numT;i++){ targetA[i]=targetB[i]=0; } 
+    year=teamNum=numA=sizeA=numB=sizeB=numT=startA=startB=0;
+    recvQZSS=0;
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000); 
+}
+
+
+//-------------------------------------------------------------------------- 
+// set team number, inc by startSW, dec by setSW, max 25
+// compare to the teamNum from QZSS massage
+//-------------------------------------------------------------------------- 
+void setTeamNum(){
+  while(resetSW==1){
+    if (startSW==0){tNum++; if (tNum>25) tNum=0;}  
+    if (setSW==0)  {tNum--; if (tNum<0) tNum=25;} 
+    lcd.locate(0,1); lcd.printf("team number=%d \n", tNum);
+    Thread::wait(200); 
+  }
+}
+
+
+// calculation of all QZSS waypoint from 4 point
+void calcQZWp(){
+ 
+  wxQ11=wxQ[1][1]; wyQ11=wyQ[1][1];
+  xQ11=wxQ[1][1]-wxQ11; yQ11=wyQ[1][1]-wyQ11; // (A1,B1) 
+  xQ71=wxQ[7][1]-wxQ11; yQ71=wyQ[7][1]-wyQ11; // (A7,B1)
+  xQ17=wxQ[1][7]-wxQ11; yQ17=wyQ[1][7]-wyQ11; // (A1,B7)  
+  xQ77=wxQ[7][7]-wxQ11; yQ77=wyQ[7][7]-wyQ11; // (A7,B7) 
+    
+  dxQ71=xQ71-xQ11; dyQ71=yQ71-yQ11;
+  dxQ17=xQ17-xQ11; dyQ17=yQ17-yQ11;
+  
+  theta=atan(dxQ71/dyQ71);
+  magx=sqrt(dxQ71*dxQ71+dyQ71*dyQ71)/6;
+  magy=sqrt(dxQ17*dxQ17+dyQ17*dyQ17)/6;
+  
+  for (int i=1;i<8;i++){
+    for(int j=1;j<8;j++){
+      wxQ[i][j]=magx*(j-1)*cos(theta)-magy*(i-1)*sin(theta)+wxQ11;
+      wyQ[i][j]=magx*(j-1)*sin(theta)+magy*(i-1)*cos(theta)+wyQ11;
+    }
+  }  
+}
+
+
+// set QZSS way point for (A1,B1)(A7,B1)(A1,B7)(A7,B7)
+void setQZWp(){
+  int qa=1,qb=1;
+  int qn=3;
+  
+  while (resetSW==1){      // STARTスイッチが押されたら抜ける
+
+    // set-swが押されたらchange A,B axis 
+    if (setSW==0) {      
+      Thread::wait(10);                   
+      while(setSW==0);      // チャタリング防止
+      Thread::wait(10); 
+      
+      qn++; if (qn>3) qn=0;  // 次のウェイポイント入力状態にするウェイポイントの追加は15まで、0からで計16個        
+      switch(qn){
+          case 0: qa=1; qb=1; break;
+          case 1: qa=7; qb=1; break;
+          case 2: qa=1; qb=7; break;
+          case 3: qa=7; qb=7; break;
+      }
+      lcd.cls();          
+      lcd.locate(0,1); lcd.printf("(A%d,B%d)", qa,qb);   
+      Thread::wait(2000);
+      lcd.cls();  
+      lcd.locate(0,0); lcd.printf("wyQ[%d][%d]=%f   \n", qa,qb, wyQ[qa][qb]);
+      lcd.locate(0,1); lcd.printf("wxQ[%d][%d]=%f   \n", qa,qb, wxQ[qa][qb]);         
+      Thread::wait(2000);  
+    }
+        
+    // start-swが押されたらウェイポイントを記録   
+    if (startSW==0) {      
+      Thread::wait(10);                   
+      while(startSW==0);      // チャタリング防止
+      Thread::wait(10);   
+
+      // GPRMCを受信できて値が正常であるまで待つ 
+      while(recvGPS==0 || (latit==0) || (longit==0));  
+
+      wyQ[qa][qb] = latit; 
+      wxQ[qa][qb] = longit;
+      lcd.cls();  
+      lcd.locate(0,0); lcd.printf("wyQ[%d][%d]=%f   \n", qa,qb, wyQ[qa][qb]);
+      lcd.locate(0,1); lcd.printf("wxQ[%d][%d]=%f   \n", qa,qb, wxQ[qa][qb]);   
+      Thread::wait(2000);             
+    }
+        
+    lcd.cls();
+    lcd.printf("LA=%f \n", latit);
+    lcd.printf("LO=%f \n", longit);
+    Thread::wait(200); 
+  }
+  calcQZWp();
+}
+  
+// file out QZSS way point, 4 point only
+void writeQZWp4(){
+    FILE *fp = fopen("/local/QZpoint4.txt","w");  
+        fprintf(fp, "%f\n",xQ11);
+        fprintf(fp, "%f\n",yQ11);
+        fprintf(fp, "%f\n",xQ71);
+        fprintf(fp, "%f\n",yQ71);
+        fprintf(fp, "%f\n",xQ17);
+        fprintf(fp, "%f\n",yQ17);
+        fprintf(fp, "%f\n",xQ77);
+        fprintf(fp, "%f\n",yQ77);        
+    fclose(fp);
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000);     
+}    
+    
+// file read QZSS way point, 4 point only
+void readQZWp4(){
+     char st[20];
+    FILE *fp = fopen("/local/QZpoint4.txt","r");                      
+        fgets(st,20,fp); xQ11=atof(st); 
+        fgets(st,20,fp); yQ11=atof(st); 
+        fgets(st,20,fp); xQ71=atof(st); 
+        fgets(st,20,fp); yQ71=atof(st); 
+        fgets(st,20,fp); xQ17=atof(st); 
+        fgets(st,20,fp); yQ17=atof(st); 
+        fgets(st,20,fp); xQ77=atof(st); 
+        fgets(st,20,fp); yQ77=atof(st); 
+    fclose(fp);
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000); 
+    calcQZWp();   
+}
+
+
+// file out QZSS way point
+void writeQZWp(){
+    FILE *fp = fopen("/local/QZpoint.txt","w");  
+        for(int i=1;i<8;i++){
+            for(int j=1;j<8;j++){
+                fprintf(fp, "%f\n",wyQ[i][j]);
+                fprintf(fp, "%f\n",wxQ[i][j]);
+            }
+        }
+    fclose(fp);
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000);     
+}    
+    
+// file read QZSS way point
+void readQZWp(){
+     char st[20];
+    FILE *fp = fopen("/local/QZpoint.txt","r");                      
+        for(int i=1;i<8;i++){
+            for(int j=1;j<8;j++){
+                fgets(st,20,fp); wyQ[i][j]=atof(st); 
+                fgets(st,20,fp); wxQ[i][j]=atof(st); 
+            }
+        }
+    fclose(fp);
+    lcd.locate(0,1); lcd.printf("Completed!      "); 
+    Thread::wait(1000);    
+}
+                   
+            
+//-------------------------------------------------------------------------- 
+//  スムージング関数(cData:現在のデータ,pData:一つ前のデータ,factor:係数,大きい現在地の割合大きい                                                   
+//-------------------------------------------------------------------------- 
+float smooth(float cData, float pData, float factor){
+  return(cData*factor + pData*(1-factor));
+}
+
+//-------------------------------------------------------------------------- 
+// count up by encoder 
+//-------------------------------------------------------------------------- 
+void countR(){
+    encR++; 
+}
+void countL(){
+    encL++; 
+}
+
+//-------------------------------------------------------------------------- 
+//  ジャイロのオフセット取得           
+//-------------------------------------------------------------------------- 
+int gyro_offset(void){
+    int i,tmp;
+
+    lcd.cls();   
+    Thread::wait(1000);
+    gyOff=0;
+    for (i=0;i<16;i++){
+        gyOff+=gyroOut;     // read gyro sensor     
+        Thread::wait(10);     
+    }
+    gyOff=gyOff/16+GYROADJ;
+    
+    gyItg=0;  
+    for (i=0;i<10;i++){
+        tmp=(int)(fabs(angle));
+        lcd.locate(0,1); lcd.printf("angle=%d \n", tmp); 
+        Thread::wait(100);
+    }
+    return ((int)fabs(angle));                  // スタートスイッチで復帰,ただしジャイロ使えないレベル                                                          
+}
+
+//-------------------------------------------------------------------------- 
+//  ジャイロのリセット          
+//-------------------------------------------------------------------------- 
+void gyro_reset(void){
+    gyItg=0;
+    angle=0;
+}
+
+//-------------------------------------------------------------------------- 
+// interrupt by us timerS                                             
+//-------------------------------------------------------------------------- 
+void sensor() {  
+    // read gyro sensor
+    gyro=-(gyroOut-gyOff);        
+    gyItg+=gyro;
+    angle=gyItg*KANG;
+    
+    cntE++; if (cntE>200){
+        cntE=0;
+        cntR=encR-encRB; 
+        cntL=encL-encLB;
+        encRB=encR;
+        encLB=encL;
+        cntC=(cntR>cntL)? cntR: cntL;   // max of cntR/L.
+    }
+    dirCompus=arrayCompus[compus];
+}                
+
+//--------------------------------------------------------------------------
+//  テスト,パラメータ設定                                                   
+//--------------------------------------------------------------------------
+
+// サーボのテスト
+void testServo() {
+  strServo=strmin;    // 最初左に曲がる
+  Thread::wait(1000); 
+  strServo=strmax;    // 次に右に曲がる
+  Thread::wait(1000); 
+  strServo=strn;      // ニュートラル
+  Thread::wait(1000); 
+}
+
+// モータテスト、実行スイッチで正転、セットスイッチで逆転、リセットを押すまでモータ回り続ける
+void testMotor(){
+  while(resetSW==1){
+     if      (startSW==0) motorAmp=POSC-posL;  
+     else if (setSW==0)   motorAmp=POSC+posL;  
+     //else motorAmp=POSC;  
+  }
+}
+
+// encoderテスト
+void testEncoder(){
+    lcd.cls();
+    while(resetSW==1){
+        lcd.locate(0,0); lcd.printf("eR%d eL%d \n", encR, encL);        
+        lcd.locate(0,1); lcd.printf("cR=%d cL=%d cC=%d \n", cntR, cntL, cntC);   
+    }
+}
+
+// test gyro sensor
+void testGyro(){
+    lcd.cls();
+    gyro_reset();
+    while(resetSW==1){
+        if (setSW==0) {
+            gyro_offset();
+            gyro_reset();
+        } 
+        lcd.locate(0,0); lcd.printf("gyItg=%f \n", gyItg);       
+        lcd.locate(0,1); lcd.printf("angle=%f \n", angle);   
+    }    
+}
+
+//-------------------------------------------------------------------------- 
+//  モータスタート
+//-------------------------------------------------------------------------- 
+void motorStart(){
+  motorAmp=POSC-posL;
+  Thread::wait(1000);
+}
+
+//-------------------------------------------------------------------------- 
+//  モータストップ
+//-------------------------------------------------------------------------- 
+void motorStop(){
+    motorAmp=POSC;
+    Thread::wait(500); 
+}
+
+//-------------------------------------------------------------------------- 
+//  ステアリングニュートラル
+//-------------------------------------------------------------------------- 
+void steerNeutral(){
+  strServo=strn; 
+}
+
+//-------------------------------------------------------------------------- 
+// ニュートラルのセット、スタートでプラス、セットでマイナス、リセットで戻る
+//-------------------------------------------------------------------------- 
+void initNeutral(){
+  while(resetSW==1){
+    if (startSW==0){strn+=0.01; if (strn>strmax) strn=strmax; }
+    if (setSW==0)  {strn-=0.01; if (strn<strmin) strn=strmin; } 
+    strServo=strn;      // ニュートラル
+    lcd.locate(0,1); lcd.printf("str nuetral=%f   \n", strn);
+    Thread::wait(100); 
+  }
+}
+
+//-------------------------------------------------------------------------- 
+// ステアリング最小値のセット、スタートでプラス、セットでマイナス、リセットで戻る
+//-------------------------------------------------------------------------- 
+void initStrmin(){
+  while(resetSW==1){
+    if (startSW==0) if (strmin<0.5) strmin+=0.02;   // 可変範囲は45-90度まで
+    if (setSW==0)   if (strmin>0.02) strmin-=0.02; 
+    strServo=strmin;      // ステアリング最小値に動かす
+    lcd.locate(0,1); lcd.printf("strmin=%f   \n", strmin);
+    Thread::wait(100); 
+  }
+}
+
+//-------------------------------------------------------------------------- 
+// ステアリング最大値のセット、スタートでプラス、セットでマイナス、リセットで戻る
+//-------------------------------------------------------------------------- 
+void initStrmax(){
+  while(resetSW==1){
+    if (startSW==0) if (strmax<0.98) strmax+=0.02;   // 可変範囲は90-135度まで
+    if (setSW==0)   if (strmax>0.5 ) strmax-=0.02; 
+    strServo=strmax;      // ステアリング最大値に動かす
+    lcd.locate(0,1); lcd.printf("strmax=%f   \n", strmax);
+    Thread::wait(200); 
+  }
+}
+
+//-------------------------------------------------------------------------- 
+// ウェイポイントの半径をセット、スタートでプラス、セットでマイナス、リセットで戻る
+// 2進数で半径を表示
+//-------------------------------------------------------------------------- 
+void initWr(){
+  while(resetSW==1){
+    if (startSW==0){wr+=0.1; if (wr>10) wr=10; } 
+    if (setSW==0)  {wr-=0.1; if (wr<0.1) wr=0.1; } 
+    lcd.locate(0,1); lcd.printf("wr=%f \n", wr);
+    Thread::wait(200); 
+  }
+}
+
+//-------------------------------------------------------------------------- 
+// ステアリング制御の比例係数をセット、スタートでプラス、セットでマイナス、リセットで戻る
+// 比例係数の50倍を2進数で表示
+//-------------------------------------------------------------------------- 
+void initKs(){
+  while(resetSW==1){
+    if (startSW==0){ks+=0.001; if (ks>1)  ks=1;}  
+    if (setSW==0)  {ks-=0.001; if (ks<-1) ks=-1;} 
+    lcd.locate(0,1); lcd.printf("ks=%f \n", ks);
+    Thread::wait(200); 
+  }
+}
+
+void initKsG(){
+  while(resetSW==1){
+    if (startSW==0){ksg+=0.001; if (ksg>1)  ksg=1;}  
+    if (setSW==0)  {ksg-=0.001; if (ksg<-1) ksg=-1;} 
+    lcd.locate(0,1); lcd.printf("ksg=%f \n", ksg);
+    Thread::wait(200); 
+  }
+} 
+
+//-------------------------------------------------------------------------- 
+// 直進スピードをセット、スタートでプラス、セットでマイナス、リセットで戻る
+// スピードの1/16を2進数で表示
+//-------------------------------------------------------------------------- 
+void initPosH(){
+  while(resetSW==1){
+    motorAmp=POSC-posH; // モータを回転させる
+    if (startSW==0){posH+=0.01; if (posH>0.8) posH=0.8;}  
+    if (setSW==0)  {posH-=0.01; if (posH<0) posH=0;} 
+    lcd.locate(0,1); lcd.printf("PosH=%f \n", posH);
+    Thread::wait(200); 
+  }
+}
+
+void initPosL(){
+  while(resetSW==1){
+    motorAmp=POSC-posL; // モータを回転させる
+    if (startSW==0){posL+=0.01; if (posL>0.8) posL=0.8;}  
+    if (setSW==0)  {posL-=0.01; if (posL<0) posL=0;} 
+    lcd.locate(0,1); lcd.printf("PosL=%f \n", posL);
+    Thread::wait(200); 
+  }
+}
+
+ 
+void initSpdH(){   // 走行スピードhighの設定
+    while(resetSW==1){
+        if (startSW==0){spdH++; if (spdH>100) spdH=100;}  
+        if (setSW==0)  {spdH--; if (spdH<0) spdH=0;} 
+        lcd.locate(0,1); lcd.printf("speed High=%d \n", spdH);
+        Thread::wait(200); 
+    }
+}
+
+void initSpdL(){   // 走行スピードlowの設定
+    while(resetSW==1){
+        if (startSW==0){spdL++; if (spdL>100) spdL=100;}  
+        if (setSW==0)  {spdL--; if (spdL<0) spdL=0;} 
+        lcd.locate(0,1); lcd.printf("speed Low=%d \n", spdL);
+        Thread::wait(200); 
+    }       
+}    
+    
+void testRun(){         // test run
+    int setSpd=0;    
+    while(resetSW==1){
+        if (setSW==0)   setSpd=spdL;
+        if (startSW==0) setSpd=spdH;
+        lcd.locate(0,1); lcd.printf("set speed=%d \n", setSpd);
+        
+        if (setSpd>cntC){
+            motorAmp=POSC-posH;
+        } else {
+            motorAmp=POSC-posL;
+        }
+        Thread::wait(50); 
+    } 
+    motorAmp=POSC;  
+}    
+
+
+void testCompus(){
+    lcd.cls();
+    while(resetSW==1){
+        lcd.locate(0,0); lcd.printf("compus=%f  \n", arrayCompus[compus]);
+        lcd.locate(0,1); lcd.printf("rd=%f  \n", rd);
+        Thread::wait(50);  
+    } 
+}
+
+    
+//-------------------------------------------------------------------------- 
+// GPS受信テスト,補足状況をLED点灯の数で示す
+//-------------------------------------------------------------------------- 
+void dispGPS(){
+    while(resetSW==1){
+        lcd.cls();
+        if (latit==0) lcd.printf("GPS Not Found \n");
+        else {
+            lcd.cls();
+            lcd.printf("LA=%f \n", latit);
+            lcd.printf("LO=%f \n", longit);
+            Thread::wait(1500);
+            lcd.cls();
+            lcd.printf("rv=%f3 \n",rv);
+            lcd.printf("rd=%f3 \n",rd);
+            Thread::wait(1500);
+        } 
+        Thread::wait(200);
+                  
+    }
+    Thread::wait(200);
+}
+
+//-------------------------------------------------------------------------- 
+//  GPS信号の数値返還       
+//-------------------------------------------------------------------------- 
+void gps_val(){
+      latitB=latit; longitB=longit;  // 一つ前の値を保管
+      latit=atof(latitude+2);        // 文字列を実数に変換.有効数字が足りないので度単位を省略
+      longit=atof(longitude+3);      // 文字列を実数に変換.有効数字が足りないので度単位を省略
+      kn=atof(knot);
+      rv=kn*0.51;                    // ノット単位をメートル単位に変換
+      rdB=rd;                        // 一つ前の値を保管
+      rd=atof(direct);               // 方位を数値変換 
+}
+
+//-------------------------------------------------------------------------- 
+//  現在地とウェイポイントとの相対関係を計算      
+//-------------------------------------------------------------------------- 
+void gps_cal(){
+      // 緯度経度の数値変換,目標地点との差分を計算
+      dy=(wy[np] - latit ) *1860; 
+      dx=(wx[np] - longit)*1560;
+      
+      // 目標地点までのと距離を計算
+      dr=sqrt(pow(dy,2)+pow(dx,2));
+      
+      // 目標地点への方向を計算 
+      dd = atan(dx / dy);                 // 北に対する角度を求める(±π/2範囲)
+      dd=dd*57;                           // ラジアン->度に変換 dd*(180/pai)
+      // 0-360度に変換
+      if (dx > 0 && dy < 0)     dd = 180 + dd;
+      else if(dx < 0 && dy < 0) dd = 180 + dd;
+      else if(dx < 0 && dy > 0) dd = 360 + dd;
+      else;
+ 
+      // GPSが正しい方位を出力しない場合は、前の座標との差分で計算
+      dy2=(latit -latitB) *1860; 
+      dx2=(longit-longitB)*1560;
+      
+      if (dy2==0 || dx2==0){                  // 緯度または経度のどちらかの変化が0の時
+        if (dy2==0){ if (dx2<0) rd2= 270; else rd2=90; } // rd2= 0, 90, 180,270 のいずれかを直接与える.
+        if (dx2==0){ if (dy2<0) rd2=-180; else rd2=0; } // dy2,dx2のどちらも0の時はrd2=0
+      } else {
+        // 目標地点への方向を計算
+        rd2 = atan(dx2 / dy2);                 // 北に対する角度を求める(±π/2範囲)
+        rd2=rd2*57;                           // ラジアン->度に変換 dd*(180/pai)
+        // 0-360度に変換
+        if (dx2 > 0 && dy2 < 0)     rd2 = 180 + rd2;
+        else if(dx2 < 0 && dy2 < 0) rd2 = 180 + rd2;
+        else if(dx2 < 0 && dy2 > 0) rd2 = 360 + rd2;
+        else;
+      }
+      
+      // 移動距離が小さくて使用するGPSが正しい速度と方向を出さない時のみ
+      // 座標差から計算した値と置き換える(速度=0,方位前の値のまま,GPSの仕様により異なる)
+      if (kn==0 && dx2!=0 && dy2!=0){  
+        rd=rd2; 
+      } 
+      
+      // compare the dirction by GPS and compus 
+      if (rd>180) rdCpy=rd-360; else rdCpy=rd;
+      if (dirCompus>180) dirCompusCpy=dirCompus-360; else dirCompusCpy=dirCompus;
+      // compare the dirction by GPS and compus 
+      rd=(fabs(rdCpy-dirCompusCpy)>45)? dirCompus: rd;
+       
+      // 方位偏差の計算し,現在の進行方向から±180度の範囲に直す
+      dd=dd-rd;
+      if (dd>180) dd=dd-360;
+      else if (dd<-180) dd=dd+360;  
+}
+
+//-------------------------------------------------------------------------- 
+// gps read by serial task 
+//-------------------------------------------------------------------------- 
+void serial_task(void const*) {
+    char c;
+    int i=0;
+    //FILE *fp;
+    
+    USBHostSerial serial;
+    
+    while(1) {
+        while(!serial.connect()) Thread::wait(500);  // try to connect a serial device
+        
+        while (1) {
+            if (!serial.connected()) break;  // if device disconnected, try to connect it again
+            
+            while (serial.available()) {     // receive message
+                c= serial.getc();
+                str[i]=c;
+                if (c == '\n') break;
+                i++; 
+            }
+            str[i] = '\0';
+            i=0;
+            //fp=fopen("/local/log.txt", "a");  // Open "out.txt" on the local file system for writing
+            //fprintf(fp, str);
+            //fclose(fp);
+            
+            header=strtok(str,",");
+            
+            //if RMC line 
+            if(strcmp(header,"$GNRMC")==0){
+                strtok(NULL,",");
+                strtok(NULL,",");
+                latitude=strtok(NULL,","); //get latitude
+                strtok(NULL,",");
+                longitude=strtok(NULL,","); //get longtude
+                strtok(NULL,",");          // E読み飛ばし
+                knot=strtok(NULL,",");     // 速度 get
+                direct=strtok(NULL,",");   // 進行方向 get 
+                gps_val();        //  GPS信号の数値返還  
+                gps_cal();       // 現在地とウェイポイントとの関係を計算  
+                recvGPS++; if(recvGPS>2) recvGPS=2;
+                printf("LA=%f LO=%f kn=%f rv=%f rd=%f recvGPS=%d\n", latit, longit, kn, rv, rd, recvGPS );    
+            }
+
+            if(strcmp(header,"$GPRMC")==0){
+                strtok(NULL,",");
+                strtok(NULL,",");
+                latitude=strtok(NULL,","); //get latitude
+                strtok(NULL,",");
+                longitude=strtok(NULL,","); //get longtude
+                strtok(NULL,",");          // E読み飛ばし
+                knot=strtok(NULL,",");     // 速度 get
+                direct=strtok(NULL,",");   // 進行方向 get 
+                gps_val();        //  GPS信号の数値返還  
+                gps_cal();       // 現在地とウェイポイントとの関係を計算  
+                recvGPS++; if(recvGPS>2) recvGPS=2; 
+                printf("LA=%f LO=%f kn=%f rv=%f rd=%f recvGPS=%d\n", latit, longit, kn, rv, rd, recvGPS );  
+            }            
+               
+            //if QZQSM line 
+            if(strcmp(header,"$QZQSM")==0 && recvQZSS==0){   //if RMC line
+                strtok(NULL,","); // 55
+                //strtok(NULL,","); // 53
+                messages=strtok(NULL,"*");
+                printf("%s\n",messages+4);                    // messages
+                strncpy(strtmp,messages+4,4); strtmp[4]='\0';
+                year=strtol(strtmp,NULL,16);
+                strncpy(strtmp,messages+8,2); strtmp[2]='\0';
+                teamNum =strtol(strtmp,NULL,16);
+                strncpy(strtmp,messages+10,2); strtmp[2]='\0';
+                numA =strtol(strtmp,NULL,16);
+                strncpy(strtmp,messages+12,2); strtmp[2]='\0';
+                sizeA=strtol(strtmp,NULL,16);
+                strncpy(strtmp,messages+14,2); strtmp[2]='\0';
+                numB =strtol(strtmp,NULL,16);
+                strncpy(strtmp,messages+16,2); strtmp[2]='\0';
+                sizeB=strtol(strtmp,NULL,16);
+                strncpy(strtmp,messages+18,2); strtmp[2]='\0';
+                numT=strtol(strtmp,NULL,16);
+                strncpy(strtmp,messages+20,2); strtmp[2]='\0';
+                startA=strtol(strtmp,NULL,18);
+                strncpy(strtmp,messages+22,2); strtmp[2]='\0';
+                startB=strtol(strtmp,NULL,20);
+                for(i=0; i<numT; i++){
+                    strncpy(strtmp,messages+24+i*4,2); strtmp[2]='\0';
+                    targetA[i]=strtol(strtmp,NULL,16);
+                    strncpy(strtmp,messages+26+i*4,2); strtmp[2]='\0';
+                    targetB[i]=strtol(strtmp,NULL,16);   
+                } 
+                if (teamNum==tNum) recvQZSS=1;  
+                
+                printf("year=%d\n",year);
+                printf("teamNum=%d\n",teamNum);
+                printf("numA=%d\n",numA);
+                printf("sizeA=%d\n",sizeA);
+                printf("numB=%d\n",numB);
+                printf("sizeB=%d\n",sizeB);                  
+                printf("tNum=%d\n",numT); 
+                printf("startA=%d\n",startA); 
+                printf("startB=%d\n",startB); 
+                for(i=0; i<numT; i++){
+                    printf("targetA[%d]=%d\n",i,targetA[i]);     
+                    printf("targetB[%d]=%d\n",i,targetB[i]); 
+                }
+                printf("recvQZSS=%d\n",recvQZSS);        
+            }
+            Thread::wait(50);
+        }
+    }
+}
+   
+
+//--------------------------------------------------------------------------
+//  GPSによる走行
+//  runMode=0:GPS run without Gyro, normal rule( stop waypoint)
+//  runMode=1:GPS run without Gyro, Double pylon race( loop waypoint without stop)                                                     
+//--------------------------------------------------------------------------
+void runGPS(int runMode){
+  lcd.cls(); lcd.locate(0,1); lcd.printf("Start!");  // 目標値までの距離をLEDに表示
+  Thread::wait(1000);
+  
+  np=0;
+  motorStart();
+  
+  while (resetSW==1){       // STARTスイッチが押されたら抜ける
+    // speed control
+    if (fabs(dr-wr)>8){                  // ステアリングが真っ直ぐで距離が十分あるとき
+      if (cntC>spdH) motorAmp=POSC-posL; else motorAmp=POSC-posH;
+    } else {
+      if (cntC>spdL) motorAmp=POSC-posL; else motorAmp=POSC-posH;  
+    }
+           
+    while (recvGPS==0) Thread::wait(15);     // GPS受信待ち  
+    recvGPS=0;              //  reset after GPS recv
+    lcd.locate(0,0); lcd.printf("dd=%f \n", dd);  // 目標値までの距離をLEDに表示
+    lcd.locate(0,1); lcd.printf("dr=%f \n", dr);  // 目標値までの距離をLEDに表示
+    
+    // 角度差に応じて方向にステアリングを切る.
+    posSteer=strn - dd*ks;
+    posSteer=(posSteer<strmin)? strmin: (posSteer>strmax)? strmax: posSteer;   // 切れ幅を制限する 
+    if (kn==0) posSteer=strn; // GPSで方位が得られなかった時(速度=0)ニュートラルに戻す
+    strServo=posSteer; 
+    Thread::wait(15);
+    
+    // ウェイポイントとの距離を求め,ポイント更新または走行終了判断
+    if (dr < wr){
+      steerNeutral();
+      if(runMode==0) motorStop();
+      np++;
+      if (np>=wp){
+          if(runMode==0) break;   // when normal robot car rule, 
+          else np=0;
+      }
+      // 次のポイント数を表示
+      lcd.locate(0,1); lcd.printf("Next WP:%d      ",np);
+      if(runMode==0){           // normal rule, wait 6sec
+          Thread::wait(6000);  
+          motorStart();
+      }
+    }
+  }
+}
+
+//--------------------------------------------------------------------------
+//  GPSによる走行, with gyro
+//  runMode=0:GPS run with Gyro, normal rule( stop waypoint)
+//  runMode=1:GPS run with Gyro, Double pylon race( loop waypoint without stop)                                                     
+//--------------------------------------------------------------------------
+void runGPSandGyro(int runMode){
+  lcd.cls(); lcd.locate(0,1); lcd.printf("Start!");  // 目標値までの距離をLEDに表示
+  Thread::wait(1000);
+  
+  np=0;
+  motorStart();
+  
+  while (resetSW==1){       // STARTスイッチが押されたら抜ける
+    // speed control
+    if (fabs(dr-wr)>8){                  // ステアリングが真っ直ぐで距離が十分あるとき
+      if (cntC>spdH) motorAmp=POSC-posL; else motorAmp=POSC-posH;
+    } else {
+      if (cntC>spdL) motorAmp=POSC-posL; else motorAmp=POSC-posH;  
+    }
+           
+    //if (recvGPS==2){
+    if (recvGPS>=1){
+        recvGPS=0;                                      //  reset after GPS recv
+        ddCpy=dd;                                       // GPSを受信した時の角度差を記録       
+        lcd.locate(0,0); lcd.printf("dd=%f \n", dd);    // 目標値までの距離をLEDに表示
+        lcd.locate(0,1); lcd.printf("dr=%f \n", dr);    // 目標値までの距離をLEDに表示
+    
+        // 角度差に応じて方向にステアリングを切る.
+        posSteer=strn - dd*ksg;
+
+        posSteer=(posSteer<strmin)? strmin: (posSteer>strmax)? strmax: posSteer;   // 切れ幅を制限する 
+        if (kn==0) posSteer=strn; // GPSで方位が得られなかった時(速度=0)ニュートラルに戻す
+        strServo=posSteer; 
+        Thread::wait(15);  
+        gyro_reset();
+    }
+    // ジャイロで角度モニタ,指定角度でステアリング戻す,ddはターン中も更新されるので更新されないddCpyでターン
+    if (fabs(angle)>fabs(ddCpy)){posSteer=strn; strServo=posSteer;} 
+    // ターン途中かつターン角度が大きい時,GPS受信しても数値を更新させない,recvGPS=0から次のターンまで2秒.待ちすぎか?
+    if (posSteer!=strn && fabs(ddCpy)>60) recvGPS=0;    
+    
+    // ウェイポイントとの距離を求め,ポイント更新または走行終了判断
+    if (dr < wr){
+      steerNeutral();
+      if(runMode==0) motorStop();
+      np++;
+      if (np>=wp){
+          if(runMode==0) break;   // when normal robot car rule, 
+          else np=0;
+      }
+      // 次のポイント数を表示
+      lcd.locate(0,1); lcd.printf("Next WP:%d      ",np);
+      if(runMode==0){           // normal rule, wait 6.5sec
+          Thread::wait(6500);  
+          motorStart();         // run straignt for 1 sec. 
+      }
+    }
+    Thread::wait(15);
+  }
+}
+
+
+//--------------------------------------------------------------------------
+//  QZSSによる走行,
+//  runMode=0: without Gyro, normal rule( stop waypoint)
+//  runMode=1: with Gyro,    normal rule( stop waypoint)                                                   
+//--------------------------------------------------------------------------
+void runQZSS(int runMode){
+  
+    lcd.cls();
+    lcd.printf("Waiting QZSS\n");  
+    lcd.locate(0,1);
+    lcd.printf("massage: %d  \n", tNum); 
+    while (recvQZSS==0){
+        Thread::wait(500);  
+        if (resetSW==0) break;
+        if (startSW==0){tNum++; if (tNum>25) tNum=0;}  
+        if (setSW==0)  {tNum--; if (tNum<0) tNum=25;} 
+        lcd.locate(0,1); lcd.printf("massage: %d  \n", tNum);  
+    }
+
+    lcd.cls();
+    lcd.printf("QZSS massage \n");  
+    lcd.printf("Recieved !!  \n"); 
+    Thread::wait(3000);  
+  
+    // set way point  
+    wp=0;
+    //wy[wp]=wyQ[startA][startB];
+    //wx[wp]=wxQ[startA][startB];
+    //wp++;
+    for(int i=0; i<numT; i++){
+        wy[wp]=wyQ[targetA[i]][targetB[i]];
+        wx[wp]=wxQ[targetA[i]][targetB[i]];
+        wp++;
+    }
+    
+    if (runMode==0) runGPS(0); runGPSandGyro(0);    
+}
+
+//-------------------------------------------------------------------------- 
+//  セットアップ以外の初期値設定
+//-------------------------------------------------------------------------- 
+void initPara(){
+  steerNeutral();
+  motorStop();
+}
+
+//-------------------------------------------------------------------------- 
+int main() {
+    strServo=POSC; motorAmp=POSC;
+    resetSW.mode(PullUp); setSW.mode(PullUp); startSW.mode(PullUp); 
+    Thread serialTask(serial_task, NULL, osPriorityNormal, 256 * 4);
+    timerS.attach_us(&sensor, 1000);    // set timer to 1ms for timer interrupt 
+    ptR.rise(&countR);  
+    ptL.rise(&countL);  
+    timer.start();
+    gyro_offset();
+    readParam();
+
+    lcd.cls();
+    lcd.printf("GPS robocar v1\n");
+    lcd.printf("sw:ret set start\n");
+    while(resetSW==1 && setSW==1 && startSW==1);
+    lcd.locate(0,1); lcd.printf(menuS[pmode]);
+                       
+    while(1) {
+
+        // initialize parameters
+        initPara();
+        lcd.cls();
+        lcd.printf("GPS robocar v1\n");
+        lcd.locate(0,1); lcd.printf(menuS[pmode]);
+        
+        while (startSW==1) {
+            if (resetSW==0) {               
+                Thread::wait(10); 
+                while (resetSW==0);
+                Thread::wait(10);  
+                pmode--;
+                if (pmode<0) pmode=nmenu;
+                lcd.locate(0,1);
+                lcd.printf(menuS[pmode]);
+            }
+            if (setSW==0) {               
+                Thread::wait(10); 
+                while (setSW==0);
+                Thread::wait(10);  
+                pmode++;
+                if (pmode>nmenu) pmode=0;
+                lcd.locate(0,1);
+                lcd.printf(menuS[pmode]);
+            }
+            
+        }
+        Thread::wait(500);                     
+        
+        // go selected functions
+        switch(pmode){
+            case  0: dispGPS();    break;    // GPSのテスト   
+            case  1: setWp();      break;    // ウェイポイントのセット  
+            case  2: dispWp();     break;    // display way point 
+            case  3: clearWp();    break;    // ウェイポイントのクリア  
+            case  4: readWp();     break;    // ウェイポイントのread
+            case  5: writeWp();    break;    // ウェイポイントのread
+            case  6: setTeamNum(); break;    // set team number for QZSS
+            case  7: setQZWp();    break;    // (1,1)(1,7)(7,1)(7,7)の4点だけ読み書き、他の点は計算
+            case  8: readQZWp4();  break;    // (1,1)(1,7)(7,1)(7,7)の4点だけ読み書き、他の点は計算
+            case  9: writeQZWp4(); break;    // (1,1)(1,7)(7,1)(7,7)の4点だけ読み書き、他の点は計算
+            case 10: dispQmsg();   break;    // ウェイポイントのクリア  
+            case 11: clearQmsg();  break;    // ウェイポイントのread    
+            case 12: readQmsg();   break;    // ウェイポイントのread
+            case 13: writeQmsg();  break;    // ウェイポイントのread            
+            case 14: runGPS(1);    break;    // GPS走行, 0:WPで止まる、1:WPで止まらない
+            case 15: runGPSandGyro(1); break; // ジャイロを使ったGPS走行,0:WPで止まる、1:WPで止まらない
+            case 16: runQZSS(0);   break;    // QZSS-GPS走行(WPで止まる)  
+            case 17: runQZSS(1);   break;    // QZSS-ジャイロを使ったGPS走行(WPで止まる)  
+            case 18: testServo();  break;    // サーボの動作テスト
+            case 19: testMotor();  break;    // モーターの動作テスト
+            case 20: initNeutral(); break;    // ステアリングニュートラル位置の設定
+            case 21: initStrmin(); break;    // ステアリングの最小値の設定
+            case 22: initStrmax(); break;    // ステアリングの最大値の設定
+            case 23: initWr();     break;    // ウェイポイントの半径設定
+            case 24: initKs();     break;    // 舵角計算の比例値設定
+            case 25: initKsG();     break;    // 舵角計算の比例値設定
+            case 26: initPosH();    break;    // amp pos for high speed
+            case 27: initPosL();    break;    // amp pos for low speed
+            case 28: initSpdH();    break;    // 走行スピードhighの設定
+            case 29: initSpdL();    break;    // 走行スピードlowの設定
+            case 30: testRun();     break;    // test run
+            case 31: writeParam(); break;    // ウェイポイントのシリアル出力
+            case 32: readParam();  break;    // パラメータのシリアル出力
+            case 33: testEncoder(); break;
+            case 34: testGyro();   break;
+            case 35: testCompus(); break;
+        }
+        Thread::wait(500);    
+    }
+}
+ 
\ No newline at end of file