David's line following code from the LVBots competition, 2015.

Dependencies:   GeneralDebouncer Pacer PololuEncoder mbed

Fork of DeadReckoning by David Grayson

Files at this revision

API Documentation at this revision

Comitter:
DavidEGrayson
Date:
Wed Apr 15 21:19:22 2015 +0000
Parent:
45:e16e74bbbf8c
Child:
47:cb5c1504c24d
Commit message:
got dead reckoning working nicely with the gyro;

Changed in this revision

logger.cpp Show annotated file Show diff for this revision Revisions of this file
logger.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
reckoner.cpp Show annotated file Show diff for this revision Revisions of this file
reckoner.h Show annotated file Show diff for this revision Revisions of this file
test.cpp Show annotated file Show diff for this revision Revisions of this file
test.h Show annotated file Show diff for this revision Revisions of this file
turn_sensor.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/logger.cpp	Wed Apr 15 19:19:19 2015 +0000
+++ b/logger.cpp	Wed Apr 15 21:19:22 2015 +0000
@@ -24,8 +24,7 @@
     LogEntry * entry = &entries[entryIndex];
     entryIndex++;
     
-    //entry->cos = reckoner.cos >> 16;
-    //entry->sin = reckoner.sin >> 16;
+    entry->turnAngle = 0;
     entry->x = reckoner.x >> 16;
     entry->y = reckoner.y >> 16;
 }
@@ -36,7 +35,7 @@
     for(int32_t i = 0; i < entryIndex; i++)
     {
         LogEntry * entry = &entries[i];
-        pc.printf("%d,%d\r\n", entry->x, entry->y);
+        pc.printf("%d,%d\r\n", entry->turnAngle, entry->x, entry->y);
     }
     pc.printf("Log dump end\r\n");
 }
\ No newline at end of file
--- a/logger.h	Wed Apr 15 19:19:19 2015 +0000
+++ b/logger.h	Wed Apr 15 21:19:22 2015 +0000
@@ -6,8 +6,7 @@
 
 struct LogEntry
 {
-    //int16_t cos;
-    //int16_t sin;
+    int16_t turnAngle;
     int16_t x;
     int16_t y;   
 };
--- a/main.cpp	Wed Apr 15 19:19:19 2015 +0000
+++ b/main.cpp	Wed Apr 15 21:19:22 2015 +0000
@@ -60,7 +60,8 @@
     //testCloseness();
     //testLogger();
     //testL3g();
-    testTurnSensor();
+    //testTurnSensor();
+    //testReckoningWithGyro();
 
     // Real routines for the contest.
     loadCalibration();
@@ -138,6 +139,32 @@
     }
 }
 
