9/19

Dependencies:   mbed KondoServoLibrary CalPID AMT21_right_arm ros_lib_melodic MotorController_AbsEC_right_arm

main.cpp

Committer:
oshin1030
Date:
2021-09-10
Revision:
3:ab266b418d90
Parent:
2:aeae129daa37
Child:
4:e20532e09d42

File content as of revision 3:ab266b418d90:

#include "mbed.h"
#include "AMT21.h"
#include "CalPID.h"
#include "MotorController.h"
#include "KondoServo.h"
//#include <ros.h>
//#include <geometry_msgs/Point.h>


#define DELTA_T 0.01    //制御周期
#define DUTY_MAX 0.8     //duty比の最大値
#define OMEGA_MAX 15    //速度制御を利用した角度制御での角速度の最大値
#define L_1 0.891
#define L_2 0.820
#define L_3 0.71362

#ifndef M_PI
#define M_PI 3.14159265359f
#endif

Timer timer_loop;  //制御周期用
DigitalOut myled_1(LED1);
DigitalOut myled_2(LED2);
DigitalOut myled_3(LED3);
DigitalOut myled_4(LED4);

/////////////////               宣言部分                  //////////////////////
CalPID speed_pid(0.2,0,0.00455,DELTA_T,DUTY_MAX);   //速度制御のPD計算
CalPID angle_duty_pid_1(0.5,0,0.00056,DELTA_T,DUTY_MAX);   //角度制御(duty式)のPD計算
CalPID angle_duty_pid_2(0.5,0.01,0.00056,DELTA_T,DUTY_MAX);   //角度制御(duty式)のPD計算

CalPID angle_omega_pid_1(4.3,0,0.01,DELTA_T,OMEGA_MAX);//角度制御(速度式)のPD計算 原点
CalPID angle_omega_pid_2(2.5,0,0.1,DELTA_T,OMEGA_MAX);//角度制御(速度式)のPD計算 肘関節

KondoServo servo(p13,p14,1,115200);
//Amt21 ecB(p28,p27,p8);//肘関節
Amt21 ecA(p28,p27,p8); //原点
Amt21 ecB(p9,p10,p15);//肘関節
// 上で宣言したインスタンスをMotorControllerに与える //
MotorController motorA(p25,p26,DELTA_T,ecA,speed_pid,angle_duty_pid_1,angle_omega_pid_1);//原点
MotorController motorB(p24,p23,DELTA_T,ecB,speed_pid,angle_duty_pid_2,angle_omega_pid_2);//肘関節
PwmOut motorR(p22); //fan
PwmOut motorL(p21);
//////////////////////////////////////////////////////////////////////////

double deg_rad_convert(double deg)
{
    return deg*M_PI/180;
}

double rad_deg_convert(double rad)
{
    return rad*180/M_PI;
}

void angleControll()
{
    //motorA.AcOmega_1(target_rad);    //duty式角度制御
    //motorB.AcOmega_2(target_rad);   //速度式角度制御
}


double function(double x)
{
    double y;
    y = 0.6 + sqrt(0.01 - (x-0.6)*(x-0.6));//円の軌道
    return y;
}

double theta1(double x, double y, double theta_2)//原点角度計算
{
    //(x:目標座標 y:目標座標)
    double theta_1;
    theta_1 = atan(y/x)-atan(L_2*sin(theta_1)/(L_1+L_2*cos(theta_2)));
    //printf("%f\r\n",theta_1);
    return theta_1;
}

double theta2(double x, double y)//肘関節角度計算
{
    double theta_2;
    theta_2 = acos((x*x+y*y-L_1*L_1-L_2*L_2)/(2*L_1*L_2));
    //printf("%f  ",theta_2);
    return theta_2;
}

double robot_x, robot_y; //ロボット座標
double pot_x, pot_y; //ポット座標
int fan_switch = -1, arm_switch = 0; //扇風機on/off, アーム関節on/off

