2015/06/05
Dependencies: ADXL345 AigamozuControlPackets HMC5843 ITG3200 MBed_Adafruit-GPS-Library XBee agzIDLIST mbed
Fork of Aigamozu_Robot_ver4_3 by
main.cpp
- Committer:
- s1210160
- Date:
- 2015-05-29
- Revision:
- 36:a11060f5199e
- Parent:
- 35:3094c84a024b
- Child:
- 37:26374d6066cb
File content as of revision 36:a11060f5199e:
/**********************************************/ // // // // Program name: Aigamozu ROBOT // Author: Mineta Kizuku // // // /**********************************************/ /**********************************************/ //更新情報 //2015/05/11 //ロボットプログラムの作成 // //2015/05/13 //カルマンフィルタの共分散の値を0.0001以下にならないようにした //共分散の値を10進数に変換するようにした // //2015/05/13 Yokokawa //何回目のGPSでとられたGPSか確認するようにしました。 // //2015/05/15 //プログラムcreateReceiveStatusCommand()にて //Aigamozu_collect_dataにinかoutかを送るためにstate関連をいじったので必要に応じて直してください。 // //2015/05//17 //Send_Status関数内を変更:基地局への送信データのみ現在のモードを入れるパケットの部分に内外判定の結果を入れるようにした //基地局以外には現在のモードを送信するようにしてある //要確認!!!! // //2015/05/17 //Get_GPS()の中身longitudeの範囲138〜140に変更 // //2015/05/19 //autoモードのとき、三十秒前進・三秒右に転回に変更した。 // //2015/05/24 //Kalmanフィルターを十進数で計算するようにした。 //Kalmanフィルターの計算式を変更した。 //set_kalmanを追加した。 // //2015/05/29 //auto_Move関数の実装とAigamozuControlPackets内にcontrol_Mortor関数の実装 /**********************************************/ #include "mbed.h" #include "XBee.h" #include "MBed_Adafruit_GPS.h" #include "AigamozuControlPackets.h" #include "agzIDLIST.h" #include "aigamozuSetting.h" #include "Kalman.h" #include "math.h" #define SIGMA_MIN 0.0001 //************ID Number***************** //Robot ID: 'A' ~ 'Z' //Base ID: 'a' ~ 'a' //manager ID: '0'(数字のゼロ) // const char MyID = 'A'; //************ID Number***************** ///////////////////////////////////////// // //Pin Setting // ///////////////////////////////////////// VNH5019 agz_motorShield(p21,p22,p23,p24,p25,p26); ///////////////////////////////////////// // //Connection Setting // ///////////////////////////////////////// //Serial Connect Setting: PC <--> mbed Serial pc(USBTX, USBRX); //Serial Connect Setting: GPS <--> mbed Serial * gps_Serial; //Serial Connect Setting: XBEE <--> mbed XBee xbee(p13,p14); ZBRxResponse zbRx = ZBRxResponse(); //set up GPS module //set up AigamozuControlPackets library AigamozuControlPackets agz(agz_motorShield); ///////////////////////////////////////// // //For Kalman data // ///////////////////////////////////////// #define FIRST_S2 0.000001 #define COUNTER_MAX 10000 #define ERROR_RANGE 0.001 double x_cur,x_prev,y_cur,y_prev;//緯度と経度の時刻tと時刻t-1での推定値 double s2x_cur=FIRST_S2,s2x_prev=FIRST_S2,s2y_cur=FIRST_S2,s2y_prev=FIRST_S2;//緯度経度のの時刻tと時刻t-1での共分散 double s2_R=FIRST_S2;//GPSセンサの分散 double Kx=0,Ky=0;//カルマンゲイン double zx,zy;//観測値 void Kalman(double Latitude,double Longitude); int change = 0; LocalFileSystem local("local"); // マウントポイントを定義(ディレクトリパスになる) ///////////////////////////////////////// // //Plus Speed // //MNUAL_MODEの時にスピードを変える ///////////////////////////////////////// void Plus_Speed(uint8_t *packetdata){ if(agz.nowMode == MANUAL_MODE){ agz.changeSpeed(packetdata); } } ///////////////////////////////////////// // //Send Status // //リクエストがきたとき、自分の位置情報などを返信する ///////////////////////////////////////// void Send_Status(char SenderIDc){ XBeeAddress64 send_Address; if(SenderIDc == '0'){ send_Address = manager_Address; agz.createReceiveStatusCommand(MyID,SenderIDc, agz.nowMode, agz.get_agzPoint_lati(),agz.get_agzPoint_longi(), agz.get_agzPointKalman_lati(),agz.get_agzPointKalman_longi(), agz.get_agzCov_lati(),agz.get_agzCov_longi()); } if(SenderIDc >= 'A' && SenderIDc <= 'Z'){ send_Address = robot_Address[SenderIDc - 'A']; //Create GPS Infomation Packet agz.createReceiveStatusCommand(MyID,SenderIDc, agz.nowMode, agz.get_agzPoint_lati(),agz.get_agzPoint_longi(), agz.get_agzPointKalman_lati(),agz.get_agzPointKalman_longi(), agz.get_agzCov_lati(),agz.get_agzCov_longi()); } if(SenderIDc >= 'a' && SenderIDc <= 'z'){ send_Address = base_Address[SenderIDc - 'a']; agz.createReceiveStatusCommand(MyID,SenderIDc, (int)agz.gpsAuto(), agz.get_agzPoint_lati(),agz.get_agzPoint_longi(), agz.get_agzPointKalman_lati(),agz.get_agzPointKalman_longi(), agz.get_agzCov_lati(),agz.get_agzCov_longi()); } //send normal data /* //debug*************************************************** printf("latitude:%f,longitude:%f\nlatitudeK:%f,longitudeK:%f\nCovlat:%f,Covlongi:%f\n", agz.get_agzPoint_lati(),agz.get_agzPoint_longi(), agz.get_agzPointKalman_lati(),agz.get_agzPointKalman_longi(), agz.get_agzCov_lati(),agz.get_agzCov_longi() ); for(int i = 0; i < RECEIVE_STATUS_COMMNAD_LENGTH; ++i) printf("%d ",agz.packetData[i]); printf("\n"); //debug end*************************************************** */ //Select Destination ZBTxRequest tx64request(send_Address,agz.packetData,agz.getPacketLength()); //Send -> Base xbee.send(tx64request); } ///////////////////////////////////////// // //Get GPS function // ///////////////////////////////////////// void Get_GPS(Adafruit_GPS *myGPS){ static int flag = 0; if (myGPS->fix) { agz.nowStatus = GPS_AVAIL; agz.reNewRobotPoint(myGPS->latitudeH,myGPS->latitudeL,myGPS->longitudeH,myGPS->longitudeL); if(flag < COUNTER_MAX){ flag++; } if(flag == 5){ x_prev = agz.get_agzPoint_lati(); y_prev = agz.get_agzPoint_longi(); } if(flag >= 6){ if(abs(x_prev - agz.get_agzPoint_lati()) < ERROR_RANGE && abs(y_prev - agz.get_agzPoint_longi()) < ERROR_RANGE){ Kalman(agz.get_agzPoint_lati(), agz.get_agzPoint_longi()); change = 1; } else{ change = 0; } /* fp = fopen(filename, "w"); fprintf(fp, "%d %.14lf %.14lf %.14lf %.14lf %.14le %.14le \n", change, agz.get_agzPoint_lati(),agz.get_agzPoint_longi(), agz.get_agzPointKalman_lati(),agz.get_agzPointKalman_longi(), agz.get_agzCov_lati(),agz.get_agzCov_longi()); */ } printf("%.14lf %.14lf %.14lf %.14lf %.14le %.14le \n", agz.get_agzPoint_lati(),agz.get_agzPoint_longi(), agz.get_agzPointKalman_lati(),agz.get_agzPointKalman_longi(), agz.get_agzCov_lati(),agz.get_agzCov_longi()); } else agz.nowStatus = GPS_UNAVAIL; } ///////////////////////////////////////// // //New Mode // ///////////////////////////////////////// void New_Mode(uint8_t *packetdata){ //bool result; agz.changeMode(packetdata); } ///////////////////////////////////////// // //Get Status // ///////////////////////////////////////// void Get_Status(char SenderIDc,uint8_t *packetdata){ //マネージャからデータが来たとき if(SenderIDc == '0'){ printf("get manager Status\n"); } //他のロボットからデータが来たとき if(SenderIDc >= 'A' && SenderIDc <= 'Z'){ printf("get other robots Status\n"); } //基地局からデータが来たとき if(SenderIDc >= 'a' && SenderIDc <= 'z'){ printf("Get Base data\n"); int id = SenderIDc - 'a'; agz.reNewBasePoint(id,&packetdata[13],&packetdata[21]); agz.reNewBasePointKalman(id,&packetdata[29],&packetdata[37]); //debug for(int i = 0;i < 4;i++){ printf("BASE:%d\n",i); printf("latitude:%f,longitude:%f\nlatitudeK:%f,longitudeK:%f\n", agz.get_basePoint_lati(i),agz.get_basePoint_longi(i), agz.get_basePointKalman_lati(i),agz.get_basePointKalman_longi(i) ); } } } void Get_Status_Kalman(char SenderIDc,uint8_t *packetdata){ //マネージャからデータが来たとき if(SenderIDc == '0'){ printf("get manager Status Kalman\n"); } //他のロボットからデータが来たとき if(SenderIDc >= 'A' && SenderIDc <= 'Z'){ printf("get other robots Status Kalman\n"); } //基地局からデータが来たとき if(SenderIDc >= 'a' && SenderIDc <= 'z'){ printf("Get Base data Kalman\n"); int id = SenderIDc - 'a'; agz.reNewBasePointKalman(id,&packetdata[29],&packetdata[37]); //debug for(int i = 0;i < 4;i++){ printf("BASE:%d\n",i); printf("latitudeK:%f,longitudeK:%f\n", agz.get_basePointKalman_lati(i),agz.get_basePointKalman_longi(i)); } } } ///////////////////////////////////////// // //Send_Request_to_base // ///////////////////////////////////////// void Send_Request_Base(int basenumber){ printf("send\n"); agz.createRequestCommand(MyID, basenumber); //Select Destination ZBTxRequest tx64request(base_Address[basenumber],agz.packetData,agz.getPacketLength()); //Send -> Base xbee.send(tx64request); } ///////////////////////////////////////// // //auto_Move // //InAreaかOutAreaの判定 //Kalmanを通した値を出力(Baseと自分) //2015/05/29 //外側判定と処理の実装 //内側判定:シーケンス動作 //外側判定:10秒間バック、3秒間旋回を行い、その後シーケンス動作へ ///////////////////////////////////////// void auto_Move(){ bool result; // 毎回の内外判定の結果を格納 bool out_flag = false; // 外側処理の実行フラグ const int sequenceTime[4] = {30000, 31000, 34000, 34200}; const int outSequenceTime[4] = {10000, 11000, 14000, 14200}; result = agz.gpsAuto(); //agz.set_agzAutoGPS(); //agz.set_agzKalmanGPS(); if(out_flag == false && result == true){ out_flag = true; agz.Out_Timer.reset(); } if(out_flag == false){ if(agz.Move_Timer.read_ms() < sequenceTime[0]){ agz.control_Motor(0); //straight } if(agz.Move_Timer.read_ms() > sequenceTime[0] && agz.Move_Timer.read_ms() < sequenceTime[1]){ agz.control_Motor(1); } if(agz.Move_Timer.read_ms() > sequenceTime[1] && agz.Move_Timer.read_ms() < sequenceTime[2]){ agz.control_Motor(2); //Turn Right } if(agz.Move_Timer.read_ms() > sequenceTime[2] && agz.Move_Timer.read_ms() < sequenceTime[3]){ agz.control_Motor(1); } if(agz.Move_Timer.read_ms() > sequenceTime[3]){ agz.Move_Timer.reset(); } } if(out_flag == true){ if(agz.Out_Timer.read_ms() < outSequenceTime[0]){ agz.control_Motor(3); //back } if(agz.Out_Timer.read_ms() > outSequenceTime[0] && agz.Out_Timer.read_ms() < outSequenceTime[1]){ agz.control_Motor(1); } if(agz.Out_Timer.read_ms() > outSequenceTime[1] && agz.Out_Timer.read_ms() < outSequenceTime[2]){ agz.control_Motor(2); //Turn Right } if(agz.Out_Timer.read_ms() > outSequenceTime[2] && agz.Out_Timer.read_ms() < outSequenceTime[3]){ agz.control_Motor(1); } if(agz.Out_Timer.read_ms() > outSequenceTime[3]){ agz.Out_Timer.reset(); agz.Move_Timer.reset(); out_flag = false; } } } void print_gps(int count){ printf("%d times:\n", count); printf("%f, %f\n", agz.get_agzPointKalman_lati(), agz.get_agzPointKalman_longi()); } ///////////////////////////////////////// // //Kalman Processing // ///////////////////////////////////////// void calc_Kalman(){ //calc Kalman gain Kx = s2x_prev/(s2x_prev+s2_R); Ky = s2y_prev/(s2y_prev+s2_R); //estimate x_cur = x_prev + Kx*(zx-x_prev); y_cur = y_prev + Ky*(zy-y_prev); //calc sigma s2x_cur = s2x_prev-Kx*s2x_prev; s2y_cur = s2y_prev-Ky*s2y_prev; } void Kalman(double Latitude,double Longitude){ zx = Latitude; zy = Longitude; calc_Kalman(); //更新 x_prev = x_cur; y_prev = y_cur; s2x_prev = s2x_cur; s2y_prev = s2y_cur; //agzPontKalmanとagzCovに格納する agz.set_agzPointKalman_lati(x_cur); agz.set_agzPointKalman_longi(y_cur); agz.set_agzCov(s2x_cur,s2y_cur); } ///////////////////////////////////////// // //Main Processing // ///////////////////////////////////////// int main() { //start up time wait(3); //set pc frequency to 57600bps pc.baud(PC_BAUD_RATE); //set xbee frequency to 57600bps xbee.begin(XBEE_BAUD_RATE); //GPS setting gps_Serial = new Serial(p28,p27); Adafruit_GPS myGPS(gps_Serial); Timer refresh_Timer; const int refresh_Time = 1000; //refresh time in ms Timer auto_Timer; const int auto_Time = 100; //refresh time in ms int count = 0; myGPS.begin(GPS_BAUD_RATE); Timer collect_Timer; const int collect_Time = 2000; //when we collect 4 GPS point, we use int collect_flag = 0; char SenderIDc; //GPS Send Command myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); myGPS.sendCommand(PGCMD_ANTENNA); wait_ms(2000); //interrupt start refresh_Timer.start(); auto_Timer.start(); agz.Move_Timer.start(); agz.Out_Timer.start(); collect_Timer.start(); printf("start\n"); while (true) { //Check Xbee Buffer Available xbee.readPacket(); if (xbee.getResponse().isAvailable()) { xbee.getResponse().getZBRxResponse(zbRx); uint8_t *buf = zbRx.getFrameData(); if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) { xbee.getResponse().getZBRxResponse(zbRx); uint8_t *buf = zbRx.getFrameData();//フレームデータを格納する uint8_t *buf1 = &buf[11];//データの部分のみを格納する SenderIDc = buf1[5];//送信元のIDを取得する char Command_type = agz.checkCommnadType(buf);//コマンドタイプを取得する //Check Command Type switch(Command_type){ //Get Request command case MANUAL:{ Plus_Speed(buf); break; } case STATUS_REQUEST:{ Send_Status(SenderIDc); printf("%c\n", SenderIDc); break; } case CHANGE_MODE:{ New_Mode(buf); break; } case RECEIVE_STATUS:{ Get_Status(SenderIDc,buf1); break; } default:{ break; } }//endswitch }//endifZB_RX_RESPONSE }//endifisAvailable myGPS.read(); //recive gps module //check if we recieved a new message from GPS, if so, attempt to parse it, if ( myGPS.newNMEAreceived() ) { if ( !myGPS.parse(myGPS.lastNMEA()) ) { continue; } else{ count++; } } //一定時間ごとに自分のGPSデータを取得し、AigamozuControlPacketsないのagzPointとagzPointKalmanに格納する if (refresh_Timer.read_ms() >= refresh_Time) { refresh_Timer.reset(); //print_gps(count); Get_GPS(&myGPS); } //get base GPS if( collect_Timer.read_ms() >= collect_Time){ collect_Timer.reset(); Send_Request_Base(collect_flag); collect_flag++; if(collect_flag == 4){ collect_flag = 0; } } if(agz.nowMode == AUTO_GPS_MODE && auto_Timer.read_ms() >= auto_Time){ auto_Timer.reset(); auto_Move(); } } }