Moved to Team 9.

Fork of LineScan by Nicholas Gan

Revision:
24:774104c34063
Parent:
20:e9f0d1483ba1
Child:
25:8357ee048ad3
diff -r e9f0d1483ba1 -r 774104c34063 LineScan.cpp
--- a/LineScan.cpp	Sat Apr 25 02:42:06 2015 +0000
+++ b/LineScan.cpp	Mon Apr 27 23:10:45 2015 +0000
@@ -10,20 +10,22 @@
 #define FIND_PEAK 1
 #define FIND_TROUGH 2
 
-uint16_t read1Bit(AnalogIn cam, DigitalOut *camClk){
+uint16_t read1Bit(AnalogIn cam, DigitalOut *camClk)
+{
     uint16_t pixel;
-    
+
     //read pixel n
     pixel = cam.read_u16();
-    
+
     //clock pulse for next pixel n + 1
     *camClk = 1;
     *camClk = 0;
-    
+
     return pixel;  //return result as an uint16_t (16 bit integer)
 }
 
-void startRead(DigitalOut *camSi, DigitalOut *camClk){
+void startRead(DigitalOut *camSi, DigitalOut *camClk)
+{
     //pulse first clock cycle and start integral pin
     *camSi = 1;
     *camClk = 1;
@@ -31,7 +33,8 @@
     *camClk = 0;
 }
 
-float processFn(uint16_t *array, int arraySz, int* exposure){//, telemetry::NumericArray<uint16_t, NUM_PIX> &tele_linescan_diff){
+float processFn(uint16_t *array, int arraySz, int* exposure, telemetry::NumericArray<uint16_t, NUM_PIX> &tele_linescan_diff)
+{
     const static int frameLen = NUM_PIX -  2 * SKIP;
     int avg[frameLen];
     int diff[frameLen];
@@ -47,70 +50,96 @@
     int out_width = frameLen;
     int i;
     float out = -1.0;
-    
+    int thinnest = 128;
+    int linestart = -1;
+    int linestop = -1;
+    int tempstart = 0;
+
     //for AGC
     float exposureChange;
-    
+
     h_idx_ary[0] = -1;
     l_idx_ary[0] = -1;
-    
-    if(array){    
+
+    if(array) {
         avg[0] = array[SKIP - 1]/2 + array[SKIP]/2;
         diff[0] = 0;
-        //tele_linescan_diff[0] = diff[0];
-        
+        tele_linescan_diff[0] = diff[0];
+
         total += avg[0];    //AGC
-        
-        for(i = 1; i < frameLen; i++){
+
+        for(i = 1; i < frameLen; i++) {
             avg[i] = array[i - 1 + SKIP]/2 + array[i + SKIP]/2;   //smoothing
-            diff[i] = avg[i - 1] - avg[i];          //differential
-            //tele_linescan_diff[i] = diff[i];
-            
+            if ((avg[i] - avg[i-1] >= THRESH) || (avg[i] - avg[i-1] <= -THRESH)) {
+                diff[i] = avg[i] - avg[i-1];          //differential
+            } else {
+                diff[i] = 0;
+            }
+            if (diff [i] > 0) {
+                tele_linescan_diff[i] = 10000;
+            } else if (diff[i] < 0) {
+                tele_linescan_diff[i] = 5000;
+            } else {
+                tele_linescan_diff[i] = 0;
+            }
+
             total += avg[i];    //AGC
-            
-            
+
+
             //Finite State Machine
             //problem in this section, rewrite? find peaks and troughs
-            switch(state){
+            switch(state) {
                 case NEUTRAL:
                     //serial.printf("Neutral case in processFn\r\n");
-                    if( diff[i] > THRESH ){
+                    if( diff[i] > THRESH ) {
                         state = FIND_PEAK;
                         highest = diff[i];
                         h_idx_ary[h_idx_pos] = i;
-                    }else if( diff[i] < -THRESH ){
+                        tempstart = i;
+                    } /*else if( diff[i] < -THRESH ) {
                         state = FIND_TROUGH;
                         lowest = diff[i];
                         l_idx_ary[l_idx_pos] = i;
-                    }
+                        tempstart = i;
+                    }*/
                     break;
-                    
+
                 case FIND_PEAK:
                     //serial.printf("Peak case in processFn\r\n");
-                    if( diff[i] <= THRESH ){
+                    if( diff[i] <= -THRESH ) {
                         state = NEUTRAL;
                         h_idx_pos++;
                         h_idx_ary[h_idx_pos] = -1;  //last element is always -1
-                    }
-                    else if(diff[i] > highest){
+                        if ((i - tempstart > 4) && (i - tempstart < thinnest)) {
+                            thinnest = i - tempstart;
+                            linestart = tempstart;
+                            linestop = i;
+                        }
+                    } else if(diff[i] > highest) {
                         highest = diff[i];
                         h_idx_ary[h_idx_pos] = i;  //insert to array, clobbers
+                        tempstart = i;
                     }
                     break;
-                    
+
                 case FIND_TROUGH:
                     //serial.printf("Trough case in processFn\r\n");
-                    if( diff[i] >= -THRESH ){
+                    if( diff[i] >= THRESH ) {
                         state = NEUTRAL;
                         l_idx_pos++;
                         l_idx_ary[l_idx_pos] = -1;  //last element is always -1
-                    }
-                    else if(diff[i] < lowest){
+                        if ((i - tempstart > 4) && (i - tempstart < thinnest)) {
+                            thinnest = i - tempstart;
+                            linestart = tempstart;
+                            linestop = i;
+                        }
+                    } else if(diff[i] < lowest) {
                         lowest = diff[i];
                         l_idx_ary[l_idx_pos] = i;  //insert to array, clobbers
+                        tempstart = i;
                     }
                     break;
-                    
+
                 default:
                     //exit case if exception happened
                     serial.printf("Default case in processFn\r\n");
@@ -119,65 +148,221 @@
         }
         //AGC, simple proportional controller
         total = total / frameLen;
-        exposureChange = ((float)(MEAN_REF - total)) * CAM_CTRL_GAIN;    
+        exposureChange = ((float)(MEAN_REF - total)) * CAM_CTRL_GAIN;
         *exposure += (int)exposureChange;
         if(*exposure < 0)
             *exposure = 0;
         else if(*exposure > UPDATE_RATE)
             *exposure = UPDATE_RATE;
     }
-    
+
     l_walker = l_idx_ary;
     h_walker = h_idx_ary;
-    
-    while(*l_walker != -1 && *h_walker != -1){
+
+    /*while(*l_walker != -1 && *h_walker != -1){
         //evaluate out and advance if line is white on black and returns center of smallest white band
         //if interval is black on white, advance the pointer for the peak array
         //width needs to be larger than 4 pixels wide to be a good read.
-        
+
         if(*h_walker > *l_walker && (*h_walker - *l_walker) < out_width && (*h_walker - *l_walker) > 3){
             out_width = *h_walker - *l_walker;
             out = ((float)(*h_walker + *l_walker)) / (2.0 * (float)frameLen);    //0.5 is center
             l_walker++;
         }
         h_walker++;
-        
+
         //serial.printf("%d %d\r\n", *h_walker, *l_walker);
         //serial.printf("%.2f\r\n", out);
+    }*/
+
+    if (linestart != -1) {
+        out = ((float)(linestart + linestop)) / (2.0 * (float)frameLen);
+    } else {
+        out = -1;
     }
-    
+    return out;
+}
+
+float processFn2(uint16_t *array, int arraySz, int* exposure)
+{
+    const static int frameLen = NUM_PIX -  2 * SKIP;
+    int avg[frameLen];
+    int diff[frameLen];
+    int highest = 0;
+    int lowest = 0;
+    int total = 0;
+    int h_idx_ary[10];
+    int h_idx_pos = 0;
+    int l_idx_ary[10];
+    int l_idx_pos = 0;
+    int state = NEUTRAL;
+    int *l_walker, *h_walker;
+    int out_width = frameLen;
+    int i;
+    float out = -1.0;
+    int thinnest = 128;
+    int linestart = -1;
+    int linestop = -1;
+    int tempstart = 0;
+
+    //for AGC
+    float exposureChange;
+
+    h_idx_ary[0] = -1;
+    l_idx_ary[0] = -1;
+
+    if(array) {
+        avg[0] = array[SKIP - 1]/2 + array[SKIP]/2;
+        diff[0] = 0;
+        //tele_linescan_diff[0] = diff[0];
+
+        total += avg[0];    //AGC
+
+        for(i = 1; i < frameLen; i++) {
+            avg[i] = array[i - 1 + SKIP]/2 + array[i + SKIP]/2;   //smoothing
+            diff[i] = avg[i] - avg[i-1];          //differential
+            //tele_linescan_diff[i] = diff[i];
+
+            total += avg[i];    //AGC
+
+
+            //Finite State Machine
+            //problem in this section, rewrite? find peaks and troughs
+            switch(state) {
+                case NEUTRAL:
+                    //serial.printf("Neutral case in processFn\r\n");
+                    if( diff[i] > THRESH ) {
+                        state = FIND_PEAK;
+                        highest = diff[i];
+                        h_idx_ary[h_idx_pos] = i;
+                        tempstart = i;
+                    } else if( diff[i] < -THRESH ) {
+                        state = FIND_TROUGH;
+                        lowest = diff[i];
+                        l_idx_ary[l_idx_pos] = i;
+                        tempstart = i;
+                    }
+                    break;
+
+                case FIND_PEAK:
+                    //serial.printf("Peak case in processFn\r\n");
+                    if( diff[i] <= THRESH ) {
+                        state = NEUTRAL;
+                        h_idx_pos++;
+                        h_idx_ary[h_idx_pos] = -1;  //last element is always -1
+                        if ((i - tempstart > 4) && (i - tempstart < thinnest)) {
+                            thinnest = i - tempstart;
+                            linestart = tempstart;
+                            linestop = i;
+                        }
+                    } else if(diff[i] > highest) {
+                        highest = diff[i];
+                        h_idx_ary[h_idx_pos] = i;  //insert to array, clobbers
+                        tempstart = i;
+                    }
+                    break;
+
+                case FIND_TROUGH:
+                    //serial.printf("Trough case in processFn\r\n");
+                    if( diff[i] >= -THRESH ) {
+                        state = NEUTRAL;
+                        l_idx_pos++;
+                        l_idx_ary[l_idx_pos] = -1;  //last element is always -1
+                        if ((i - tempstart > 4) && (i - tempstart < thinnest)) {
+                            thinnest = i - tempstart;
+                            linestart = tempstart;
+                            linestop = i;
+                        }
+                    } else if(diff[i] < lowest) {
+                        lowest = diff[i];
+                        l_idx_ary[l_idx_pos] = i;  //insert to array, clobbers
+                        tempstart = i;
+                    }
+                    break;
+
+                default:
+                    //exit case if exception happened
+                    serial.printf("Default case in processFn\r\n");
+                    return out;
+            }
+        }
+        //AGC, simple proportional controller
+        total = total / frameLen;
+        exposureChange = ((float)(MEAN_REF - total)) * CAM_CTRL_GAIN;
+        *exposure += (int)exposureChange;
+        if(*exposure < 0)
+            *exposure = 0;
+        else if(*exposure > UPDATE_RATE)
+            *exposure = UPDATE_RATE;
+    }
+
+    l_walker = l_idx_ary;
+    h_walker = h_idx_ary;
+
+    /*while(*l_walker != -1 && *h_walker != -1){
+        //evaluate out and advance if line is white on black and returns center of smallest white band
+        //if interval is black on white, advance the pointer for the peak array
+        //width needs to be larger than 4 pixels wide to be a good read.
+
+        if(*h_walker > *l_walker && (*h_walker - *l_walker) < out_width && (*h_walker - *l_walker) > 3){
+            out_width = *h_walker - *l_walker;
+            out = ((float)(*h_walker + *l_walker)) / (2.0 * (float)frameLen);    //0.5 is center
+            l_walker++;
+        }
+        h_walker++;
+
+        //serial.printf("%d %d\r\n", *h_walker, *l_walker);
+        //serial.printf("%.2f\r\n", out);
+    }*/
+
+    if (linestart != -1) {
+        out = ((float)(linestart + linestop)) / (2.0 * (float)frameLen);
+    } else {
+        out = -1;
+    }
     return out;
 }
 
 //call after integration time is done, returns index of array line is expected to be at and new exposure time
-float getLinePos(AnalogIn cam, 
-                 DigitalOut *camSi, 
-                 DigitalOut *camClk, 
-                 int *exposure, 
-                 telemetry::NumericArray<uint16_t, NUM_PIX> &tele_linescan){//,
-                 //telemetry::NumericArray<uint16_t, NUM_PIX> &tele_linescan_diff){
+float getLinePos(AnalogIn cam,
+                 DigitalOut *camSi,
+                 DigitalOut *camClk,
+                 int *exposure,
+                 telemetry::NumericArray<uint16_t, NUM_PIX> &tele_linescan,
+                 telemetry::NumericArray<uint16_t, NUM_PIX> &tele_linescan_diff)
+{
     uint16_t lineAry[NUM_PIX];
     float position;
-    
-    //read 
+
+    //read
     startRead(camSi, camClk);
-    for(int i = 0; i < NUM_PIX; i++){
+    for(int i = 0; i < NUM_PIX; i++) {
         lineAry[i] = read1Bit(cam, camClk);
         tele_linescan[i] = lineAry[i];
     }
-    
+
     //process line scan data
-    position  = processFn(lineAry, NUM_PIX, exposure);//, tele_linescan_diff);
-    //serial.printf("%.2f\r\n", position);
-    
+    position  = processFn(lineAry, NUM_PIX, exposure, tele_linescan_diff);
+
     return position;
 }
 
-/*
-sample call (handler thread):
+float getLinePos2(AnalogIn cam,
+                  DigitalOut *camSi,
+                  DigitalOut *camClk,
+                  int *exposure)
+{
+    uint16_t lineAry[NUM_PIX];
+    float position;
 
-while(1){
-   linePos  = getLinePos(cameraIn1, si, clk, &exposureTime);   //volatile linePos, replace with steering angle and read 2 cameras?
-   Thread::wait(exposureTime);    //sleep for 14 us
+    //read
+    startRead(camSi, camClk);
+    for(int i = 0; i < NUM_PIX; i++) {
+        lineAry[i] = read1Bit(cam, camClk);
+    }
+
+    //process line scan data
+    position  = processFn2(lineAry, NUM_PIX, exposure);//, tele_linescan_diff);
+
+    return position;
 }
-*/