統合プログラム

Dependencies:   mbed Servo BMP180

direction.cpp

Committer:
tsubasa_nakajima
Date:
2021-11-01
Revision:
8:7209c810309d

File content as of revision 8:7209c810309d:

#include "mbed.h"
#include "getGPS.h"
#include "Movement.h"
#include "direction.h"

  
// 球面三角法により、大円距離(メートル)を求める
double distance1(double lat1, double lng1, double lat2, double lng2){
    // 円周率
    const double pi = 3.14159265359;
 
    // 緯度経度をラジアンに変換
    double rlat1 = lat1 * pi / 180;
    double rlng1 = lng1 * pi / 180;
    double rlat2 = lat2 * pi / 180;
    double rlng2 = lng2 * pi / 180;
 
    // 2点の中心角(ラジアン)を求める
    double a =
      sin(rlat1) * sin(rlat2) +
      cos(rlat1) * cos(rlat2) *
      cos(rlng1 - rlng2);
    double rr = acos(a);
 
    // 地球赤道半径(メートル)
    const double earth_radius = 6378140;
 
    // 2点間の距離(メートル)
    double distance2 = earth_radius * rr;
 
    return distance2;
}



//CanSatから見た目的地の角度theta(-180<=theta<=180で、角度は正面が0で反時計回り)の計算  
float calculate_theta(float x_0,float y_0,float x_1,float y_1,float x_2,float y_2){
    
    //float x_0 ,y_0: 目的地 , float x_1 ,y_1: 現在地, float x_2 ,y_2: 20秒前の現在地
    //theta_0:目的地の角度,theta_1:CanSatの角度theta:CanSatから見た目的地の角度(-180)   
    //theta_0,theta_1は北が90、東が0
    //theta:CanSatから見た目的地の角度(-180<=theta<=180で、角度は正面が0で反時計回り)   
    
    float theta_0,theta_1;
    
    if(x_0 == x_1 && x_1 == x_2){
        
        if(y_0 - y_1 > 0){
            theta_0 =  90;
            }
        if(y_0 - y_1 < 0){
            theta_0 = 270;
            }
        if(y_0 - y_1 == 0){
            theta_0 = 0;
            }
        
        if(y_1 - y_2 > 0){
            theta_1 =  90;
            }
        if(y_1 - y_2 < 0){
            theta_1 = 270;
            }
        if(y_1 - y_2 == 0){
            theta_1 = 0;
            }    
    }
        
    if(x_0 == x_1 && x_1 != x_2){
        theta_1 = atan(9*(y_1 - y_2)/11*(x_1- x_2));  
        
        if(y_0 - y_1 > 0){
            theta_0 =  90;
            }
            
        if(y_0 - y_1 < 0){
            theta_0 = 270;
            }
            
        if(y_0 - y_1 == 0){
            theta_0 = 0;
            }
    
        if(y_1 - y_2 > 0 && x_1 - x_2 < 0){
            theta_1 = theta_1 - 180;
        }
        if(y_1 - y_2 == 0 && x_1 - x_2 < 0){
            theta_1 = 180;
        }
        if(y_1 - y_2 < 0 && x_1 - x_2 > 0){
            theta_1 = theta_1 + 180;
        }     
    }
    
    if(x_0 != x_1 && x_1 == x_2){
        
        theta_0 = atan(9*(y_0 - y_1)/11*(x_0 - x_1));  
    
        if(y_0 - y_1 > 0 && x_0 - x_1 < 0){
            theta_0 = theta_0 - 180;
        }
        if(y_0 - y_1 == 0 && x_0 - x_1 < 0){
            theta_0 = 180;
        }
        if(y_0 - y_1 < 0 && x_0 - x_1 > 0){
            theta_0 = theta_0 + 180;
        }
        
        if(y_1 - y_2 > 0){
            theta_1 =  90;
            }
        if(y_1 - y_2 < 0){
            theta_1 = 270;
            }
        if(y_1 - y_2 == 0){
            theta_1 = 0;
            }    
    }
    
    else{
        theta_0 = atan(9*(y_0 - y_1)/11*(x_0 - x_1));
        theta_1 = atan(9*(y_1 - y_2)/11*(x_1- x_2));  
    
        if(y_0 - y_1 > 0 && x_0 - x_1 < 0){
            theta_0 = theta_0 - 180;
        }
        if(y_0 - y_1 == 0 && x_0 - x_1 < 0){
            theta_0 = 180;
        }
        if(y_0 - y_1 < 0 && x_0 - x_1 > 0){
            theta_0 = theta_0 + 180;
        }
    
        if(y_1 - y_2 > 0 && x_1 - x_2 < 0){
            theta_1 = theta_1 - 180;
        }
        if(y_1 - y_2 == 0 && x_1 - x_2 < 0){
            theta_1 = 180;
        }
        if(y_1 - y_2 < 0 && x_1- x_2 > 0){
            theta_1 = theta_1 + 180;
        } 
    
        
    }
    
    float theta = theta_0 - theta_1;
    if(theta < -180){
      theta = 360 - theta;
      }
    if(theta > 180){
      theta = -360 + theta;
      }  
      
    return theta;
}      

