Dies ist die von Julian Mueller überarbeitete Bahnkantenregelung.

Dependencies:   TextLCD mbed

edge_func.cpp

Committer:
Jules20
Date:
2016-05-31
Revision:
0:b72d86a7b005

File content as of revision 0:b72d86a7b005:

/**
*Funktionen zum Auslesen der Linienkamera und zur Detektion der Kante
*
*CPP-Datei edge_func.cpp
*
*@version: 01.11.2015
*@author: Gustav Grether
*/

#include "edge_func.h"

//Definiton zur Anzeige von Fehlern
DigitalOut errorLED(LED1); //zeigt an, dass Fehler auftritt

// Definition der Pins des Sensors
DigitalOut clk(p18); //Clock Pin
DigitalOut si(p19); //SI Pin
//analoger Eingang Wertebereich [0..1] mit ao.read()
// misst die Spannung die am Sensorausgang anliegt
AnalogIn ao(p20); 

//Variablen fuer alle Funktionen der Datei
const int numPx =128; // Anzahl der Pixel
const int leftbound = 8; // linker Randbereich des Sensors, nicht betrachtet
const int rightbound = numPx - leftbound; //rechter Randbereich des Sensors, nicht betrachtet
queue<int> possEdgePx; //enthaelt die Pixel die als Kante in Frage kommen
int tmpPossEdgePx; //temporaeres moegliches Kantenpixel
int numPossEdgePx; //Anzahl der moeglichen Kantenpixel

//Variablen fuer read()
float currentVal[numPx]; //Werte der Pixel einer Messung
const int numMeas =3; //Werte werden ueber numMeas Messungen gemittelt
float meanVal[numPx]; //Mittelwerte jedes Pixels ueber die (NumMeas) Messungen
float currentPx;
int delay=2; //Verzoegerung zum Einstellen der Belichtungszeit in [10⁻³ s]
//Variablen zur Detektion einer Fehlfunktion des Sensors
const float epsilon=0.01; //minimal zulaessiger Wert eines Pixels
int cntZero; //Anzahl ungueltiger Pixel(<epsilion)
const int zeroMax=5; //maximale Anzahl ungueltiger Pixel pro Messung
bool validMeas; //zeigt ob eine Messungen gueltig ist

//Variablen fuer gaussian_calc()
float gaussian[numPx]; //gauss gefilterte Grauwerte

//Variablen fuer gradient_calc()
float gradient[numPx]; //Gradienten der Pixel

//Variablen fuer nonMaxSupr()
//Gradienten liegt in [-1.0,1.0]
// relevant ist nur [-1.0,0.0]
// Anzahl der Quanten in Intervall=numQuant+1 
const int numQuant=15;
float quantStepSize=1.0/numQuant; // Schrittweite eines Quants
float quantStep[numQuant]; //Quantenstufen
float quant[numPx]; //quantisierte Werte des Gradienten

//Variablen fuer plausible()
float meanLeft; //Mittelwert der Pixel links eines moeglichen Kantenpixels
float meanRight; //Mittelwert der Pixel rechts eines moeglichen Kantenpixels
const float threshBlack=0.4; //Grenzwert definiert Beschichtung
const float threshFoil=0.7; //Grenzwert definiert Metallfolie

//Variablen fuer edge_calc()
float gradmin; //minimaler Gradient
int edgePx; //gefundenes Kantenpixel Wertebereich [leftbound..rightbound]

void clockPulse()
{
    clk=1;
    clk=0;
}

void siClkPulse()
{
    si=1;
    clockPulse();
    si=0;
}

void sens_setup()
{
    errorLED=0;
    edgePx=-1;
    clk=0;
    si=0;

    //linker und rechter Randbereich werden nicht betrachtet
    for (int i = 0; i < leftbound - 1; i++) {
        gaussian[i]= 0.0;
        gradient[i]= 0.0;
        quant[i]= 0.0;
    }
    for (int i = rightbound + 1; i < numPx; i++) {
        gaussian[i]= 0.0;
        gradient[i]= 0.0;
        quant[i]= 0.0;
    }

    //QuantenStufen zur Quantisierung des Gradienten
    for(int k=0; k<numQuant; k++) {
        quantStep[k]=-(k+1)*quantStepSize;
    }
}

void read()
{
    
    edgePx=-10; //Fehler in Algorithmus wenn Wert -10 bleibt
    for(int j=0; j<numMeas; j++) {
        validMeas=1; // setze Messung gueltig
        cntZero=0;  // setze Anzahl ungueltiger Pixel=0
        
        siClkPulse(); //stoppt Belichtung der Pixel und startet sie erneut
        for(int k = 0; k < 130; k++) {
            //neue Belichtung der Pixel beginnt bei k=18
            //jeder clock-Puls eliminiert den alten Wert eines Pixels
            clockPulse();
        }

        wait_ms(delay); // Verzoegerung um die Belichtungszeit zu vergroessern
        siClkPulse(); //stoppt Belichtung der Pixel und startet sie erneut

        //Auslesen und Speichern der Werte der Pixel
        //jeder Clock Puls legt an ao den Wert(Spannung) des naechsten Pixels an
        for(int i=0; i < numPx; i++) {
            wait_us(5);//Verzoegerung um den analogen Ausgang des Sensors zu stabilisieren
            currentPx= ao.read(); //einlesen des Wertes
            if(currentPx < epsilon) {
                cntZero++; //zaehlen der ungueltigen Pixel
            }
            currentVal[i]=currentPx;
            clockPulse();

            //ueberpruefen ob Messung noch gueltig ist
            if (cntZero > zeroMax) {
                errorLED=!errorLED;
                edgePx= -1; //Fehler Nummer 1
                validMeas=0; // setze Messung fehlerhaft
                break; //stoppt Auslesen des Sensors, startet neue Belichtung
            }
        }

        //Mittelung der Werte mit vorherigen Messungen wenn neue Messung gueltig
        if(validMeas) {
            if(j>0) {
                for(int i=0; i<numPx; i++) {
                    meanVal[i]=(meanVal[i]+currentVal[i])/2;
                }
            } else { //j==0
                for(int i=0; i<numPx; i++) {
                    meanVal[i]=currentVal[i];
                }
            }
        }
    }
}