+void updateReckoner(TurnSensor & turnSensor)
+{
+    if (!encoderBuffer.hasEvents())
+    {
+        return;
+    }
+    
+    reckoner.setTurnAngle(turnSensor.getAngle());
+    
+    while(encoderBuffer.hasEvents())
+    {
+        PololuEncoderEvent event = encoderBuffer.readEvent();
+        switch(event)
+        {
+        case ENCODER_LEFT | POLOLU_ENCODER_EVENT_INC:
+        case ENCODER_RIGHT | POLOLU_ENCODER_EVENT_INC:
+            reckoner.handleForward();
+            break;
+        case ENCODER_LEFT | POLOLU_ENCODER_EVENT_DEC:
+        case ENCODER_RIGHT | POLOLU_ENCODER_EVENT_DEC:
+            reckoner.handleBackward();
+            break;
+        }
+    }
+}
+
 float magnitude()
 {
     return sqrt((float)reckoner.x * reckoner.x + (float)reckoner.y * reckoner.y);   
@@ -145,8 +172,8 @@
 
 float dotProduct()
 {
-    float s = (float)reckoner.sin / (1 << 30);
-    float c = (float)reckoner.cos / (1 << 30);
+    float s = (float)reckoner.sinv / (1 << 30);
+    float c = (float)reckoner.cosv / (1 << 30);
     float magn = magnitude();
     if (magn == 0){ return 0; }    
     return ((float)reckoner.x * c + (float)reckoner.y * s) / magn;
@@ -157,8 +184,8 @@
 float determinant()
 {
     // TODO: get rid of the magic numbers here (i.e. 30)
-    float s = (float)reckoner.sin / (1 << 30);
-    float c = (float)reckoner.cos / (1 << 30);
+    float s = (float)reckoner.sinv / (1 << 30);
+    float c = (float)reckoner.cosv / (1 << 30);
     return (reckoner.x * s - reckoner.y * c) / magnitude();
 }
 
@@ -241,10 +268,13 @@
     uint32_t loopCount = 0;
     Timer timer;
     timer.start();
+    TurnSensor turnSensor;
+    turnSensor.start();
     while(1)
     {
         loopCount += 1;
-        updateReckonerFromEncoders();
+        turnSensor.update();
+        updateReckoner(turnSensor);
         loggerService();
         
         if ((loopCount % 256) == 0)
--- a/main.h	Wed Apr 15 19:19:19 2015 +0000
+++ b/main.h	Wed Apr 15 21:19:22 2015 +0000
@@ -3,6 +3,7 @@
 #include "reckoner.h"
 #include "line_tracker.h"
 #include "logger.h"
+#include "turn_sensor.h"
 
 void loadCalibration();
 
@@ -13,11 +14,13 @@
 
 void updateMotorsToFollowLine();
 void updateReckonerFromEncoders();
+void updateReckoner(TurnSensor &);
 void setLeds(bool v1, bool v2, bool v3, bool v4);
 float determinant();
 float dotProduct();
 float magnitude();
 void loggerService();
+void waitForSignalToStart();
 
 extern Reckoner reckoner;
 extern LineTracker lineTracker;
--- a/reckoner.cpp	Wed Apr 15 19:19:19 2015 +0000
+++ b/reckoner.cpp	Wed Apr 15 21:19:22 2015 +0000
@@ -1,5 +1,6 @@
 #include <mbed.h>
 #include "reckoner.h"
+#include "math.h"
 
 /**
 First, we define two int32_t variables cos and sin that make a unit vector.
@@ -7,7 +8,7 @@
 We need to choose units for them that allow for a lot of accuracy without overflowing.
 We choose the units to be 1/(1 << 30) so that they will typically be about half of the
 way between 0 and overflow.
-The starting value ofvalue of the [cos, sin] will be [1 << 30, 0].
+The starting value of the [cos, sin] will be [1 << 30, 0].
 To record this choice, we define LOG_UNIT_MAGNITUDE:
 **/
 #define LOG_UNIT_MAGNITUDE 30
@@ -109,8 +110,8 @@
 
 void Reckoner::reset()
 {
-  cos = 1 << LOG_UNIT_MAGNITUDE;
-  sin = 0;
+  cosv = 1 << LOG_UNIT_MAGNITUDE;
+  sinv = 0;
   x = 0;
   y = 0;
 }
@@ -141,14 +142,14 @@
 
 void Reckoner::handleForward()
 {
-    x += cos >> LOG_COS_TO_X_CONVERSION;
-    y += sin >> LOG_COS_TO_X_CONVERSION;
+    x += cosv >> LOG_COS_TO_X_CONVERSION;
+    y += sinv >> LOG_COS_TO_X_CONVERSION;
 }
 
 void Reckoner::handleBackward()
 {
-    x -= cos >> LOG_COS_TO_X_CONVERSION;
-    y -= sin >> LOG_COS_TO_X_CONVERSION;
+    x -= cosv >> LOG_COS_TO_X_CONVERSION;
+    y -= sinv >> LOG_COS_TO_X_CONVERSION;
 }
 
 void Reckoner::handleRight()
@@ -165,10 +166,18 @@
 
 void Reckoner::handleTurnRadians(int32_t radians)
 {
-    int32_t dc = -((int64_t)sin * radians) >> LOG_UNIT_MAGNITUDE;
-    int32_t ds = ((int64_t)cos * radians) >> LOG_UNIT_MAGNITUDE;
-    dc = -((int64_t)(sin+ds/2) * radians) >> LOG_UNIT_MAGNITUDE;
-    ds = ((int64_t)(cos+dc/2) * radians) >> LOG_UNIT_MAGNITUDE;
-    cos += dc;
-    sin += ds;
+    int32_t dc = -((int64_t)sinv * radians) >> LOG_UNIT_MAGNITUDE;
+    int32_t ds = ((int64_t)cosv * radians) >> LOG_UNIT_MAGNITUDE;
+    dc = -((int64_t)(sinv+ds/2) * radians) >> LOG_UNIT_MAGNITUDE;
+    ds = ((int64_t)(cosv+dc/2) * radians) >> LOG_UNIT_MAGNITUDE;
+    cosv += dc;
+    sinv += ds;
+}
+
+// For angle, 0x20000000 represents 45 degrees.
+void Reckoner::setTurnAngle(int32_t angle)
+{
+    double angleToRadiansFactor = 1.46291808e-9;  // pi/4 / 0x20000000
+    cosv = (int32_t)(cos(angle * angleToRadiansFactor) * (1 << LOG_UNIT_MAGNITUDE));
+    sinv = (int32_t)(sin(angle * angleToRadiansFactor) * (1 << LOG_UNIT_MAGNITUDE));
 }
\ No newline at end of file
--- a/reckoner.h	Wed Apr 15 19:19:19 2015 +0000
+++ b/reckoner.h	Wed Apr 15 21:19:22 2015 +0000
@@ -10,7 +10,7 @@
     // the current position of the robot.
     // cos corresponds to the x component of the orientation vector.
     // sin corresponds to the y component of the orientation vector.
-    int32_t cos, sin;
+    int32_t cosv, sinv;
     
     // Together, x and y are a vector that points from the starting point to the
     // robot's current position.
@@ -29,4 +29,5 @@
     void handleRight();
     void handleLeft();
     void handleTurnRadians(int32_t radians);
+    void setTurnAngle(int32_t angle);
 };
--- a/test.cpp	Wed Apr 15 19:19:19 2015 +0000
+++ b/test.cpp	Wed Apr 15 21:19:22 2015 +0000
@@ -47,8 +47,8 @@
 
 void showOrientationWithLeds34()
 {
-    led3 = reckoner.cos > 0;
-    led4 = reckoner.sin > 0;
+    led3 = reckoner.cosv > 0;
+    led4 = reckoner.sinv > 0;
 }
 
 void testTurnInPlace()
@@ -78,7 +78,7 @@
         if (motorUpdatePacer.pace())
         {
             int16_t rotationSpeed;
-            float s = (float)reckoner.sin / (1 << 30);
+            float s = (float)reckoner.sinv / (1 << 30);
             integral += s;
             rotationSpeed = -(s * 2400 + integral * 20);
             
@@ -272,7 +272,7 @@
         if (reportPacer.pace())
         {
             pc.printf("%11d %11d %11d %11d | %8d %8d %10f\r\n",
-              reckoner.cos, reckoner.sin, reckoner.x, reckoner.y,
+              reckoner.cosv, reckoner.sinv, reckoner.x, reckoner.y,
               encoderLeft.getCount(), encoderRight.getCount(), determinant());
         }
     }
@@ -439,7 +439,7 @@
         if(reportPacer.pace())
         {
             pc.printf("%11d %11d %11d %11d | %11f %11f\r\n",
-              reckoner.cos, reckoner.sin, reckoner.x, reckoner.y,
+              reckoner.cosv, reckoner.sinv, reckoner.x, reckoner.y,
               determinant(), dotProduct());
        }
     }
@@ -507,4 +507,32 @@
             pc.printf("%d\r\n", turnSensor.getAngleDegrees());
         }
     }
