9/19
Dependencies: mbed KondoServoLibrary CalPID AMT21_right_arm ros_lib_melodic MotorController_AbsEC_right_arm
main.cpp
- Committer:
- oshin1030
- Date:
- 2021-09-19
- Revision:
- 4:e20532e09d42
- Parent:
- 3:ab266b418d90
File content as of revision 4:e20532e09d42:
#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; } 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,robot_theta; //ロボット座標 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; robot_theta = robot_pos.z; } 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 } ////////////////////////////////////////////////////////////////////////////// ros::NodeHandle nh; ros::Subscriber<geometry_msgs::Point> sub_robo_posi("/posi_dr",&robotCallback); ros::Subscriber<geometry_msgs::Point> sub_pot_posi("/posi_pot",&potCallback); ros::Subscriber<geometry_msgs::Point> sub_switch("/fan_switch",&switchCallback); geometry_msgs::Point relative_posi_pot; geometry_msgs::Point target_kakudo; ros::Publisher pub_pot("/relative_pot",&relative_posi_pot); ros::Publisher pub_theta("/target_theta",&target_kakudo); int main () { nh.getHardware()->setBaud(115200); nh.initNode(); nh.subscribe(sub_robo_posi); nh.subscribe(sub_pot_posi); nh.subscribe(sub_switch); nh.advertise(pub_pot); nh.advertise(pub_theta); 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 mode_1 = 1; //arm_switch = 1 用 int mode_0 = 4; //arm_switch = 0 用 double DegA,DegB; double angleA,angleB; double radA,radB; double start_theta_A, start_theta_B; //初期角度 double target_theta_A=0,target_theta_B=0;//目標角度(robot_xy, pot_xyから計算) double relative_pot_x,relative_pot_y;//アーム原点から見たポットの相対座標 int servo_speed = 37; int servo_degree; target_kakudo.x=0; target_kakudo.y=0; 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(85); //初期角度 start_theta_B = deg_rad_convert(-140); //初期角度 wait(3); while(1) { 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(115 + angleA/3 + angleA*16.63/90); } else if(radA < 0) { radB = ecB.getRad()*36/60 - deg_rad_convert(115 + angleA/3 - angleA*16.63/90); } angleA = DegA/3 + 159.72; if(angleA >= 0) { angleB = DegB*36/60 - 115 - angleA/3 - angleA*16.63/90; } else if(angleA < 0) { angleB = DegB*36/60 - 115 - angleA/3 + angleA*16.63/90; } ///////////////目標角度を常に計算する////////////////// relative_pot_x = 6.0 - (robot_x + (0.185*cos(-robot_theta) + 0.29275*sin(-robot_theta))); //potの相対座標x(目標座標) relative_pot_y = 8.0 - (robot_y + (0.185*sin(-robot_theta) - 0.29275*cos(-robot_theta))); //potの相対座標y(目標座標) target_theta_B = theta2(relative_pot_x,relative_pot_y); //目標角度計算(第二関節) target_theta_A = theta1(relative_pot_x,relative_pot_y,target_theta_B); //目標角度計算(第一関節) relative_posi_pot.x = relative_pot_x; relative_posi_pot.y = relative_pot_y; if(target_theta_A){ target_kakudo.x = double(target_theta_A); target_kakudo.y = double(target_theta_B); } target_kakudo.z=0; pub_pot.publish(&relative_posi_pot); pub_theta.publish(&target_kakudo); 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); motorB.AcOmega_2(target_theta_B,angleA,0.2); if(fabs(target_theta_A - radA) < 0.01 && fabs(target_theta_B - radB) < 0.01) { //収束判定 mode_1++; } //printf("1_1 "); } else if(mode_1 == 2) {//最初にswitchをオンにした後のため、最大dutyを下げておく //printf("1_2 "); motorA.AcOmega_1(target_theta_A,0.1);//更新し続ける目標値に常に移動 motorB.AcOmega_2(target_theta_B,angleA,0.1); //更新し続ける目標値に常に移動 } } 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 = 0; mode_1 = 1; if(mode_0 == 1) { motorA.AcOmega_1(start_theta_A,0.2); //最初の位置に移動 motorB.AcOmega_2(start_theta_B,angleA,0.2);//最初の位置に移動 if(fabs(start_theta_B - radB) < 0.01 && fabs(start_theta_A - radA) < 0.01) { //収束判定 mode_0++; } //printf("0_1 "); } else if(mode_0 == 2) { motorA.AcOmega_1(start_theta_A,0.01); motorB.AcOmega_2(start_theta_B,angleA,0.04); //printf("0_2 "); } else {} } if(fan_switch == 0) { myled_1 = 0; motorR = 0; } else if (fan_switch == 1) { myled_1 = 1; motorR = 0.5; //扇風機回す //printf("fan_on "); } else if (fan_switch == 2){ myled_1 = !myled_1; //点滅 motorL = 0.5; } } }