//void robotCallback(const geometry_msgs::Point &robot_pos)
//{
//    robot_x = robot_pos.x;
//    robot_y = robot_pos.y;
//
//}
//void potCallback(const geometry_msgs::Point &pot_pos)
//{
//    pot_x = pot_pos.x;
//    pot_y = pot_pos.y;
//}
//void switchCallback(const geometry_msgs::Point &button_fa)
//{
//    fan_switch  = button_fa.x; //fan
//    arm_switch = button_fa.y;    //arm
//}

//////////////////////////////////////////////////////////////////////////////

float plot[]= {0.6,0.1,0.6,0.1};
double x[20];
double target_radA[20];
double target_radB[20];

//ros::NodeHandle nh;
//ros::Subscriber<geometry_msgs::Point> sub_robo_posi("/robot",&robotCallback);
//ros::Subscriber<geometry_msgs::Point> sub_pot_posi("/posi_pot",&potCallback);
//ros::Subscriber<geometry_msgs::Point> sub_switch("/fan_switch",&switchCallback);

int main ()
{
    
//    nh.getHardware()->setBaud(115200);
//    nh.initNode();
//    nh.subscribe(sub_robo_posi);
//    nh.subscribe(sub_pot_posi);
//    nh.subscribe(sub_switch);
//    NVIC_SetPriority(TIMER3_IRQn, 5);

    motorA.setEquation(0.082047,0.020033,-0.08206,0.020087);//原点、速度制御のC値D値
    motorB.setEquation(0.096001,0.067528,-0.08753,0.043631);//肘関節、速度制御のC値D値
    motorR.period_us(50);
    motorL.period_us(50);
//////////////////////////////////////////////////////////////////////////////
    int i = 0;
    int mode_1 = 1; //arm_switch = 1 用
    int mode_0 = 1; //arm_switch = 0 用
    double Deg,angle,Count,rad;
    double DegA,DegB;
    double angleA,angleB;
    double CountA,CountB;
    double radA,radB;
    double start_theta_A, start_theta_B; //初期角度
    double target_theta_A,target_theta_B;//目標角度(robot_xy, pot_xyから計算)
    int servo_speed = 37;
    int servo_degree;
    static bool IsFirst = true;
    int M=0,N=0;
    /*
    for(int i = 0; i < 20; i++) {//軌道のプロット
        x[i] = 0.5 + 0.01*i;
        target_radA[i] = theta1(x[i],function(x[i]),20.0);
        target_radB[i] = theta2(x[i],function(x[i]),target_radA[i]);
        target_radA[i] = -target_radA[i];
        target_radB[i] = target_radB[i] - 1;
        printf("%f\t%f\t%f\r\n",x[i],target_radA[i],target_radB[i]);
    }*/

    double target_x = 1.05; //ポット相対座標x
    double target_y = 1.05; //ポット相対座標y
    target_theta_B = theta2(target_x,target_y); //目標角度計算(第二関節)
    target_theta_A = theta1(target_x,target_y,target_theta_B); //目標角度計算(第一関節)
    servo_degree = 148 - (int)(0.7111*rad_deg_convert(target_theta_B)); //目標位置(サーボモータ)
    target_theta_B = deg_rad_convert(5.0); //第二関節決め打ち(実験用)
    target_theta_A =deg_rad_convert(45.0); //第一関節決め打ち(実験用)
    //printf("%f\t%f\r\n",target_theta_A,target_theta_B);
    start_theta_A = deg_rad_convert(95);
    start_theta_B = deg_rad_convert(-165);
    wait(3);

    while(1) {
        /*
        ecA.rewriteCount_1();
        ecB.rewriteCount_2();
        DegA = ecA.getDeg();
        DegB = ecB.getDeg();
        radA = ecA.getRad()/3 + deg_rad_convert(159.72);
        if(radA >= 0){
            radB = ecB.getRad()*36/60 - deg_rad_convert(102 + angleA/3 + angleA*16.63/90);
        }else if(radA < 0){
            radB = ecB.getRad()*36/60 - deg_rad_convert(102 + angleA/3 - angleA*16.63/90);
        }
        angleA = DegA/3 + 159.72;
        if(angleA >= 0){
            angleB = DegB*36/60  - angleA/3-102-angleA*16.63/90;
        }else if(angleA < 0){
            angleB = DegB*36/60  - angleA/3-102+angleA*16.63/90;
        }

        CountA = ecA.getCount();
        CountB = ecB.getCount();
        printf("%f\t%f\t%f\t%f\t%f\t%f\r\n",DegA,DegB,CountA,CountB,angleA,angleB);
        */
        //nh.spinOnce();
        wait_ms(1);
        ecA.rewriteCount_1();
        ecB.rewriteCount_2();
        DegA = ecA.getDeg();
        DegB = ecB.getDeg();
        radA = ecA.getRad()/3 + deg_rad_convert(159.72);
        if(radA >= 0) {
            radB = ecB.getRad()*36/60 - deg_rad_convert(102 + angleA/3 + angleA*16.63/90);
        } else if(radA < 0) {
            radB = ecB.getRad()*36/60 - deg_rad_convert(102 + angleA/3 - angleA*16.63/90);
        }
        angleA = DegA/3 + 159.72;
        if(angleA >= 0) {
            angleB = DegB*36/60 - 102 - angleA/3 - angleA*16.63/90;
        } else if(angleA < 0) {
            angleB = DegB*36/60 - 102 - angleA/3 + angleA*16.63/90;
        }
        
        
        if(arm_switch == 1) {
            printf("%f\t%f\t%f\t%f\t%f\t%f\r\n",angleA,angleB,radA,radB,target_theta_A,target_theta_B);
            myled_2 = 1;
            mode_0 = 1;
            if(mode_1 == 1) {
                motorA.AcOmega_1(target_theta_A,0.2);
                if(fabs(target_theta_A - radA) < 0.01) { //収束判定
                    mode_1++;
                }
                printf("1_1  ");
            } else if(mode_1 == 2) {
                motorB.AcOmega_2(target_theta_B,angleA,0.2);
                if(fabs(target_theta_B - radB) < 0.01) { //収束判定
                    mode_1++;
                }
                printf("1_2  ");
            } else if(mode_1 == 3) {
                mode_1++;
                printf("1_3  ");
            } else if(mode_1 == 4) {
                printf("1_4  ");
                motorA.AcOmega_1(target_theta_A,0.05); //位置固定
                motorB.AcOmega_2(target_theta_B,angleA,0.05); //位置固定

                if(fabs(target_theta_A - radA) < 0.001) { //収束判定
                    target_theta_B = target_theta_B + 0.01744;
                    M++;
                    if(M == 2) {
                        target_theta_B = target_theta_B - 0.01744*2;
                        M = 0;
                    }
                }
                if(fabs(target_theta_B - radB) < 0.001) { //収束判定
                    target_theta_B = target_theta_B + 0.01744;
                    N++;
                    if(N == 2) {
                        target_theta_B = target_theta_B - 0.01744*2;
                        N = 0;
                    }
                }
            }
        } else if(arm_switch == 0) {
            printf("%f\t%f\t%f\t%f\t%f\t%f\r\n",angleA,angleB,radA,radB,start_theta_A,start_theta_B);
            myled_2 = !myled_2;
            mode_1 = 1;
            if(mode_0 == 1) {
                motorA.AcOmega_1(start_theta_A,0.2);
                if(fabs(start_theta_A - radA) < 0.01) { //収束判定
                    mode_0++;
                }
                printf("0_1  ");
            } else if(mode_0 == 2) {
                motorB.AcOmega_2(start_theta_B,angleA,0.2);
                if(fabs(start_theta_B - radB) < 0.01) { //収束判定
                    mode_0++;
                }
                printf("0_2  ");
                
                
                
            } else if(mode_0 == 3) {
                mode_0++;
                printf("0_3  ");
            } else if(mode_0 == 4) {
                printf("0_4  ");
            }
        }
        if(fan_switch == 0) {
            myled_1 = 0;
            motorR = 0;
        } else if (fan_switch == 1) {
            myled_1 = 1;
            motorR = 0.1; //扇風機回す
            printf("fan_on  ");
        }
    }
}