yuto kawamura
/
MR2_n_1_class
l
main.cpp
- Committer:
- eri
- Date:
- 2019-03-30
- Revision:
- 3:df0c9883e403
- Parent:
- 2:90bdca5d5b60
- Child:
- 4:3f59e4f5ca30
File content as of revision 3:df0c9883e403:
#include "mbed.h" #include "EC.h" #include "KondoServo.h" #include "hcsr04.h" #include "pin.h" #include "microinfinity.h" Timer timer; //パラメタ double dutylimit_nomal = 0.2; // duty出力の上限値(通常時) double dutylimit_turn = 0.4; // duty出力の上限値(回転時) int ecgear = 25; //エンコーダのギアの歯数 /*double Kp_r = 0.342000; //P値 double Ki_r = 0.013062; //I値 double Kd_r = 0.003266; //D値 double Kp_l = 0.342000; //P値 double Ki_l= 0.013062; //I値 double Kd_l = 0.003266; //D値*/ double Kp_r_n = 0.0015; //P値 通常時右 double Ki_r_n = 0.001; //I値 double Kd_r_n = 0.0001; //D値 double Kp_l_n = 0.0015; //P値 回転時右 double Ki_l_n = 0.001; //I値 double Kd_l_n = 0.0001; //D値 double Kp_r_t = 0.004; //P値 double Ki_r_t = 0.001; //I値 double Kd_r_t = 0.0001; //D値 double Kp_l_t = 0.004; //P値 double Ki_l_t = 0.001; //I値 double Kd_l_t = 0.0001; //D値 double leg_wait_time = 0.2; //脚の伸縮にかかる時間 double leg_wait_time_l = 1; //長い足にかかる時間 double target_max = 310; //直動機構の目標座標の上限(オーバーシュートを考慮して短めに設定) double target_min = 20; //直動機構の目標座標の下限(オーバーシュートを考慮して短めに設定) double servo_iniposi=105; //サーボ初期角度 double error_target=10;//PIDでの許容誤差 double pid_time=0.01;//PIDの割り込み時間 double accel_max=0.01;//加速制限 //定数 #define Pi 3.14159265359 //円周率π //変数 int target_num=0; //現在の目標プロット bool move_r=0,move_l=0; // double target_r_out=0,target_l_out=0; bool reach_target_r=0,reach_target_l=0; double posi_r=0,posi_l=0; double pre_out_r=0,pre_out_l=0; bool turn_mode=0; void setup(); void out_r(double);//モーターの出力 void out_l(double);//モーターの出力 void pid_r(double,double); //PID (移動先の座標(機体内)[mm],許容誤差の絶対値[mm]) void pid_l(double,double); //PID (移動先の座標(機体内)[mm],許容誤差の絶対値[mm]) void move(double,double); //(target_r,target_l) void up(int); void down(int); //void reset(); //脚位置の初期化 void turn(double); //旋回動作 void turn_2(double); void straight(double); //目的地まで直進 void wait_MR1(); double get_dist(); void output(); void sanddune(); void tussock(); Ticker ticker; int main() { setup(); ticker.attach(&output,pid_time); /*while(1){ printf("%f\r\n",degree0); }*/ wait(3); /*down(long_r); down(long_l); wait(1); up(long_r);*/ //straight(2800); //turn_2(45); //move(50,50); //move(190,190); sanddune(); /*for(int i=0;i<15;i++){ move(220,220); move(80,80); }*/ /*for(int i=0;i<5;i++){ move(300,300); move(30,30); } turn_2(45); for(int i=0;i<2;i++){ move(300,300); move(30,30); } turn_2(0); for(int i=0;i<4;i++){ move(300,300); move(30,30); }*/ //sanddune(); //move(300,300); //move(-300,-300); //wait(5); /*move(300,300); move(30,30); move(300,300); move(30,30); move(300,300); move(30,30); move(300,300); move(30,30); move(300,300); move(30,30);*/ /* wait_MR1(); for(int i=0; i<4; i++) { move(360,360); move(10,10); } turn(700); sanddune(); move(360,360); move(10,10); move(10,10); turn(-700); tussock();*/ } double get_dist() { sensor.start(); //wait_ms(50); //sensor.start()で信号を送ったあと反射波が帰ってきてから距離データが更新されるため、少し待つ必要がある。 //何ループも回す場合は不要。また、時間は適当だから調整が必要。 return sensor.get_dist_cm(); } //初期設定 void setup() { motor_r_f.period_us(100); motor_r_b.period_us(100); motor_l_f.period_us(100); motor_l_b.period_us(100); switch_max.mode(PullUp); switch_min.mode(PullUp); switch_x.mode(PullUp); switch_y.mode(PullUp); switch_hand.mode(PullUp); for(int i=0; i<4; i++) { air[i]=1; } air[4]=0; air[5]=0; servo.init(); wait_us(1000); servo.set_degree(0,servo_iniposi); device.baud(115200); device.format(8,Serial::None,1); device.attach(dev_rx, Serial::RxIrq); wait(0.05); theta0=degree0; } int k=0; void output() { posi_r=1.0*ecgear*Pi*ec_r.getCount()/resolution; posi_l=1.0*ecgear*Pi*ec_l.getCount()/resolution; if(move_r) pid_r(target_r_out,error_target); else out_r(0); if(move_l) pid_l(target_l_out,error_target); else out_l(0); k++; if(k>50){ printf("%f, %f, %f\r\n",posi_r,posi_l,degree0); k=0; } } //モーターの出力 void out_r (double duty) { double dutylimit=0; if(turn_mode)dutylimit=dutylimit_turn; else dutylimit=dutylimit_nomal; if(duty > 0) { //入力duty比が正の場合 if(duty-pre_out_r >accel_max)duty=pre_out_r+accel_max; //if(switch_max == 0) { //上限のリミットスイッチが押されていない場合 if( fabs( duty ) < dutylimit ) { //制限値内 motor_r_f = fabs(duty); motor_r_b = 0; } else { //制限値超 motor_r_f = dutylimit; motor_r_b = 0; } /*} else { //上限のリミットスイッチが押されている場合 motor_r_f = 0; motor_r_b = 0; }*/ } else {//入力duty比が負の場合 if(pre_out_r-duty >accel_max)duty=pre_out_r-accel_max; //if(switch_min == 0) { //下限のリミットスイッチが押されていない場合 if( fabs(duty) < dutylimit) { //制限値内 motor_r_f = 0; motor_r_b = fabs(duty); } else { //制限値超 motor_r_f = 0; motor_r_b = dutylimit; } /*} else { //下限のリミットスイッチが押されている場合 motor_r_f = 0; motor_r_b = 0; }*/ } pre_out_r=duty; //if(k>49)printf("%f\r\n",dutylimit); } void out_l (double duty) { double dutylimit=0; if(turn_mode)dutylimit=dutylimit_turn; else dutylimit=dutylimit_nomal; if(duty > 0) { //入力duty比が正の場合 if(duty-pre_out_l >accel_max)duty=pre_out_l+accel_max; //if(switch_max == 0) { //上限のリミットスイッチが押されていない場合 if( fabs( duty ) < dutylimit ) { //制限値内 motor_l_f = fabs(duty); motor_l_b = 0; } else { //制限値超 motor_l_f = dutylimit; motor_l_b = 0; } /*} else { //上限のリミットスイッチが押されている場合 motor_l_f = 0; motor_l_b = 0; }*/ } else {//入力duty比が負の場合 if(pre_out_l-duty >accel_max)duty=pre_out_l-accel_max; //if(switch_min == 0) { //下限のリミットスイッチが押されていない場合 if( fabs(duty) < dutylimit) { //制限値内 motor_l_f = 0; motor_l_b = fabs(duty); } else { //制限値超 motor_l_f = 0; motor_l_b = dutylimit; } /*} else { //下限のリミットスイッチが押されている場合 motor_l_f = 0; motor_l_b = 0; }*/ } pre_out_l=duty; } double pile_r=0,distance_r_old=0,pile_l=0,distance_l_old=0; //PID制御 void pid_r(double target,double error) //(移動先の座標(機体内)[mm],許容誤差の絶対値[mm]) { double Kp_r,Ki_r,Kd_r; if(turn_mode){ Kp_r=Kp_r_t; Ki_r=Ki_r_t; Kd_r=Kd_r_t; }else{ Kp_r=Kp_r_n; Ki_r=Ki_r_n; Kd_r=Kd_r_n; } move_r=1; double deviation = target - posi_r; //printf("%f,%f\r\n",posi_r,deviation); pile_r += deviation; out_r(deviation * Kp_r - (posi_r - distance_r_old) / pid_time * Kd_r + pile_r * Ki_r * pid_time); distance_r_old = posi_r; if (fabs(deviation) < error) { out_r(0); pile_r=0; move_r=0; reach_target_r=1; } } void pid_l(double target,double error) //(移動先の座標(機体内)[mm],許容誤差の絶対値[mm]) { double Kp_l,Ki_l,Kd_l; if(turn_mode){ Kp_l=Kp_l_t; Ki_l=Ki_l_t; Kd_l=Kd_l_t; }else{ Kp_l=Kp_l_n; Ki_l=Ki_l_n; Kd_l=Kd_l_n; } move_l=1; double deviation = target - posi_l; pile_l += deviation; out_l(deviation * Kp_l - (posi_l - distance_l_old) / pid_time * Kd_l + pile_l * Ki_l * pid_time); distance_l_old = posi_l; if (fabs(deviation) < error) { out_l(0); pile_l=0; move_l=0; reach_target_l=1; } } //脚を上げる void up(int i) // j=1 待ち時間あり { air[i]=0; //if(j)wait(leg_wait_time); } //脚を降ろす void down(int i) { air[i]=1; //if(j)wait(leg_wait_time); } //移動 void move (double target_r,double target_l) { //pc.printf("x target=%f , posi=%f\r\n",x,linear_posi); int upleg_r=0,upleg_l=0; if(fabs(target_r)>target_max)target_r=target_max; else if(fabs(target_r)<target_min)target_r=target_min; if(target_r>0) { if(posi_r<target_r)upleg_r=r_o_s; else upleg_r=r_i_s; } else { if(posi_r>-target_r)upleg_r=r_o_s; else upleg_r=r_i_s; } if(fabs(target_l)>target_max)target_l=target_max; else if(fabs(target_l)<target_min)target_l=target_min; if(target_l>0) { if(posi_l>target_l)upleg_l=l_o_s; else upleg_l=l_i_s; } else { if(posi_l<-target_l)upleg_l=l_o_s; else upleg_l=l_i_s; } up(upleg_r); up(upleg_l); wait(leg_wait_time); target_r_out=fabs(target_r); target_l_out=fabs(target_l); reach_target_r=0; reach_target_l=0; move_r=1; move_l=1; //printf("%d\r\n",reach_target_r); /*while(reach_target_r==0 || reach_target_l==0){ printf("%d\r\n",reach_target_r); };*/ while(reach_target_r==0 || reach_target_l==0){ wait(0.01); //printf("%d\r\n",reach_target_r); } down(upleg_r); down(upleg_l); wait(leg_wait_time); reach_target_r=0; reach_target_l=0; } void straight(double distance) //とりあえず左右で位置をずらさない前提 { bool reach=0; while(1) { if(distance>0) { if(target_max-posi_r > posi_r-target_min) { if(target_max-posi_r > distance) { move(posi_r+distance,posi_r+distance); reach=1; } else { distance-=target_max-posi_r; move(target_max,target_max); } } else { if(posi_r-target_min > distance) { move(posi_r-distance,posi_r-distance); reach=1; } else { distance-=posi_r-target_min; move(target_min,target_min); } } } else { if(target_max-posi_r > posi_r-target_min) { if(target_max-posi_r > -distance) { move(-posi_r+distance,-posi_r+distance); reach=1; } else { distance+=target_max-posi_r; move(-target_max,-target_max); } } else { if(posi_r-target_min> -distance) { move(-posi_r-distance,-posi_r-distance); reach=1; } else { distance+=posi_r-target_min; move(-target_min,-target_min); } } } if(reach==1)break; } } void turn(double distance) //理論計算の元気が出ないから脚の動かす量のみ distance>0:左回転 { while(1) { if(distance>0) { if(target_max-posi_r > posi_r-target_min) { if(target_max-posi_r > distance) { move(posi_r+distance,-(posi_r+distance)); break; } else { distance-=target_max-posi_r; move(target_max,-target_max); } } else { if(posi_r-target_min > distance) { move(-(posi_r-distance),posi_r-distance); break; } else { distance-=posi_r-target_min; move(-target_min,target_min); } } } else { if(target_max-posi_r > posi_r-target_min) { if(target_max-posi_r > -distance) { move(-(-posi_r+distance),-posi_r+distance); break; } else { distance+=target_max-posi_r; move(target_max,-target_max); } } else { if(posi_r-target_min> -distance) { move(-posi_r-distance,-(-posi_r-distance)); break; } else { distance+=posi_r-target_min; move(-target_min,target_min); } } } } } double a=140,b=70; void turn_2(double target){ turn_mode=1; if(target-degree0>0){ move(a,a); while(1){ move(a+b,-(a+b)); if(fabs(target-degree0)<5)break; move(a,-a); if(fabs(target-degree0)<5)break; //printf("%f\r\n",degree0); } }else{ move(a,a); while(1){ move(-(a+b),a+b); if(fabs(target-degree0)<5)break; move(-a,a); if(fabs(target-degree0)<5)break; //printf("%f\r\n",degree0); } } turn_mode=0; } void sanddune() { move(160,160); down(long_r); down(long_l); wait(1); up(long_l); wait(leg_wait_time_l); target_r_out=50; //target_l_out=50; target_l_out=270; reach_target_r=0; reach_target_l=0; move_r=1; move_l=1; while(reach_target_r==0 || reach_target_l==0){ wait(0.01); } down(long_l); //down(l_o_s); //down(r_i_s); wait(leg_wait_time_l); reach_target_r=0; reach_target_l=0; up(long_r); wait(leg_wait_time_l); target_r_out=250; //target_l_out=250; target_l_out=70; reach_target_r=0; reach_target_l=0; move_r=1; move_l=1; while(reach_target_r==0 || reach_target_l==0){ wait(0.01); } down(long_r); wait(leg_wait_time_l); reach_target_r=0; reach_target_l=0; up(long_l); //up(l_o_s); //up(r_i_s); wait(leg_wait_time_l); target_r_out=160; target_l_out=160; reach_target_r=0; reach_target_l=0; move_r=1; move_l=1; while(reach_target_r==0 || reach_target_l==0){ wait(0.01); } down(long_l); wait(leg_wait_time_l); reach_target_r=0; reach_target_l=0; up(long_r); wait(leg_wait_time_l); target_r_out=220; //target_l_out=220; target_l_out=100; reach_target_r=0; reach_target_l=0; move_r=1; move_l=1; while(reach_target_r==0 || reach_target_l==0){ wait(0.01); } down(long_r); //down(r_o_s); //down(l_i_s); wait(leg_wait_time_l); reach_target_r=0; reach_target_l=0; up(long_l); wait(leg_wait_time_l); target_r_out=80; //target_l_out=80; target_l_out=240; reach_target_r=0; reach_target_l=0; move_r=1; move_l=1; while(reach_target_r==0 || reach_target_l==0){ wait(0.01); } down(long_l); wait(leg_wait_time_l); reach_target_r=0; reach_target_l=0; //up(r_o_s); //up(l_i_s); up(long_r); wait(leg_wait_time_l); target_r_out=0; target_l_out=0; reach_target_r=160; reach_target_l=160; move_r=1; move_l=1; while(reach_target_r==0 || reach_target_l==0){ wait(0.01); } down(long_r); wait(leg_wait_time_l); reach_target_r=0; reach_target_l=0; } void tussock() { for(int i=0; i<3; i++) { up(long_l); wait(leg_wait_time); target_r_out=360; target_l_out=360; while(reach_target_r==0 || reach_target_l==0); down(long_l); wait(leg_wait_time); reach_target_r=0; reach_target_l=0; up(long_r); wait(leg_wait_time); target_r_out=10; target_l_out=10; while(reach_target_r==0 || reach_target_l==0); down(long_r); wait(leg_wait_time); reach_target_r=0; reach_target_l=0; } } /*int k=0; //脚位置の初期化 void reset() { up_x(); while(switch_min == 0) { out(-0.2); k++; if(k>5000) { servo.set_degree(0,servo_iniposi); k=0; } } //pc.printf("%d\r\n",ec.getCount()); ec.reset(); out(0); down_x(); //pc.printf("%d\r\n",ec.getCount()); }*/ /*void straight(double target) { while(1) { double xleg_posi=1.0*ecgear*Pi*ec.getCount()/resolution; //機体内のX脚位置 double dist=target-linear_posi; pc.printf("leg=%f,dist=%f,linear_posi=%f\r\n",xleg_posi,dist,linear_posi); if(fabs(dist)<10) { break; } else if((dist>0 && dist<=(target_max-xleg_posi)) || (dist<0 && dist>=(target_min-xleg_posi))) { move_x(xleg_posi+dist,10); } else if(dist<0) { pc.printf("distance < 0"); break; } else if(dist<=(target_max-target_min-10)) { if(dist<=(rail_len*0.5-target_min-10)) { move_y(dist+xleg_posi-rail_len*0.5,10); } else { move_y(target_min,10); } } else { if(xleg_posi<(rail_len*0.5))move_x(target_max,10); else move_y(target_min,10); } } }*/ void wait_MR1() { while(switch_x==1) { } //while(switch_hand==0); //air_hand=1; wait(1); }