void direction::walk(){
        GPS gps(D1, D0);
        Movement idou;
        s = 0; 
        x_0 = 0;
        y_0 = 0;
        x_01 = 0;
        y_01 = 0;
        
        while(s<1){
        if(gps.getgps()){
            x_1 = gps.longitude; 
            y_1 = gps.latitude;
            idou.move_forward(20);
            s = s + 1;
            }
        }    
        
       while(1){        
        if(gps.getgps()){ //現在地取得
            x_2 = x_1;           
            y_2 = y_2;           //20(+回転or復帰時間)秒前に居た地点の緯度と経度を取得
            x_1 = gps.longitude; 
            y_1 = gps.latitude; //現在地の緯度と経度を取得
            d1 = distance1(y_1,x_1,y_0,x_0);
            d = distance1(y_1,x_1,y_2,x_2);
            theta =  calculate_theta(x_0,y_0,x_1,y_1,x_2,y_2);
            
            //中間地点に到達したらbreak            
            if(d1 < 15){
                idou.stop();
                break;
                } 
            
            //移動距離が短ければ横転と判定し復帰   
            if(d < 3){
                idou.wakeup(2);
                idou.stop();
            } 
            
            //Θによって回転か直進か決定
            if(-30 < theta && theta < 30){
                idou.move_forward(20);
                }
            if(theta >=30){
                idou.turn_right(theta);
                idou.stop();
                idou.move_forward(20);
                }
            if(theta<=-30){
                idou.turn_left(theta);
                idou.stop();
                idou.move_forward(20);
                }        
                            
        }
    }
        while(s < 2){
            if(gps.getgps()){
            x_1 = gps.longitude; 
            y_1 = gps.latitude;
            idou.move_forward(20);
            s  = s + 1;
            }  
        }
    
    while(1){
        
        if(gps.getgps()){ //現在地取得
            x_2 = x_1;           
            y_2 = y_2;           //20(+回転or復帰時間)秒前に居た地点の緯度と経度を取得
            x_1 = gps.longitude; 
            y_1 = gps.latitude; //現在地の緯度と経度を取得
            d2 = distance1(y_1,x_1,y_01,x_01);
            d = distance1(y_1,x_1,y_2,x_2);
            theta =  calculate_theta(x_01,y_01,x_1,y_1,x_2,y_2);
            
            //ゴール地点に到達したらbreak
            if(d2 < 15){
                idou.stop();
                break;
                } 
            
            //移動距離が短ければ横転と判定し復帰   
            if(d < 3){
                idou.wakeup(2);
                idou.stop();
            } 
            
            //thetaによって回転か直進か決定
            if(-30 < theta && theta < 30){
                idou.move_forward(20);
                }
            if(theta >=30){
                idou.turn_right(theta);
                idou.move_forward(20);
                }
            if(theta<= -30){
                idou.turn_left(theta);
                idou.move_forward(20);
                }        
                            
        }
    
        
    } 
    
    idou.stop();  
}