2d drive position tracking

Dependencies:   MotorV2 QEI mbed

main.cpp

Committer:
simplyellow
Date:
2016-11-14
Revision:
0:d4bb648b7f2c

File content as of revision 0:d4bb648b7f2c:

#include "QEI.h"
#include "mbed.h"
#include "Motor.h"

/*
    Written by Milo Pan with the help of Jacob Callahan
*/

/*
Use X4 encoding.
QEI wheel(p29, p30, NC, 624, QEI::X4_ENCODING);
QEI constructor(CHANNEL A, CHANNEL B,PinName index (NC), int pulsesPerRev, Encoding encoding=X2_ENCODING) 
Use X2 encoding by default.
Encoding x4 = x4_ENCODING;
*/

/*
Measurement Instructions
in order to convert the numerical value (outputted by this program) to Inches traveled,
measurements need to be taken (i.e. have the truck travel 40" for 10 trials, average the values, and find the factor
*/

Serial pc(USBTX, USBRX);

QEI wheel (p29, p30, NC, 128, QEI::X4_ENCODING);    //orange, yellow wires, VU 5 VOLTS, BOTTOM 2x2 pins on WW02
float pulseCount;                                   //number of pulses detected by encoder
float encoding = 2;                                 //X2
float circumference = 13.25;                        //inches of circumference
float distance;

AnalogIn pot(p15);
float value;
float angle;
float zero;

float PI = 3.14159;

/* VERSION 1
float x = 0;
float dx;
float y = 0;
float dy;
float dispAngle;        // theta d
float r;                // r
float c;                // c, chord length

float segment;          // intermediary variable for ease of calculation

float heading;          // heading of front
*/


// VERSION 2
float df;
float db;
float circumference2;
float proportion;
float scaledDown;
float W;
float R;
int dir; //1 CCW, 2 CW, 0 straight
float heading = 0.0;
float dispAngleRad;
float dispAngleDeg;
float x;
float dx;
float y;
float dy;

float totalDistance;
int i;



void measure() {
    // raw measurements of pot, encoder
    //(pulse count / X * N) * (1 / PPI)
    pulseCount = (float) wheel.getPulses();
    /* conversion to relevant values: distance of arc traveled, angle of turn
        |   suppose the truck is a two-segment body
        /  <- angle between bottom leg and the vertical = angle of turn
    the 20 and 68 were arbitrary and determined from testing, respectively
    the distance is in inches
    */
    distance = pulseCount*circumference/encoding/20/68; 
    // with half inch correction after testing extensively
    /*if (distance > 0) {                                 
        distance-=0.5;
    } 
    */
}

/* VERSION 1
void calculateDisplacement() {
    /
        Premise:
        Suppose the arc s (distance), the distance traveled by the 
        turning truck, is defined by two connected points on 
        a circle with radius r.
    /
    
    // convert angle to radians
    angle = angle*PI/180;
    // r = s/angle, for distance of arc s         
    r = distance/(angle);
    // c = 2*r*sin(angle/2) for chord c
    c = 2*r*sin(angle/2);
    // intermediate value
    segment = (r*(1-cos(angle)));
    // calculation of angle of displacement
    dispAngle = acos(segment/c);
    // calculation of displacement
    dx = c*cos(dispAngle+heading);
    dy = c*sin(dispAngle+heading);
    x = x - r + dx;
    y = y + dy;
    wait(1.0);                                           
}
*/

void calculateDisplacement() {
    df = 4.5; // distance from pivot to front wheel
    db = 4.25; // distance from pivot to back wheel
    // W = 2*R*sin(0.5*angle);
    // W = shortest distance between wheels
    angle = angle*PI/180;
    W = sqrt(df*df+db*db-2*df*db*cos(PI-angle));
    R = W/(2*sin(0.5*angle));
    
    circumference2 = 2*PI*R; // inches
    proportion = distance/circumference2;
    scaledDown = proportion - floor(proportion);
    dispAngleRad = scaledDown*2*PI;
    dispAngleDeg = scaledDown*360;
    dx = R*cos(dispAngleRad + heading);
    dy = R*sin(dispAngleRad + heading);

    if(dir == 1) {               // CCW
        x = 0 - R + dx;
        y = dy;
    } else if (dir == 2) {                // CW
        y = dy;
        if((dispAngleDeg < 90) || (dispAngleDeg > 270)) {
        x = dx;
        } else {
            x = R - dx;
        }
    } else {
        x = 0;
        y = distance;
    }
    heading += dispAngleRad;
    wait(1.0);
}
/*
dir
and straight accuracy
*/

int main() {
    // required to set truck straight before start up to calibrate to zero
    zero = (float) pot;
    while(i<5) {
        printf("%d set angle \n\r",i);
        wait(1);
        i++;
    }
    if (totalDistance == 0) { // pot turns constant after the distance turns non zero
        value = (float) pot;
        // appropriate conversion from potentiometer float value to angle
        angle = (value-zero)*300;
        printf("%f",angle);
    }
    distance = 0;
    totalDistance = 0;
    heading = 0;
    while(1){
        measure(); 

        calculateDisplacement();
        
        totalDistance+=distance;
        if(totalDistance>0) {//@@@@@@@@@@check dir with angle vals@@@@@@@
            if (angle > 0.5) {
                dir = 1;//ccw
            } else if (angle < -0.5) {
                dir = 2;//cw
            } else {
                dir = 0;
            }
        }
        distance = 0;
        
        /*
            Notes:
            At startup:
            distance = 0
            angle =! 0
        */
        
        // for debugging
        pc.printf("Distance %f, Angle %f\n\r", totalDistance, angle*180/PI);     
        pc.printf("(X,Y): %f %f\n\r", x, y); 
        pc.printf("(DX,DY): %f %f\n\r", dx, dy);    
        pc.printf("heading: %f\n\r", heading);
        pc.printf("----------------------------\n\r");   
    }
}