20160725

Dependencies:   QEI mbed

Revision:
0:926cd923a480
Child:
1:a78e5f6154d3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Jul 22 07:57:56 2016 +0000
@@ -0,0 +1,285 @@
+/* 版本說明: 可1~9任選,但scanf有問題
+實驗說明:
+    利用運動學模型並以靜止的virtual leader當作輸入命令,達到point to point控制,來驗證里程計的正確性。
+    =八個方位的測試=
+          7  8  9
+           ↖ ↑ ↗
+          4← . →6
+           ↙ ↓ ↘
+          1  2  3
+07/07測試結果:
+    實驗成功但略有誤差
+*/
+#include "mbed.h"
+#include "math.h"
+#include "QEI.h"
+// definition
+#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 c0 0.06// control  gain
+
+// initial pose
+#define x0 0  //[m]
+#define y0 0  //[m]
+#define theta0 0//[deg.]
+// desied pose
+#define xd 0.5   //[cm]
+#define yd 0.5   //[cm]
+#define thetad 0//[deg.]
+// error threshold
+#define ex 0.5   //[cm]
+#define ey 0.5   //[cm]
+#define etheta 1//[deg.]
+
+PwmOut pwm_1(D9);
+PwmOut pwm_2(D10);
+PwmOut pwm_3(D11);
+
+Timer t;   // timer for printing
+
+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);
+// odomerty para.
+float c1 = r/(3*L);
+float c2 = 2*r/3;
+float Current_X[3] = {x0,y0,(theta0*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;
+int qei1_old, qei2_old, qei3_old;
+// control law para.
+float f1[3] = {0}; // formation vector
+float X1[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;
+// Others
+DigitalIn mybutton(USER_BUTTON);
+DigitalOut myled(LED1);
+int c = 3;
+float err[3]= {0};
+bool s0 = false;
+char dire;
+
+
+int main()
+{
+
+    t.start();
+
+    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("===================Reset===================\n");
+aa: {
+
+        printf("Which direction to go?\n");
+        printf("     7  8  9   \n");
+        printf("        |      \n");
+        printf("     4- 5 -6    \n");
+        printf("        |      \n");
+        printf("     1  2  3   \n");
+        myled = 1;
+    }
+
+    scanf("%c", &dire);
+    switch (dire) {
+        case '1':
+            XL[0]=-0.4;
+            XL[1]=-0.4;
+            XL[2]=0+pi/3;
+            break;
+        case '2':
+            XL[0]=0;
+            XL[1]=-0.4;
+            XL[2]=0+pi/3;
+            break;
+        case '3':
+            XL[0]=0.4;
+            XL[1]=-0.4;
+            XL[2]=0+pi/3;
+            break;
+        case '4':
+            XL[0]=-0.4;
+            XL[1]=0;
+            XL[2]=0+pi/3;
+            break;
+        case '5':
+            XL[0]=0;
+            XL[1]=0;
+            XL[2]=0+pi/3;
+            break;
+        case '6':
+            XL[0]=0.4;
+            XL[1]=0;
+            XL[2]=0+pi/3;
+            break;
+        case '7':
+            XL[0]=-0.4;
+            XL[1]=0.4;
+            XL[2]=0+pi/3;
+            break;
+        case '8':
+            XL[0]=0;
+            XL[1]=0.4;
+            XL[2]=0+pi/3;
+            break;
+        case '9':
+            XL[0]=0.4;
+            XL[1]=0.4;
+            XL[2]=0+pi/3;
+            break;
+    }
+
+    printf("PWM Reset: [%.2f(%%) %.2f(%%) %.2f(%%)]\n",pwm_1.read()*100,pwm_2.read()*100,pwm_3.read()*100);
+    printf("Initial Pose : [% .1f(cm) % .1f(cm) % .1f(deg)]\n", Current_X[0]*100, Current_X[1]*100 ,Current_X[2]*180/pi-60);
+    printf("Desired Pose : [% .1f(cm) % .1f(cm) % .1f(deg)]\n", XL[0]*100, XL[1]*100 ,XL[2]*180/pi-60);
+    //printf("Press USER_BUTTON to START (Go to Direction '%c')\n", dire);
+    printf("Go to Direction '%c')\n", dire);
+    //while (mybutton == 1) {}
+
+    while(c>0) {
+        wait(1);
+        printf("%d\n",c--);
+        myled = !myled;
+    }
+
+    while(1) {
+        //
+        myled = 0;
+        X1[0] = Current_X[0];
+        X1[1] = Current_X[1];
+        X1[2] = Current_X[2];
+
+        // 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));
+
+        // 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 //
+
+        // 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] = -c0*(X1_b[0]-XL[0]);
+        u[1] = -c0*(X1_b[1]-XL[1]);
+        u[2] = -c0*(X1_b[2]-XL[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 //
+
+        //theta = theta + pi/3; // shift: origin to new
+
+        // 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]-XL[0];
+        err[1] = Current_X[1]-XL[1];
+        err[2] = Current_X[2]-XL[2];
+        // END //
+        if ( t.read_ms() > 200) { // print
+
+            t.reset();
+            t.start();
+            if (s0 == true) printf ("=================Homing====================\n");
+            else            printf ("===========================================\n");
+            printf ("Current Pose : [% .1f(cm) % .1f(cm) % .1f(deg)]\n", Current_X[0]*100, Current_X[1]*100, Current_X[2]*180/pi-60);
+            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("X: [%.3f] Y:[%.3f]\n",px,py);
+            //printf("px+py=%.2f\n", px+py);
+
+        }
+        if ( abs(err[0])<=(ex/100) && abs(err[1])<=(ey/100) && abs(err[2])<=(etheta*pi/180) ) {
+            printf("The robot Arrived!\n");
+            pwm_1.write(0.50);
+            pwm_2.write(0.50);
+            pwm_3.write(0.50);
+            //s0 = true;
+            c = 3;
+            goto aa;
+            /*
+                        printf("Press USER_BUTTON to go HOME\n");
+                        while (mybutton == 1) {
+                            wait(0.25);
+                            myled = !myled;
+
+                        }
+
+                        while(c>0) {
+                            wait(1);
+                            printf("%d\n",c--);
+                            myled = !myled;
+                        }
+                        XL[0]=0;
+                        XL[1]=0;
+                        XL[2]=0+pi/3;
+                        */
+        }
+
+        wait_ms(10);// 會有什麼影響?
+    }
+}