+}
+
+void testReckoningWithGyro()
+{   
+    setLeds(0, 0, 0, 1);
+    waitForSignalToStart();
+    setLeds(1, 0, 0, 1);
+
+    loadCalibration();
+    Timer timer;
+    timer.start();
+    TurnSensor turnSensor;
+    turnSensor.start();
+    while(1)
+    {
+        turnSensor.update();
+        updateReckoner(turnSensor);
+        loggerService();
+        
+        if (button1DefinitelyPressed())
+        {
+            break;
+        }
+    }
+    motorsSpeedSet(0, 0);
+    
+    setLeds(1, 1, 1, 1);
+    loggerReportLoop();
 }
\ No newline at end of file
--- a/test.h	Wed Apr 15 19:19:19 2015 +0000
+++ b/test.h	Wed Apr 15 21:19:22 2015 +0000
@@ -15,4 +15,5 @@
 void __attribute__((noreturn)) testCloseness();
 void __attribute__((noreturn)) testLogger();
 void __attribute__((noreturn)) testL3g();
-void __attribute__((noreturn)) testTurnSensor();
\ No newline at end of file
+void __attribute__((noreturn)) testTurnSensor();
+void __attribute__((noreturn)) testReckoningWithGyro();
\ No newline at end of file
--- a/turn_sensor.cpp	Wed Apr 15 19:19:19 2015 +0000
+++ b/turn_sensor.cpp	Wed Apr 15 21:19:22 2015 +0000
@@ -19,6 +19,11 @@
             // error
             return;
         }
+        
+        // The gyro on this robot is mounted upside down; account for that here so that
+        // we can have counter-clockwise be a positive rotation.
+        gz = -gz;
+        
         rate = gz;
         
         // First figure out how much time has passed since the last update (dt)