void gaussian_calc()
{
    //Gauß Filter sigma=2, k=5, G(x,sigma)=1/113*[1,3,7,14,20,23,20,14,7,3,1]
    for (int i = leftbound - 1; i < rightbound + 1; i++) {
        gaussian[i] = (meanVal[i-5]+meanVal[i-4]*3
                       +meanVal[i-3]*7+meanVal[i-2]*14
                       + meanVal[i-1]*20+meanVal[i]*23
                       + meanVal[i+1]*20+meanVal[i+2]*14
                       + meanVal[i+3]*7+meanVal[i+4]*3+
                       meanVal[i+5])/113;
    }

}

void gradient_calc()
{
    for (int i = leftbound; i < rightbound; i++) {
        gradient[i] = (meanVal[i-1]- meanVal[i+1]) / 2;
    }

}


void nonMaxSupr()
{
    //Quantisierung des Gradienten
    for(int i=leftbound; i<rightbound; i++) {
        if(gradient[i]> quantStep[0]) {
            quant[i]=0.0;//keine Kante
        } else {
            for(int k=1; k<numQuant; k++) {
                if(gradient[i]> quantStep[k]) {
                    quant[i]=quantStep[k-1];
                    possEdgePx.push(i); //moegliche Kante
                    break;
                }
            }
        }
    }

    //Non-Maxima-Supression

    numPossEdgePx=possEdgePx.size();

    for (int i=0; i<numPossEdgePx; i++) {
        tmpPossEdgePx=possEdgePx.front();
        possEdgePx.pop();
        //Bedingung fuer Kante if(quant[tmpPossEdgePx]<=quant[tmpPossEdgePx-1] && quant[tmpPossEdgePx]<=quant[tmpPossEdgePx+1] )
        //negiert damit Gleichheit zwischen Float nicht ueberprüft werden muss
        if(!(quant[tmpPossEdgePx]>quant[tmpPossEdgePx-1] || quant[tmpPossEdgePx]>quant[tmpPossEdgePx+1]))  {
            possEdgePx.push(tmpPossEdgePx); //moegliche Kante
        }
    }
}

void plausible()
{
//Plausibilitaetspruefung
    if(possEdgePx.empty()) {
        errorLED=!errorLED;
        edgePx=-2; // Fehler Nummer 2
    }

    //Plausibilitaetspruefung: ueberpruefe die Umgebung jedes moeglichen Kantenpixels
    // die Pixel links davon muessen im Mittelwert < threshblack
    // die Pixel rechts davon >threshfoil
    numPossEdgePx=possEdgePx.size();

    for (int j=0; j<numPossEdgePx; j++) {
        tmpPossEdgePx=possEdgePx.front();
        possEdgePx.pop();
        meanLeft=0.0;
        meanRight=0.0;
        for(int i=1; i<6; i++) {
            meanLeft+=meanVal[tmpPossEdgePx-i];
            meanRight+=meanVal[tmpPossEdgePx+i];
        }
        meanLeft=meanLeft/5;
        meanRight=meanRight/5;

        if(meanLeft < threshBlack && meanRight> threshFoil) {
            possEdgePx.push(tmpPossEdgePx);
        }
    }

}

void edgePx_calc()
{
    if(possEdgePx.empty()) {
        errorLED=!errorLED;
        edgePx=-3; //Fehler Nummer 3
    } else if (possEdgePx.size()==1) {
        //nur ein moegliches Kantenpixel uebrig
        edgePx=possEdgePx.front();
        possEdgePx.pop();
    } else {
        //mehrere moegliche Kantenpixel;
        //bei richtig eingestelltem Sensor sollten hier durch die Plausibilitaetspruefung
        //nur noch Nachbarpixel mit gleich großem quantisiertem Gradient uebrig sein
        //waehle Pixel mit minimalem Gradient(float)
        gradmin = 0.0;
        numPossEdgePx = possEdgePx.size();
        for (int i = 0; i < numPossEdgePx; i++) {
            tmpPossEdgePx=possEdgePx.front();
            possEdgePx.pop();
            if ( gradient[tmpPossEdgePx]< gradmin) {
                gradmin=gradient[tmpPossEdgePx];
                edgePx=tmpPossEdgePx;//gefundenes Kantenpixel, Algorithmus erfolgreich
                errorLED=0;
            }
        }
    }
}

int edgePx_get()
{
    read();
    gaussian_calc();
    gradient_calc();
    nonMaxSupr();
    plausible();
    edgePx_calc();
    return edgePx;
}