AECL 601
/
3W_1_fmt_squ_0717
Robot 1
Diff: main.cpp
- Revision:
- 0:f0f040a29912
- Child:
- 1:1b3714ce6cf9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Aug 03 06:45:31 2016 +0000 @@ -0,0 +1,411 @@ +/* 版本說明: 正方形軌跡追蹤(從邊緣出發)邊長3m +實驗說明: + 正式實驗:leader為正方形軌跡 + followers維持等腰三角形隊形 + +實驗規格: + +07/17測試紀錄: + +*/ +#include "mbed.h" +#include "math.h" +#include "QEI.h" +// pre-define +#define pi 3.1416 +#define pwm_period_us 500 +#define r 0.05 // wheel radius [m] +#define L 0.125 // distance between wheel center & geometric center [m] +#define pulsesPerRev 1024 +#define kp 0.7// p gain +#define kd 0.03// d gain +// leader initial pose +#define x0 0 //[m] +#define y0 0 //[m] +#define theta0 0//[deg.] +// desied pose +#define xd 0 //[cm] +#define yd 0 //[cm] +#define thetad 0//[deg.] +// error threshold +#define ex 0.02 //[m] +#define ey 0.02 //[m] +#define etheta 3//[deg.] + +PwmOut pwm_1(D9); +PwmOut pwm_2(D10); +PwmOut pwm_3(D11); + +Timer clk; + +// define +QEI w1 (D2, D3, NC, pulsesPerRev, QEI::X4_ENCODING); +QEI w2 (D4, D5, NC, pulsesPerRev, QEI::X4_ENCODING); +QEI w3 (D14, D15, NC, pulsesPerRev, QEI::X4_ENCODING); +// formation para. +//float x=14.43; +float f1[3] = {0,1.5,0}; // formation vector +// odomerty para. +float c1 = r/(3*L), c2 = 2*r/3; +float Current_X[3] = {x0+f1[0],y0+f1[1],((theta0+f1[2])*pi/180)+pi/3}; // X[0] = x; X[1] = y; X[2] = theta; shift pi/3 : origin to new +float Next_X[3] = {0,0,0}; +double d_theta1,d_theta2,d_theta3,d_theta; +int qei1_new, qei2_new, qei3_new, qei1_old, qei2_old, qei3_old; +// control law para. + +float X1[3],V1[3],Vc[3],X1_b[3];// X1_b(X_BAR) is defined as X1-f1 +float XL[3];// = {xd,yd,(thetad*pi/180)+pi/3};// pose of virtual leader [m m rad.] +float u[3] = {0};// control law +float omg1,omg2,omg3;// velocity of wheels +// PWM +float pwm_w1,pwm_w2,pwm_w3; +// Differential +float dy,dx,dtheta; +float dt = 0.05; +// V command +float t1 = 7.5;//2*3.75 +float T = 22.5;//6*3.75 +float S = 3.0;//0.8*3.75 +// Others +DigitalIn mybutton(USER_BUTTON); +DigitalOut myled(LED1); +int c = 3; +int xdir,ydir; // x y direction +float err[3]= {0}; +//bool s0 = false; +bool s0 = true; +bool stop = false; +char gosw = true; +int sw = 13; +float xL0,yL0;// initial position of leader +char kb='p'; + +int main() +{ + pwm_1.period_us(pwm_period_us); + pwm_2.period_us(pwm_period_us); + pwm_3.period_us(pwm_period_us); + + pwm_1.write(0.50); + pwm_2.write(0.50); + pwm_3.write(0.50); + + qei1_old = 0; + qei2_old = 0; + qei3_old = 0; + printf("3W_1_fmt_squ_0717\n"); + printf("Press any key to START\n"); + + while (kb=='p') { + scanf("%c",&kb); + } + + //if (s0 == ture) + s0 = true; + /* + while(c>0) { + wait(1); + c--; + myled = !myled; + } + */ + xL0=0.0;// dire. 9 + yL0=0.0; + //clk.reset(); + clk.start(); + while(1) { + // + myled = 0; + X1[0] = Current_X[0]; + X1[1] = Current_X[1]; + X1[2] = Current_X[2]; + + // P&V command 1→3→9→7→1 + if(s0==true) { + if(gosw==true) { + switch (sw) { + case 97: + xdir=-1; + ydir=0; + sw=71; + break; + case 71: + xdir=0; + ydir=-1; + sw=13; + break; + case 13: + xdir=1; + ydir=0; + sw=39; + break; + case 39: + xdir=0; + ydir=1; + sw=97; + stop=true; + break; + default: + printf("err."); + } + } + gosw=false; + clk.start(); + if(clk.read()<t1) {//1 + Vc[0]=(2*clk.read()/75)*xdir; + Vc[1]=(2*clk.read()/75)*ydir; + Vc[2]=0; + // + XL[0]=xL0 + (clk.read()*clk.read()/75)*xdir;// go to target + XL[1]=yL0 + (clk.read()*clk.read()/75)*ydir; + XL[2]=0+pi/3; + } else if(clk.read()>t1 && clk.read()<(T-t1) ) {//2 + Vc[0]=0.2*xdir; + Vc[1]=0.2*ydir; + Vc[2]=0; + // + XL[0]=xL0 + (clk.read()/5 - 0.75)*xdir; + XL[1]=yL0 + (clk.read()/5 - 0.75)*ydir; + XL[2]=0+pi/3; + } else if (clk.read()>T) {//4 + Vc[0]=0; + Vc[1]=0; + Vc[2]=0; + // + XL[0]=xL0+S*xdir; + XL[1]=yL0+S*ydir; + XL[2]=0+pi/3; + clk.reset(); + xL0=XL[0]; + yL0=XL[1]; + gosw=true; + } else {//3 + Vc[0]=(0.6-2*clk.read()/75)*xdir; + Vc[1]=(0.6-2*clk.read()/75)*ydir; + Vc[2]=0; + // + XL[0]=xL0 + (-((2*clk.read()/75 - 0.8)*(clk.read() - 15))/2 + 2.25)*xdir; + XL[1]=yL0 + (-((2*clk.read()/75 - 0.8)*(clk.read() - 15))/2 + 2.25)*ydir; + XL[2]=0+pi/3; + } + } + //printf("% .2f|% .2f|%f|X V cmd(xdire)\n", XL[0]*100, Vc[0]*100, clk.read()); + + // odometry beginning // + qei1_new = w1.getPulses(); + qei2_new = w2.getPulses(); + qei3_new = w3.getPulses(); + + double qei1 = qei1_new - qei1_old; + double qei2 = qei2_new - qei2_old; + double qei3 = qei3_new - qei3_old; + + //wait_ms(50); + + d_theta1 = qei1*360*pi/(4096*6*180); //DEG to RAD + d_theta2 = qei2*360*pi/(4096*6*180); + d_theta3 = qei3*360*pi/(4096*6*180); + d_theta = c1*( d_theta1 + d_theta2 + d_theta3 ); + + // compute theta + Next_X[2] = Current_X[2] + d_theta; + double theta = Current_X[2]; + float c3 = Current_X[2] + d_theta/2; + // compute y + Next_X[1] = Current_X[1] + c2*(+d_theta1*cos(c3)-d_theta2*cos(pi/3-c3)-d_theta3*cos(pi/3+c3)); + // compute x + Next_X[0] = Current_X[0] + c2*(-d_theta1*sin(c3)-d_theta2*sin(pi/3-c3)+d_theta3*sin(pi/3+c3)); + + // compute velocity + dx =Next_X[0]-Current_X[0]; + dy =Next_X[1]-Current_X[1]; + dtheta =Next_X[2]-Current_X[2]; + V1[0]=dx/dt; + V1[1]=dy/dt; + V1[2]=dtheta/dt; + // transition + Current_X[2] = Next_X[2]; + Current_X[1] = Next_X[1]; + Current_X[0] = Next_X[0]; + + + qei1_old = qei1_new; + qei2_old = qei2_new; + qei3_old = qei3_new; + // odometry end // + + + //printf ("% .1f|% .1f|% .1f|%f|Vc\n", Vc[0]*100, Vc[1]*100, Vc[2]*180/pi,clk.read()); + // control law beginning // + //#define r 0.05 + //#define L 0.125 + X1_b[0] = X1[0]-f1[0]; + X1_b[1] = X1[1]-f1[1]; + X1_b[2] = X1[2]-f1[2]; + + u[0] = -kp*(X1_b[0]-XL[0])-kd*(V1[0]-Vc[0]); + u[1] = -kp*(X1_b[1]-XL[1])-kd*(V1[1]-Vc[1]); + u[2] = -kp*(X1_b[2]-XL[2])-kd*(V1[2]-Vc[2]); + // + omg1 = (5*u[2])/2 + 20*u[1]*cos(theta) - 20*u[0]*sin(theta); + omg2 = (5*u[2])/2 - 20*u[1]*cos(pi/3 - theta) - 20*u[0]*sin(pi/3 - theta); + omg3 = (5*u[2])/2 - 20*u[1]*cos(pi/3 + theta) + 20*u[0]*sin(pi/3 + theta); + // control law end // + + // omega to PWM // + pwm_w1 = 0.5 + omg1/2; + pwm_w2 = 0.5 + omg2/2; + pwm_w3 = 0.5 + omg3/2; + + pwm_1.write(pwm_w1); + pwm_2.write(pwm_w2); + pwm_3.write(pwm_w3); + // END // + + // define error // not abs() yet + err[0] = (Current_X[0]-f1[0])-(0.0); + err[1] = (Current_X[1]-f1[1])-(0.0); + err[2] = (Current_X[2]-f1[2])-XL[2]; + + if ( abs(err[0])<ex && abs(err[1])<ey && abs(err[2])<(etheta*pi/180) && stop==true ) { + printf("Arrived!\n"); + pwm_1.write(0.50); + pwm_2.write(0.50); + pwm_3.write(0.50); + while (mybutton == 1) {} + } + + //print + //printf ("\n"); + //printf("% .2f|% .2f|% .1f|Xnow|%f\n", Current_X[0]*100, Current_X[1]*100,Current_X[2]*180/pi-60,clk.read()); + printf("% .2f|% .2f|% .1f|Xnow|% .2f|% .2f|% .1f|XL|%f\n", + Current_X[0]*100, Current_X[1]*100,Current_X[2]*180/pi-60, + XL[0]*100, XL[1]*100 ,XL[2]*180/pi-60,clk.read()); + //printf("% .1f|% .1f|% .1f|Xc|%f\n", XL[0]*100, XL[1]*100 ,XL[2]*180/pi-60,clk.read()); + ///printf ("% .2f|% .2f|% .1f|Vnow\n", V1[0]*100, V1[1]*100, V1[2]*180/pi); + //printf("%f\n",clk.read()); + //printf("% .1f|% .1f|% .1f|Xc \n", XL[0]*100, XL[1]*100 ,XL[2]*180/pi-60); + //printf("% .2f|% .2f|% .1f|Vc \n", Vc[0]*100, Vc[1]*100, Vc[2]*180/pi); + //printf ("% .2f|% .2f|%f|now\n", Current_X[0]*100, V1[0]*100,clk.read()); + //printf("% .2f|% .2f|%f|X V cmd(xdire)\n", XL[0]*100, Vc[0]*100, clk.read());//測命令用 + //printf("% .2f|% .2f|%f|X V cmd(ydire)\n", XL[1]*100, Vc[1]*100, clk.read()); + //printf ("Error : [% .1f(cm) % .1f(cm) % .1f(deg)]\n", (err[0])*100, (err[1])*100, (err[2])*180/pi); + /* + printf ("\nWheel[1] counts: %d | revolutions: % .2f", qei1_new, (float)qei1_new/(4096*6)); + printf ("\nWheel[2] counts: %d | revolutions: % .2f", qei2_new, (float)qei2_new/(4096*6)); + printf ("\nWheel[3] counts: %d | revolutions: % .2f", qei3_new, (float)qei3_new/(4096*6)); + */ + //printf("Wheel Vel. [%3.2f %3.2f %3.2f]\n",pwm_w1,pwm_w2,pwm_w3); + //printf("OMEGA: [%.2f %.2f %.2f]\n",omg1,omg2,omg3); + //printf("PWM: [%.2f(%%) %.2f(%%) %.2f(%%)]\n",pwm_1.read()*100,pwm_2.read()*100,pwm_3.read()*100); + //printf("%f\n",clk.read()); + + //} + + // arrive? + wait_ms(50);// + } +} + +/* + switch (sw) { + case '1': + tempchar = sw; + xdir=-1; + ydir=-1; + sw = '2'; + break; + case '2': + tempchar = sw; + xdir=0; + ydir=-1; + sw = '3'; + break; + case '3': + tempchar = sw; + xdir=1; + ydir=-1; + sw = '6'; + break; + case '4': + tempchar = sw; + xdir=-1; + ydir=0; + sw = '1'; + break; + case '5': + tempchar = sw; + + xdir=0; + ydir=0; + XL[2]=0+pi/3; + break; + case '6': + tempchar = sw; + xdir=1; + ydir=0; + sw = '9'; + break; + case '7': + tempchar = sw; + xdir=-1; + ydir=1; + sw = '4'; + break; + case '8': + tempchar = sw; + xdir=0; + ydir=1; + sw = '7'; + break; + case '9': + tempchar = sw; + xdir=1; + ydir=1; + sw = '8'; + break; + default: + xdir=0; + ydir=0; + XL[2]=0+pi/3; + break; + }*/ + +// P&V command compensation +/*if(s0==false) { + if(clk.read()<1) { + Vc[0]=0.15; + Vc[1]=0.05+0.1*clk.read(); + Vc[2]=0; + // + XL[0]=0.15*clk.read();// go to target + XL[1]=0.05*clk.read()+0.05*clk.read()*clk.read(); + XL[2]=0+pi/3; + } else if(clk.read()>1 && clk.read()<2) { + Vc[0]=0.15; + Vc[1]=0.15; + Vc[2]=0; + // + XL[0]=0.15*clk.read();// go to target + XL[1]=0.1+0.15*(clk.read()-1); + XL[2]=0+pi/3; + } else if(clk.read()>2 && clk.read()<3) { + Vc[0]=0.15-0.1*(clk.read()-2); + Vc[1]=0.15; + Vc[2]=0; + // + XL[0]=0.3+(0.3-0.1*(clk.read()-2))*(clk.read()-2)/2;// go to target + XL[1]=0.25+0.15*(clk.read()-2); + XL[2]=0+pi/3; + } else { + Vc[0]=0; + Vc[1]=0; + Vc[2]=0; + // + XL[0]=0.4;// go to target + XL[1]=0.4; + XL[2]=0+pi/3; + s0=true; + clk.reset(); + } +}*/ \ No newline at end of file