0106
Dependencies: ADXL345 AigamozuControlPackets HMC5843 ITG3200 MBed_Adafruit-GPS-Library XBee agzIDLIST mbed
Diff: main.cpp
- Revision:
- 0:75c267089975
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Jan 06 10:49:22 2016 +0000 @@ -0,0 +1,546 @@ +/**********************************************/ +// +// +// +// 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関数の実装 +// +//2015/05/30 +//新カルマンフィルタの実装 +// +//2015/06/04 +//内外判定の結果によって動きを変えるように変更 +//ロボットA,B,C,D,Eは基地局a,b,c,dの内側を +//ロボットF,G,H,I,Jは基地局e,f,g,hの内側を走る +/**********************************************/ + +#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 = 'G'; + +const int collect_base_address[4]={0,1,2,3};//1,2,3,4,5,6,7,8 +//************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_1 1.0e-8 +#define FIRST_S2_2 1.0e-6 +#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_1,s2x_prev=FIRST_S2_1,s2y_cur=FIRST_S2_1,s2y_prev=FIRST_S2_1;//緯度経度のの時刻tと時刻t-1での共分散 +double s2_R=FIRST_S2_2;//GPSセンサの分散 +double s2_Q=FIRST_S2_2; +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(collect_base_address), + 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=false; // 毎回の内外判定の結果を格納 + static bool out_flag = false; // 外側処理の実行フラグ + const int sequenceTime[4] = {30000, 31000, 34000, 34200}; + const int outSequenceTime[4] = {10000, 11000, 14000, 14200}; + + + //内外判定を行うtrueの時は外 falseの時は内側にいる + result = agz.gpsAuto(collect_base_address); + + //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+s2_Q)/(s2x_prev+s2_R+s2_Q); + Ky = (s2y_prev+s2_Q)/(s2y_prev+s2_R+s2_Q); + //estimate + x_cur = x_prev + Kx*(zx-x_prev); + y_cur = y_prev + Ky*(zy-y_prev); + //calc sigma + s2x_cur = (1-Kx)*(s2x_prev+s2_Q); + s2y_cur = (1-Ky)*(s2y_prev+s2_Q); + +} + +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; + + + + + myGPS.begin(GPS_BAUD_RATE); + + Timer collect_Timer; + //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 + printf("start\n"); + + char input_data=0; + int speed=64; + while (true) { + input_data=0; + scanf("%c",&input_data); + + switch(input_data){ + case 'i'://stanby + printf("stanby\n"); + agz.createChangeModeCommand('A','G',0); + ZBTxRequest tx64request1(robot_Address[6],agz.packetData,agz.getPacketLength()); + xbee.send(tx64request1); + break; + case 'o'://manual + printf("manual\n"); + agz.createChangeModeCommand('A','G',1); + ZBTxRequest tx64request2(robot_Address[6],agz.packetData,agz.getPacketLength()); + xbee.send(tx64request2); + break; + case 'w'://zennsinn + printf("sensin\n"); + agz.createManualCommad('A','G',1,speed,1,speed); + ZBTxRequest tx64request3(robot_Address[6],agz.packetData,agz.getPacketLength()); + xbee.send(tx64request3); + break; + case 'a'://hidari + printf("hidari\n"); + agz.createManualCommad('A','G',2,speed,1,speed); + ZBTxRequest tx64request4(robot_Address[6],agz.packetData,agz.getPacketLength()); + xbee.send(tx64request4); + break; + case 'd'://migi + printf("migi\n"); + agz.createManualCommad('A','G',1,speed,2,speed); + ZBTxRequest tx64request5(robot_Address[6],agz.packetData,agz.getPacketLength()); + xbee.send(tx64request5); + break; + case 's'://stop + printf("stop\n"); + agz.createManualCommad('A','G',0,speed,0,speed); + ZBTxRequest tx64request6(robot_Address[6],agz.packetData,agz.getPacketLength()); + xbee.send(tx64request6); + break; + case 'z'://back + printf("back\n"); + agz.createManualCommad('A','G',2,speed,2,speed); + ZBTxRequest tx64request7(robot_Address[6],agz.packetData,agz.getPacketLength()); + xbee.send(tx64request7); + break; + case '1': + printf("change\n"); + speed=32; + break; + case '2': + printf("change\n"); + speed = 64; + break; + case '3': + printf("change\n"); + speed=128; + break; + default: + break; + } + }//endifisAvailable + + + } + +