Code for autonomous rover for Sparkfun AVC. DataBus won 3rd in 2012 and the same code was used on Troubled Child, a 1986 Jeep Grand Wagoneer to win 1st in 2014.

Dependencies:   mbed Watchdog SDFileSystem DigoleSerialDisp

Files at this revision

API Documentation at this revision

Comitter:
shimniok
Date:
Thu Nov 29 19:45:49 2018 +0000
Parent:
21:894ba6f8d67b
Child:
23:a34af501ea89
Commit message:
Converted updater to class, fixed calls in main; changed include order of globals.h to fix extern pc variable.

Changed in this revision

Config/Config.cpp Show annotated file Show diff for this revision Revisions of this file
UI/shell.cpp Show annotated file Show diff for this revision Revisions of this file
Updater.cpp Show annotated file Show diff for this revision Revisions of this file
Updater.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
updater.cpp Show diff for this revision Revisions of this file
updater.h Show diff for this revision Revisions of this file
--- a/Config/Config.cpp	Thu Nov 29 18:34:22 2018 +0000
+++ b/Config/Config.cpp	Thu Nov 29 19:45:49 2018 +0000
@@ -1,198 +0,0 @@
-#define MAXBUF 64
-
-#include "Config.h"
-#include "SDFileSystem.h"
-#include "GeoPosition.h"
-#include "globals.h"
-#include "util.h"
-
-// Identifiers for each of the parameters
-#define CURB            "curb"
-#define WAYPOINT        "wpt"
-#define GPS             "gps"
-#define GYRO            "gyro"
-#define MAGNETOMETER    "mag"
-#define ACCELEROMETER   "accel"
-#define DECLINATION     "decl"
-#define NAVIGATION      "nav"
-#define STEER           "steer"
-#define SPEED           "speed"
-#define VEHICLE         "veh"
-#define ENCODER         "enc"
-
-
-Config::Config():
-    loaded(false),
-    intercept(0),
-    waypointDist(0),
-    brakeDist(0),
-    wptCount(0),
-    escMin(1300),
-    escZero(1300),
-    escMax(1300),
-    topSpeed(0),
-    turnSpeed(0),
-    startSpeed(0),
-    minRadius(0),
-    speedKp(0),
-    speedKi(0),
-    speedKd(0),
-    steerZero(0),
-    steerScale(0),
-    curbThreshold(0),
-    curbGain(0),
-    gyroScale(0),
-    // Data Bus Original Settings
-    wheelbase(0.280),
-    track(0.290),
-    tireCirc(0.321537),
-    encStripes(32)
-{
-    for (int i=0; i < MAX_WPT; i++) {
-        wptTopSpeedAdj[i] = 0;
-        wptTurnSpeedAdj[i] = 0;
-    }
-    for (int i=0; i < 3; i++) {
-        magOffset[i] = 0;
-        magScale[i] = 0;
-    }
-}
-
-// load configuration from filesystem
-bool Config::load(const char *filename)
-{
-    FILE *fp;
-    char buf[MAXBUF];   // buffer to read in data
-    char tmp[MAXBUF];   // temp buffer
-    char *p;
-    double lat, lon;
-    float wTopSpeed, wTurnSpeed;
-    bool declFound = false;
-    bool confStatus = false;
-
-    pc.printf("opening config file...\n");
-    
-    fp = fopen(filename, "r");
-    if (fp == 0) {
-        pc.puts("Could not open ");
-        pc.puts(filename);
-        pc.puts(" \n");
-    } else {
-        wptCount = 0;
-        while (!feof(fp)) {
-            fgets(buf, MAXBUF-1, fp);
-            p = split(tmp, buf, MAXBUF, ',');               // split off the first field
-
-            if (!strcmp(tmp, CURB)) {
-
-                p = split(tmp, p, MAXBUF, ',');             // threshold distance for curb avoid
-                curbThreshold = cvstof(tmp);
-                p = split(tmp, p, MAXBUF, ',');             // steering gain for curb avoid
-                curbGain = cvstof(tmp);
-
-            } else if (!strcmp(tmp, WAYPOINT)) {
-
-                p = split(tmp, p, MAXBUF, ',');             // split off the latitude to tmp
-                lat = cvstof(tmp);
-                p = split(tmp, p, MAXBUF, ',');             // split off the longitude to tmp
-                lon = cvstof(tmp);
-                p = split(tmp, p, MAXBUF, ',');             // split off the waypoint top speed
-                wTopSpeed = cvstof(tmp);
-                p = split(tmp, p, MAXBUF, ',');             // split off the waypoint turn speed
-                wTurnSpeed = cvstof(tmp);
-                if (wptCount < MAXWPT) {
-                    wpt[wptCount].set(lat, lon);            // set position
-                    wptTopSpeedAdj[wptCount] = wTopSpeed;   // set top speed adjust
-                    wptTurnSpeedAdj[wptCount] = wTurnSpeed; // set turn speed adjust
-                    wptCount++;
-                }
-
-            } else if (!strcmp(tmp, NAVIGATION)) {
-
-                p = split(tmp, p, MAXBUF, ',');
-                intercept = (float) cvstof(tmp);        // intercept distance for steering algorithm
-                p = split(tmp, p, MAXBUF, ',');
-                waypointDist = (float) cvstof(tmp);         // distance before waypoint switch
-                p = split(tmp, p, MAXBUF, ',');
-                brakeDist = (float) cvstof(tmp);            // distance at which braking starts
-                p = split(tmp, p, MAXBUF, ',');
-                minRadius = (float) cvstof(tmp);            // minimum turning radius
-
-            } else if (!strcmp(tmp, STEER)) {
-
-                p = split(tmp, p, MAXBUF, ',');
-                steerZero = cvstof(tmp);                    // servo center setting
-                p = split(tmp, p, MAXBUF, ',');
-                steerScale = cvstof(tmp);                   // steering angle conversion factor
-
-            } else if (!strcmp(tmp, SPEED)) {
-
-                p = split(tmp, p, MAXBUF, ',');
-                escMin = cvstof(tmp);                       // minimum esc (brake) setting
-                p = split(tmp, p, MAXBUF, ',');
-                escZero = cvstof(tmp);                      // esc center/zero setting
-                p = split(tmp, p, MAXBUF, ',');
-                escMax = cvstof(tmp);                       // maximum esc setting
-                p = split(tmp, p, MAXBUF, ',');
-                topSpeed = cvstof(tmp);                     // desired top speed
-                p = split(tmp, p, MAXBUF, ',');
-                turnSpeed = cvstof(tmp);                    // speed to use when turning
-                p = split(tmp, p, MAXBUF, ',');
-                startSpeed = cvstof(tmp);                   // speed to use at start
-                p = split(tmp, p, MAXBUF, ',');
-                speedKp = cvstof(tmp);                      // speed PID: proportional gain
-                p = split(tmp, p, MAXBUF, ',');
-                speedKi = cvstof(tmp);                      // speed PID: integral gain
-                p = split(tmp, p, MAXBUF, ',');
-                speedKd = cvstof(tmp);                      // speed PID: derivative gain
-
-            } else if (!strcmp(tmp, VEHICLE)) {
-                p = split(tmp, p, MAXBUF, ',');
-                wheelbase = cvstof(tmp);                    // vehicle wheelbase (front to rear axle)
-                p = split(tmp, p, MAXBUF, ',');
-                track = cvstof(tmp);                        // vehicle track width (left to right)
-            } else if (!strcmp(tmp, ENCODER)) {
-                p = split(tmp, p, MAXBUF, ',');
-                tireCirc = cvstof(tmp);                     // tire circumference
-                p = split(tmp, p, MAXBUF, ',');
-                encStripes = atoi(tmp);                     // ticks per revolution
-            } else if (!strcmp(tmp, GYRO)) {
-                p = split(tmp, p, MAXBUF, ',');             // split off the declination to tmp
-                gyroScale = cvstof(tmp);            // gyro scaling factor to deg/sec
-            } else if (!strcmp(tmp, GPS)) {
-                p = split(tmp, p, MAXBUF, ',');
-                gpsValidSpeed = cvstof(tmp);
-            } //if-else
-            /* else if (!strcmp(tmp, DECLINATION)) {
-                p = split(tmp, p, MAXBUF, ',');     // split off the declination to tmp
-                declination = (float) cvstof(tmp);
-                declFound = true;
-            } else if (!strcmp(tmp, MAGNETOMETER)) {
-                for (int i=0; i < 3; i++) {
-                    p = split(tmp, p, MAXBUF, ',');
-                    magOffset[i] = (float) cvstof(tmp);
-                    pc.printf("magOffset[%d]: %.2f\n", i, magOffset[i]);
-                }
-                for (int i=0; i < 3; i++) {
-                    p = split(tmp, p, MAXBUF, ',');
-                    magScale[i] = (float) cvstof(tmp);
-                    pc.printf("magScale[%d]: %.2f\n", i, magScale[i]);
-                }
-            }
-            */
-        } // while
-
-        // Did we get the values we were looking for?
-        if (wptCount > 0 && declFound) {
-            confStatus = true;
-        }
-        
-    } // if fp
-    
-    if (fp != 0)
-        fclose(fp);
-
-    loaded = confStatus;
-
-    return confStatus;
-}
\ No newline at end of file
--- a/UI/shell.cpp	Thu Nov 29 18:34:22 2018 +0000
+++ b/UI/shell.cpp	Thu Nov 29 19:45:49 2018 +0000
@@ -1,527 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include "mbed.h"
-#include "globals.h"
-#include "updater.h"
-#include "print.h"
-#include "DirHandle.h"
-#include "SDFileSystem.h"
-#include "util.h"
-#include "Buttons.h"
-
-#define MAXBUF      128
-#define MAXCMDARR   21
-
-char cwd[MAXBUF];
-char buf[MAXBUF];
-char path[MAXBUF];
-int status;
-bool _debug=false;
-bool done=false;
-
-typedef struct {
-    const char *cmd;
-    int (*f)(char *arg0);
-    const char *desc;
-} cmd;
-
-extern int autonomousMode();
-extern int resetMe();
-extern int gyroSwing();
-
-extern "C" {
-
-void shell(void *args);
-void docmd(char *cmdline);
-void termInput(char *cmd);
-void resolveDirectory(char *newpath, char *path);
-void splitName(const char *path, char *dirname, char *basename);
-int dols(char *arg);
-int docd(char *path);
-int dopwd(char *s);
-int dotouch(char *path);
-int dorm(char *path);
-int domkdir(char *path);
-int dohead(char *path);
-int docat(char *path);
-int dosend(char *path);
-int doprintfree(char *path);
-int doexit(char *s);
-int dodebug(char *s);
-int dohelp(char *s);
-int dogyroswing(char *s);
-int doreset(char *s);
-int doautonomous(char *s);
-int dospeed(char *arg);
-int dosteer(char *arg);
-int dotimes(char *arg);
-
-// TODO 3 multiple arguments
-
-const cmd command[MAXCMDARR] = {
-        { "help", dohelp, "print this help" },
-        { "ls", dols, "list files" },
-        { "cd", docd, "change directory" },
-        { "pwd", dopwd, "print working directory" },
-        { "touch", dotouch, "create, update file" },
-        { "mkdir", domkdir, "make directory" },
-        { "head", dohead, "output first part of file" },
-        { "cat", docat, "output file" },
-        { "send", dosend, "send file to terminal" },
-        { "rm", dorm, "remove file" },
-        { "debug", dodebug, "toggle debug mode" },
-        { "gyro", dogyroswing, "gyro swing" },
-        { "auto", doautonomous, "run autonomous mode" },
-        { "reset", doreset, "reset the MCU" },
-        { "free", doprintfree, "heap bytes available" },
-        { "speed", dospeed, "set speed servo output" },
-        { "steer", dosteer, "set steering servo output" },
-        { "time", dotimes, "display update timing stats" },
-//      { "exit", doexit, "exit shell" },
-        { 0, 0, 0 }
-};
-
-void shell(void *args) {
-    char cmdline[MAXBUF];
-
-    pc.baud(115200);
-
-    strcpy(cwd, "/log");
-
-    fputs("Type help for assistance.\n", stdout);
-
-    status=0;
-    done=false;
-    while (!done) {
-        termInput(cmdline);
-
-        // interrupt operation if keypad button is pressed
-        if (keypad.pressed) {
-            keypad.pressed = false;
-            break;
-        }        
-
-        docmd(cmdline);
-    }
-    fputs("exiting shell\n", stdout);
-
-    return;
-}
-
-
-/** docmd
- * Run a command by looking it up the command requested on the shell command line in the
- * command array.  If it's found, run the associated function. If not, print an error.
- */
-void docmd(char *cmdline) {
-    char *arg;
-    char cmd[MAXBUF];
-    bool found = false;
-
-    arg = split(cmd, cmdline, MAXBUF, ' ');
-    if (strlen(cmd) > 0) {
-        //if (debug) fprintf(stdout, "cmdline:<%s> cmd:<%s> arg:<%s>\n", cmdline, cmd, arg);
-
-        for (int i=0; command[i].cmd; i++) {
-            if (!strcmp(cmd, command[i].cmd)) {
-                found = true;
-                command[i].f(arg);
-            }
-        }
-
-        if (!found) {
-            fputs(cmd, stdout);
-            fputs(": command not found\n", stdout);
-        }
-    }
-
-    return;
-}
-
-
-/** termInput
- * read input from the terminal
- */
-void termInput(char *cmd) {
-    int i=0;
-    char c;
-    bool done = false;
-    
-    memset(cmd, 0, MAXBUF);
-    fputc('(', stdout);
-    fputs(cwd, stdout);
-    fputs(")# ", stdout);
-    do {
-        cmd[i] = 0;
-        c = fgetc(stdin);
-        if (c == '\r') { // if return is hit, we're done, don't add \r to cmd
-            done = true;
-        } else if (i < MAXBUF-1) {
-            if (c == 0x7f || c == '\b') { // backspace or delete
-                if (i > 0) { // if we're at the beginning, do nothing
-                    i--;
-                    fputs("\b \b", stdout);
-
-                }
-            } else {
-                fputc(c, stdout);
-                cmd[i++] = c;
-            }
-        }
-    } while (!done);
-    fputc('\n', stdout);
-
-
-} 
-
-/** resolveDirectory
- * resolve the directory path provided, given the cwd
- */
-void resolveDirectory(char *newpath, char *path) {
-    char dirname[32], basename[16];
-    
-    /** absolute path */
-    if (path[0] == '/') {
-        strcpy(newpath, path);
-    }
-    /** relative path */
-    else {
-        strcpy(newpath, cwd);
-        if (path[0] != 0) {
-            if (newpath[strlen(newpath)-1] != '/')
-                strcat(newpath, "/");
-            strcat(newpath, path);    
-        }
-        /** Resolve .. references */
-        splitName(newpath, dirname, basename);
-        if (!strcmp(basename, "..")) {
-            splitName(dirname, newpath, basename);
-        }
-    }
-}
-
-/** splitCmd
- * copy t to s until space is reached
- * return location of delimiter+1 in t
- * if space not found, return t pointing to end of string
- * if s or t null, return null
- */
-char *splitCmd(char *s, char *t, int max)
-{
-  int i = 0;
-  
-  if (s == 0 || t == 0)
-    return 0;
-
-  while (*t != 0 && i < max) {
-    *s++ = *t++;
-    i++;
-    if (*t == ' ') {
-        t++;
-        break;
-    }
-  }
-  *s = 0;
-
-  return t;
-}
-
-/** splitName
- * split the path into a dirname and a 
- */
-void splitName(const char *path, char *dirname, char *basename) {
-    int sep;
-    
-    sep = 0;
-    //if (debug) fprintf(stdout, "%d\n", strlen(path));
-    for (int i=strlen(path)-1; i >= 0; i--) {
-        //if (debug) fprintf(stdout, "- %c\n", path[i]);
-        sep = i;
-        if (path[i] == '/') break;
-    }
-    for (int j=0; j < sep; j++) {
-        //if (debug) fprintf(stdout, "> %c\n", path[j]);
-        dirname[j] = path[j];
-        dirname[j+1] = 0;
-    }
-    for (unsigned int k=sep+1; k != strlen(path); k++) {
-        //if (debug) fprintf(stdout, "* %c\n", path[k]);
-        basename[k-(sep+1)] = path[k];
-        basename[k-sep] = 0;    
-    }
-    //if (_debug) fprintf(stdout, "d:<%s> b:<%s>\n", dirname, basename);
-
-
-}
-
-/** ls
- * lists files in the current working directory, 4 columns
- */
-int dols(char *arg) {
-    //if (_debug) fprintf(stdout, "%s\n", cwd);
-    DIR *d;
-    struct dirent *p;
-
-    resolveDirectory(path, arg);
-
-    int count=0;
-    if ((d = opendir(path)) != NULL) {
-        while ((p = readdir(d)) != NULL) {
-            int pad = 20 - strlen(p->d_name);
-            while (pad-- > 0) fputc(' ', stdout);
-            fputs(p->d_name, stdout);
-            if (count++ >= 3) {
-                count = 0;
-                fputc('\n', stdout);
-            }
-        }
-        fputc('\n', stdout);
-        if (count < 3)
-            fputc('\n', stdout);
-        closedir(d);
-        status = 0;
-    } else {
-        fputs(path, stdout);
-        fputs(": No such directory\n", stdout);
-        status = 1;
-    }
-
-    return status;
-}
-
-/** cd
- * changes current working directory
- */
-int docd(char *arg) {
-
-    resolveDirectory(path, arg);
-    strcpy(cwd, path);
-
-    return 0;
-}
-
-/** pwd
- * print current working directory
- */
-int dopwd(char *arg) {
-    fputs(cwd, stdout);
-    fputc('\n', stdout);
-    //fprintf(stdout, "%s\n", cwd);
-
-    return 0;
-}
-
-/** touch
- * create an empty file
- */
-int dotouch(char *arg) {
-    FILE *fp;
-
-    resolveDirectory(path, arg);
-    if ((fp = fopen(path, "w")) != NULL) {
-        fclose(fp);
-        status = 0;
-    } else {
-        fputs(path, stdout);
-        fputs(": No such file\n", stdout);
-        status = 1;
-    }
-
-    return status;
-} 
-
-int dorm(char *arg) {
-    resolveDirectory(path, arg);
-    return remove(path);
-}
-
-int domkdir(char *arg) {
-    resolveDirectory(path, arg);
-    return mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO);
-}
-
-/** head
- * print the first 10 lines of a file
- */
-int dohead(char *arg) {
-    FILE *fp;
-    char line = 0;
-
-    resolveDirectory(path, arg);
-    if ((fp = fopen(path, "r")) != NULL) {
-        while (!feof(fp) && line++ < 10) {
-            fgets(buf, 128, fp);
-            fputs(buf, stdout);
-        }
-        fclose(fp);
-        status = 0;
-    } else {
-        fputs(path, stdout);
-        fputs(": No such file\n", stdout);
-        status = 1;
-    }
-
-    return status;
-}
-
-/** cat
- * display the content of a file
- */
-int docat(char *arg) {
-    FILE *fp;
-
-    resolveDirectory(path, arg);
-    if ((fp = fopen(path, "r")) != NULL) {
-        while (fgets(buf, 127, fp)) {
-            fputs(buf, stdout);
-        }
-        fclose(fp);
-        status = 0;
-    } else {
-        fputs(path, stdout);
-        fputs(": No such file\n", stdout);
-        status = 1;
-    }
-
-    return status;
-}
-
-/** send
- * Simple serial file transfer protocol
- * Initiates escape sequence: ^A^B, sends filename, ^C, and then file
- * contents followed by ^D
- */
-int dosend(char *arg) {
-    FILE *fp;
-    char dirname[32], basename[16];
-
-    resolveDirectory(path, arg);
-    if ((fp = fopen(path, "r")) != NULL) {
-        splitName(path, dirname, basename);
-        fputc(0x01, stdout);
-        fputc(0x02, stdout);
-        fputs(basename, stdout);
-        fputc(0x03, stdout);
-        while (!feof(fp)) {
-            if (fgets(buf, 127, fp) != NULL)
-                fputs(buf, stdout);
-        }
-        fclose(fp);
-        fputc(0x04, stdout);
-        status = 0;
-    } else {
-        fputs(path, stdout);
-        fputs(": No such file\n", stdout);
-        status = 1;
-    }
-
-    return status;
-}
-
-int doprintfree(char *arg) {
-    //printInt(stdout, xPortGetFreeHeapSize());
-    fputs(" bytes free.\n", stdout);
-
-    return 0;
-}
-
-/** doexit
- * set a flag to exit the shell
- */
-int doexit(char *arg) {
-    done = true;
-
-    return 0;
-}
-
-/** dodebug
- * toggle the _debug state variable
- */
-int dodebug(char *arg) {
-    _debug = !_debug;
-
-    return 0;
-}
-
-/** dohelp
- * print the list of commands and descriptions
- */
-int dohelp(char *arg) {
-    for (int i=0; command[i].cmd; i++) {
-        int pad = 10 - strlen(command[i].cmd);
-        while (pad--) fputc(' ', stdout);
-        fputs(command[i].cmd, stdout);
-        fputs(": ", stdout);
-        fputs(command[i].desc, stdout);
-        fputc('\n', stdout);
-    }
-
-    return 0;
-}
-
-/** dogyroswing
- * perform gyro swing, call external function
- */
-int dogyroswing(char *arg) {
-    gyroSwing();
-
-    return 0;
-}
-
-/** doreset
- * reset the processor
- */
-int doreset(char *arg) {
-    resetMe();
-    return 0; // won't ever reach this line...
-}
-
-/** doautonomous
- * call external doAutonomous mode to perform an autonomous run
- */
-int doautonomous(char *arg) {
-    autonomousMode();
-
-    return 0;
-}
-
-
-int dospeed(char *arg) {
-    // TODO 3 dospeed()
-//  int v = atoi(arg);
-//  if (config.escMin < v && v < config.escMax {
-//      fputs("speed=", stdout);
-//      setThrottle(v);
-//      printFloat(stdout, getThrottle(), 4);
-//      fputc('\n', stdout);
-//  }
-    return 0;
-}
-
-int dosteer(char *arg) {
-    float v = cvstof(arg);
-    fputs("angle=", stdout);
-    printFloat(stdout, v, 4);
-    fputs(" servo=", stdout);
-    // TODO fix setSteering call
-    //setSteering(v);
-    // TODO 4 printFloat(stdout, getSteering(), 4);
-    fputc('\n', stdout);
-    return 0;
-}
-
-int dotimes(char *arg) {
-    int i;
-    for (i = 1; i < 8; i++) {
-        printInt(stdout, i);
-        fputc(':', stdout);
-        // TODO 4 printInt(stdout, getUpdateTime(i)-getUpdateTime(i-1));
-        fputc('\n', stdout);
-    }
-    fputs("total:", stdout);
-    // TODO 4 printInt(stdout, getUpdateTime(7)-getUpdateTime(0));
-    fputc('\n', stdout);
-    return 0;
-}
-
-} // extern C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Updater.h	Thu Nov 29 19:45:49 2018 +0000
@@ -0,0 +1,45 @@
+#ifndef __SCHEDULER_H
+#define __SCHEDULER_H
+
+/** Updater is the main real time sensor update, estimation, and control routine that is
+ * called at 100Hz by a timer interrupt
+ */
+class Updater {
+public:
+
+    /** attach the update routine to Ticker interrupt */
+    void start(void);
+
+    /** detach the update routine from Ticker interrupt */
+    void stop(void);
+
+    /** Tells the updater to re-initialize the navigation state */
+    void restartNav(void);
+
+    /** Indicates to the updater that the vehicle should begin its run */
+    void beginRun(void);
+
+    /** Indicates to the updater that the vehicle should abort its run */
+    void endRun(void);
+    
+    /** Returns the elapsed time taken by the updater routine on its most recent run */
+    int getUpdateTime(void);
+
+    /** Sets the desired speed of the rover */
+    void setSpeed(float speed);
+    
+    /** The function that is called at 100Hz. It reads sensors, performs estimation, and controls the robot */
+    void update(void);
+    
+    /** initialize throttle to center position */
+    void initThrottle(void);
+
+    /** initialize steering to center position */
+    void initSteering(void);
+
+    /** Sets the steering angle */
+    void setSteering(float steerAngle);
+    
+}
+
+#endif
--- a/main.cpp	Thu Nov 29 18:34:22 2018 +0000
+++ b/main.cpp	Thu Nov 29 19:45:49 2018 +0000
@@ -1,770 +0,0 @@
-/** Code for "Data Bus" UGV entry for Sparkfun AVC 2014
- *  http://www.bot-thoughts.com/
- */
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-// INCLUDES
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#include "mbed.h"
-#include <math.h>
-#include <stdint.h>
-#include "devices.h"
-#include "globals.h"
-#include "Config.h"
-#include "Buttons.h"
-#include "Display.h"
-#include "Menu.h"
-#include "GPSStatus.h"
-#include "logging.h"
-#include "Telemetry.h"
-#include "SystemState.h"
-#include "shell.h"
-#include "Steering.h"
-#include "Sensors.h"
-#include "kalman.h"
-#include "Ublox6.h"
-#include "PinDetect.h" // TODO 4 this should be broken into .h, .cpp
-#include "IncrementalEncoder.h"
-#include "Steering.h"
-#include "Schedule.h"
-#include "GeoPosition.h"
-#include "Mapping.h"
-#include "SimpleFilter.h"
-#include "Beep.h"
-#include "util.h"
-#include "updater.h"
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-// DEFINES
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-#define absf(x) (x *= (x < 0.0) ? -1 : 1)
-
-#define GPS_MIN_SPEED   2.0             // speed below which we won't trust GPS course
-#define GPS_MAX_HDOP    2.0             // HDOP above which we won't trust GPS course/position
-
-// Driver configuration parameters
-#define SONARLEFT_CHAN   0
-#define SONARRIGHT_CHAN  1
-#define IRLEFT_CHAN      2
-#define IRRIGHT_CHAN     3  
-#define TEMP_CHAN        4
-#define GYRO_CHAN        5
-
-#define INSTRUMENT_CHECK    0
-#define AHRS_VISUALIZATION  1
-#define DISPLAY_PANEL       2
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-// GLOBAL VARIABLES
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// OUTPUT
-DigitalOut confStatus(LED1);            // Config file status LED
-DigitalOut logStatus(LED2);             // Log file status LED
-DigitalOut gpsStatus(LED3);             // GPS fix status LED
-DigitalOut updaterStatus(LED4);         // update loop status LED
-//DigitalOut sonarStart(p18);           // Sends signal to start sonar array pings
-Display display;                        // UI display
-//Beep speaker(p24);                      // Piezo speaker
-
-// INPUT
-Menu menu;
-Buttons keypad;
-
-// COMM
-Serial pc(USBTX, USBRX);                // PC usb communications
-SerialGraphicLCD lcd(LCDTX, LCDRX, SD_FW);  // Graphic LCD with summoningdark firmware
-Serial tel(TELEMTX, TELEMRX);           // UART for telemetry
-Telemetry telem(tel);                   // Setup telemetry system
-
-// SENSORS
-Sensors sensors;                        // Abstraction of sensor drivers
-//DCM ahrs;                             // ArduPilot/MatrixPilot AHRS
-Serial *dev;                            // For use with bridge
-
-// MISC
-FILE *camlog;                           // Camera log
-Config config;                          // Configuration utility
-
-// Timing
-Timer timer;                            // For main loop scheduling
-
-// GPS Variables
-unsigned long age = 0;                  // gps fix age
-
-// schedule for LED warning flasher
-Schedule blink;
-
-// Estimation & Navigation Variables
-GeoPosition dr_here;                    // Estimated position based on estimated heading
-Mapping mapper;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-// FUNCTION DEFINITIONS
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-int autonomousMode(void);
-void serialBridge(Serial &gps);
-int gyroSwing(void);
-int setBacklight(void);
-int reverseScreen(void);
-float irDistance(const unsigned int adc);
-extern "C" void mbed_reset();
-
-// If we don't close the log file, when we restart, all the written data
-// will be lost.  So we have to use a button to force mbed to close the
-// file and preserve the data.
-//
-
-int dummy(void)
-{
-    return 0;
-}
-
-
-int resetMe()
-{
-    mbed_reset();
-    
-    return 0;
-}
-
-
-int main()
-{
-    //checkit(__FILE__, __LINE__);
-    //xTaskCreate( shell, (const signed char * ) "shell", 128, NULL, (tskIDLE_PRIORITY+3), NULL );
-    //checkit(__FILE__, __LINE__);
-    //vTaskStartScheduler(); // should never get past this line.
-    //while(1);
-
-    // Let's try setting priorities...
-    //NVIC_SetPriority(DMA_IRQn, 0);
-    NVIC_SetPriority(TIMER3_IRQn, 2);   // updater running off Ticker, must be highest priority!!
-    NVIC_SetPriority(EINT0_IRQn, 5);    // wheel encoders
-    NVIC_SetPriority(EINT1_IRQn, 5);    // wheel encoders
-    NVIC_SetPriority(EINT2_IRQn, 5);    // wheel encoders
-    NVIC_SetPriority(EINT3_IRQn, 5);    // wheel encoders
-    NVIC_SetPriority(SPI_IRQn, 7);      // uSD card, logging
-    NVIC_SetPriority(UART0_IRQn, 10);   // USB
-    NVIC_SetPriority(UART1_IRQn, 10);
-    NVIC_SetPriority(UART2_IRQn, 10);
-    NVIC_SetPriority(UART3_IRQn, 10);
-    NVIC_SetPriority(I2C0_IRQn, 10);    // sensors?
-    NVIC_SetPriority(I2C1_IRQn, 10);    // sensors?
-    NVIC_SetPriority(I2C2_IRQn, 10);    // sensors?
-    NVIC_SetPriority(ADC_IRQn, 10);     // Voltage/current
-    NVIC_SetPriority(TIMER0_IRQn, 10);  // unused(?)
-    NVIC_SetPriority(TIMER1_IRQn, 10);  // unused(?)
-    NVIC_SetPriority(TIMER2_IRQn, 10);  // unused(?)
-
-    // Something here is jacking up the I2C stuff
-    // Also when initializing with ESC powered, it causes motor to run which
-    // totally jacks up everything (noise?)
-    initSteering();
-    initThrottle();
-
-    display.init();
-    display.status("Data Bus 2014");
-
-    // Send data back to the PC
-    pc.baud(115200);
-    fputs("Data Bus 2014\n", stdout);
-    fflush(stdin);
-
-    fputs("Initializing...\n", stdout);
-    display.status("Initializing");
-    
-    // Initialize status LEDs
-    updaterStatus = 0;
-    gpsStatus = 0;
-    logStatus = 0;
-    confStatus = 0;
-
-    if (!fifo_init()) {
-        error("\n\n%% Error initializing SystemState fifo %%\n");
-    }
-
-    fputs("Loading configuration...\n", stdout);
-    display.status("Load config");
-    if (config.load("/etc/config.txt"))                          // Load various configurable parameters, e.g., waypoints, declination, etc.
-        confStatus = 1;
-
-    initThrottle();
-
-    //pc.printf("Declination: %.1f\n", config.declination);
-    pc.puts("Speed: escZero=");
-    pc.puts(cvftos(config.escZero, 3));
-    pc.puts(" escMin=");
-    pc.puts(cvftos(config.escMin, 3));
-    pc.puts(" escMax=");
-    pc.puts(cvftos(config.escMax, 3));
-    pc.puts(" top=");
-    pc.puts(cvftos(config.topSpeed, 1));
-    pc.puts(" turn=");
-    pc.puts(cvftos(config.turnSpeed, 1));
-    pc.puts(" Kp=");
-    pc.puts(cvftos(config.speedKp, 4));
-    pc.puts(" Ki=");
-    pc.puts(cvftos(config.speedKi, 4));
-    pc.puts(" Kd=");
-    pc.puts(cvftos(config.speedKd, 4));
-    pc.puts("\n");
-
-    pc.puts("Steering: steerZero=");
-    pc.puts(cvftos(config.steerZero, 2));
-    pc.puts(" steerScale=");
-    pc.puts(cvftos(config.steerScale, 1));
-    pc.puts("\n");
-    steering.setScale(config.steerScale);
-
-    // Convert lat/lon waypoints to cartesian
-    mapper.init(config.wptCount, config.wpt);
-    for (unsigned int w = 0; w < MAXWPT && w < config.wptCount; w++) {
-        mapper.geoToCart(config.wpt[w], &(config.cwpt[w]));
-        pc.puts("Waypoint #");
-        pc.puts(cvntos(w));
-        pc.puts(" (");
-        pc.puts(cvftos(config.cwpt[w].x, 4));
-        pc.puts(", ");
-        pc.puts(cvftos(config.cwpt[w].y, 4));
-        pc.puts(") lat: ");
-        pc.puts(cvftos(config.wpt[w].latitude(), 6));
-        pc.puts(" lon: ");
-        pc.puts(cvftos(config.wpt[w].longitude(), 6));
-        pc.puts(", topspeed: ");
-        pc.puts(cvftos(config.topSpeed + config.wptTopSpeedAdj[w], 1));
-        pc.puts(", turnspeed: ");
-        pc.puts(cvftos(config.turnSpeed + config.wptTurnSpeedAdj[w], 1));
-        pc.puts("\n");
-    }
-
-    // TODO 3 print mag and gyro calibrations
-
-    // TODO 3 remove GPS configuration, all config will be in object itself I think
-
-    display.status("Vehicle config      ");
-    pc.puts("Wheelbase: ");
-    pc.puts(cvftos(config.wheelbase, 3));
-    pc.puts("\n");
-    pc.puts("Track Width: ");
-    pc.puts(cvftos(config.track, 3));
-    pc.puts("\n");
-    steering.setWheelbase(config.wheelbase);
-    steering.setTrack(config.track);
-
-    display.status("Encoder config      ");
-    pc.puts("Tire Circumference: ");
-    pc.puts(cvftos(config.tireCirc, 5));
-    pc.puts("\n");
-    pc.puts("Ticks per revolution: ");
-    pc.puts(cvftos(config.encStripes, 5));
-    pc.puts("\n");
-    sensors.configureEncoders(config.tireCirc, config.encStripes);
-
-    display.status("Nav configuration   ");
-    pc.puts("Intercept distance: ");
-    pc.puts(cvftos(config.intercept, 1));
-    pc.puts("\n");
-    steering.setIntercept(config.intercept);
-    pc.puts("Waypoint distance: ");
-    pc.puts(cvftos(config.waypointDist, 1));
-    pc.puts("\n");
-    pc.puts("Brake distance: ");
-    pc.puts(cvftos(config.brakeDist, 1));
-    pc.puts("\n");
-    pc.puts("Min turn radius: ");
-    pc.puts(cvftos(config.minRadius, 3));
-    pc.puts("\n");
-
-    display.status("Gyro config         ");
-    pc.puts("Gyro scale: ");
-    pc.puts(cvftos(config.gyroScale, 5));
-    pc.puts("\n");
-    sensors.setGyroScale(config.gyroScale);
-
-    display.status("GPS configuration   ");
-    pc.puts("GPS valid speed: ");
-    pc.puts(cvftos(config.gpsValidSpeed,1));
-    pc.puts("\n");
-
-    pc.puts("Gyro config         ");
-    pc.puts("\n");
-    pc.puts("Gyro scale: ");
-    pc.puts(cvftos(config.gyroScale, 5));
-    pc.puts("\n");
-    sensors.setGyroScale(config.gyroScale);
-
-    pc.puts("Calculating offsets...\n");
-    display.status("Offset calculation  ");
-    wait(0.2);
-    // TODO 3 Really need to give the gyro more time to settle
-    sensors.gps.disable();
-    // TODO 2 sensors.Calculate_Offsets();
-
-    pc.puts("Starting GPS...\n");
-    display.status("Start GPS           "); // TODO 3: would be nice not to have to pad at this level
-    wait(0.2);
-    sensors.gps.setUpdateRate(10);
-    sensors.gps.enable();
-
-    pc.puts("Starting Scheduler...\n");
-    display.status("Start scheduler     ");
-    wait(0.2);
-    // Startup sensor/AHRS ticker; update every UPDATE_PERIOD
-    restartNav();
-    startUpdater();
-
-    pc.puts("Starting keypad...\n");
-
-    keypad.init();
-    
-    pc.puts("Adding menu items...\n");
-
-    // Setup LCD Input Menu
-    menu.add("Auto mode", &autonomousMode);
-    menu.add("Gyro Calib", &gyroSwing);
-    menu.add("Backlight", &setBacklight);
-    menu.add("Reverse", &reverseScreen);
-    menu.add("Reset", &resetMe);
-
-    pc.puts("Starting main timer...\n");
-
-    timer.start();
-    timer.reset();
-
-    int thisUpdate = timer.read_ms();    
-    int nextDisplayUpdate = thisUpdate;
-    int nextWaypointUpdate = thisUpdate;
-    char cmd;
-    bool printMenu = true;
-    bool printLCDMenu = true;
-
-    pc.puts("Timer done, enter loop...\n");
-
-    while (1) {
-
-        thisUpdate = timer.read_ms();
-        if (thisUpdate > nextDisplayUpdate) {
-            // Pulling out current state so we get the most current
-            SystemState *s = fifo_first();
-            // TODO 3 fix this so gps is already in state
-            // Now populate in the current GPS data
-            s->gpsHDOP = sensors.gps.hdop();
-            s->gpsSats = sensors.gps.sat_count();
-
-            telem.sendPacket(s);
-            display.update(s);
-            nextDisplayUpdate = thisUpdate + 200;
-        }
-
-        // every so often, send the currently configured waypoints
-        if (thisUpdate > nextWaypointUpdate) {
-            telem.sendPacket(config.cwpt, config.wptCount);
-            nextWaypointUpdate = thisUpdate + 10000;
-            // TODO 2: make this a request/response, Telemetry has to receive packets, decode, etc.
-        }
-
-        if (keypad.pressed) {
-            keypad.pressed = false;
-            printLCDMenu = true;
-            switch (keypad.which) {
-                case NEXT_BUTTON:
-                    menu.next();
-                    break;
-                case PREV_BUTTON:
-                    menu.prev();
-                    break;
-                case SELECT_BUTTON:
-                    display.select(menu.getItemName());
-                    menu.select();
-                    printMenu = true;
-                    break;
-                default:
-                    printLCDMenu = false;
-                    break;
-            }//switch  
-            keypad.pressed = false;
-        }// if (keypad.pressed)
-
-            
-        if (printLCDMenu) {
-            display.menu( menu.getItemName() );
-            display.status("Ready.");
-            display.redraw();
-            printLCDMenu = false;
-        }
-        
-        // TODO 3 move to UI area
-        if (printMenu) {
-            fputs("\n==============\nData Bus Menu\n==============\n", stdout);
-            fputs("0) Autonomous mode\n", stdout);
-            fputs("1) Bridge serial to GPS\n", stdout);
-            fputs("2) Gyro calibrate\n", stdout);
-            fputs("3) Shell\n", stdout);
-            fputs("R) Reset\n", stdout);
-            fputs("\nSelect from the above: ", stdout);
-            fflush(stdout);
-            printMenu = false;
-        }
-
-        if (pc.readable()) {
-            cmd = fgetc(stdin);
-            fputc(cmd, stdout);
-            fputc('\n', stdout);
-            printMenu = true;
-            printLCDMenu = true;
-            
-            switch (cmd) {
-                case 'R' :
-                    resetMe();
-                    break;
-                case '0' :
-                    display.select(menu.getItemName(0));
-                    autonomousMode();
-                    break;
-                case '1' :
-                    display.select("Serial bridge");
-                    display.status("Standby.");
-                    sensors.gps.enableVerbose();
-                    serialBridge( *(sensors.gps.getSerial()) );
-                    sensors.gps.disableVerbose();
-                    break;
-                case '2' :
-                    display.select("Gyro Calib");
-                    display.select(menu.getItemName(2));
-                    gyroSwing();
-                    break;
-                case '3' :
-                    display.select("Shell");
-                    display.status("Standby.");
-                    shell(0);
-                    break;
-                default :
-                    break;
-            } // switch        
-
-        } // if (pc.readable())
-
-        wait(0.1);
-
-    } // while
-
-}
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-// OPERATIONAL MODE FUNCTIONS
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-int autonomousMode()
-{
-    bool goGoGo = false;                // signal to start moving
-    bool navDone;                       // signal that we're done navigating
-    int nextTelemUpdate;                // keeps track of teletry update periods
-    //extern int tSensor, tGPS, tAHRS, tLog;
-
-    sensors.gps.reset_available();
-
-    // TODO: 3 move to main?
-    // Navigation
-
-    goGoGo = false;
-    navDone = false;
-    keypad.pressed = false;
-    //bool started = false;  // flag to indicate robot has exceeded min speed.
-    
-    if (initLogfile()) logStatus = 1; // Open the log file in sprintf format string style; numbers go in %d
-    wait(0.2);
-
-    sensors.gps.disableVerbose();
-    sensors.gps.enable();
-    //gps2.enable();
-
-    fputs("Press select button to start.\n", stdout);
-    display.status("Select starts.");
-    wait(1.0);
-    
-    timer.reset();
-    timer.start();
-    nextTelemUpdate = timer.read_ms();
-    wait(0.1);
-    
-    // Tell the navigation / position estimation stuff to reset to starting waypoint
-    // Disable 05/27/2013 to try and fix initial heading estimate
-    //restartNav();
-
-    // Main loop
-    //
-    while(navDone == false) {
-        //////////////////////////////////////////////////////////////////////////////
-        // USER INPUT
-        //////////////////////////////////////////////////////////////////////////////
-
-        // Button state machine
-        // if we've not started going, button starts us
-        // if we have started going, button stops us
-        // but only if we've released it first
-        //
-        // set throttle only if goGoGo set
-        if (goGoGo) {
-            // TODO: 2 Add additional condition of travel for N meters before the HALT button is armed
-            
-            if (keypad.pressed == true) { // && started
-                fputs(">>>>>>>>>>>>>>>>>>>>>>> HALT\n", stdout);
-                display.status("HALT.");
-                navDone = true;
-                goGoGo = false;
-                keypad.pressed = false;
-                endRun();
-            }
-        } else {
-            if (keypad.pressed == true) {
-                fputs(">>>>>>>>>>>>>>>>>>>>>>> GO GO GO\n", stdout);
-                display.status("GO GO GO!");
-                goGoGo = true;
-                keypad.pressed = false;
-                beginRun();
-            }
-        }        
-
-        // Are we at the last waypoint?
-        // 
-        if (fifo_first()->nextWaypoint == config.wptCount) {
-            fputs("Arrived at final destination.\n", stdout);
-            display.status("Arrived at end.");
-            navDone = true;
-            endRun();
-        }
-
-        //////////////////////////////////////////////////////////////////////////////
-        // TELEMETRY
-        //////////////////////////////////////////////////////////////////////////////
-        if (timer.read_ms() > nextTelemUpdate) {
-            SystemState *s = fifo_first();
-            telem.sendPacket(s); // TODO 4 run this out of timer interrupt
-            nextTelemUpdate += 200; // TODO 3 increase update speed
-        }
-
-        //////////////////////////////////////////////////////////////////////////////
-        // LOGGING
-        //////////////////////////////////////////////////////////////////////////////
-        // sensor reads are happening in the schedHandler();
-        // Are there more items to come out of the log fifo?
-        // Since this could take anywhere from a few hundred usec to
-        // 150ms, we run it opportunistically and use a buffer. That way
-        // the sensor updates, calculation, and control can continue to happen
-        if (fifo_available()) {
-            logStatus = !logStatus;         // log indicator LED
-            logData( fifo_pull() );         // log state data to file
-            logStatus = !logStatus;         // log indicator LED
-        }
-
-    } // while
-    closeLogfile();
-    wait(2.0);
-    logStatus = 0;
-    display.status("Completed. Saved.");
-    wait(2.0);
-
-    updaterStatus = 0;
-    gpsStatus = 0;
-    //confStatus = 0;
-    //flasher = 0;
-
-    sensors.gps.disableVerbose();
-
-    return 0;
-} // autonomousMode
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-// UTILITY FUNCTIONS
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// Gather gyro data using turntable equipped with dual channel
-// encoder. Use onboard wheel encoder system. Left channel
-// is the index (0 degree) mark, while the right channel
-// is the incremental encoder.  Can then compare gyro integrated
-// heading with machine-reported heading
-//
-int gyroSwing()
-{
-    FILE *fp;
-    int now;
-    int next;
-    int g[3];
-    int leftTotal=0;
-    int rightTotal=0;
-
-    // Timing is pretty critical so just in case, disable serial processing from GPS
-    sensors.gps.disable();
-    stopUpdater();
-
-    fputs("Starting gyro swing...\n", stdout);
-    display.status("Starting...");
-//    fp = openlog("gy");
-    fp = stdout;
-
-    display.status("Rotate clockwise.");
-    fputs("Begin clockwise rotation, varying rpm\n", stdout);
-    wait(1);
-
-    display.status("Select exits.");
-    fputs("Press select to exit\n", stdout);
-    wait(1);
-
-
-    timer.reset();
-    timer.start();
-
-    next = now = timer.read_ms();
-
-    sensors._right.read();  // easiest way to reset the heading counter
-    sensors._left.read();
-    
-    while (1) {
-        now = timer.read_ms();
-
-        if (keypad.pressed) {
-            keypad.pressed = false;
-            break;
-        }
-
-        if (now >= next) {
-            leftTotal += sensors._left.read();
-            rightTotal += sensors._right.read();
-            sensors._gyro.read(g);
-            fputs(cvitos(now), fp);
-            fputs(" ", fp);
-            fputs(cvntos(leftTotal), fp);
-            fputs(" ", fp);
-            fputs(cvntos(rightTotal), fp);
-            fputs(" ", fp);
-            fputs(cvitos(g[_z_]), fp);
-            fputs("\n", fp);
-            next = now + 50;
-        }
-    }    
-    if (fp && fp != stdout) {
-        fclose(fp);
-        display.status("Done. Saved.");
-        fputs("Data collection complete.\n", stdout);
-        wait(2);
-    }
-
-    sensors.gps.enable();
-    restartNav();
-    startUpdater();
-    
-    keypad.pressed = false;
-
-    return 0;
-}
-
-
-
-void bridgeRecv()
-{
-#if 0
-    while (dev && dev->readable()) {
-        pc.putc(dev->getc());
-    }
-#endif
-}
-
-
-void serialBridge(Serial &serial)
-{
-#if 0
-    char x;
-    int count = 0;
-    bool done=false;
-
-    fputs("\nEntering serial bridge in 2 seconds, +++ to escape\n\n", stdout);
-    sensors.gps.enableVerbose();
-    wait(2.0);
-    //dev = &gps;
-    sensors.gps.disable();
-    serial.baud(38400);
-    while (!done) {
-        if (pc.readable()) {
-            x = pc.getc();
-            serial.putc(x);
-            // escape sequence
-            if (x == '+') {
-                if (++count >= 3) done=true;
-            } else {
-                count = 0;
-            }
-        }
-        if (serial.readable()) {
-            fputc(serial.getc(), stdout);
-        }
-    }
-#endif
-}
-
-
-int setBacklight(void) {
-    Menu bmenu;
-    bool done = false;
-    bool printUpdate = false;
-    static int backlight=100;
-    
-    display.select(">> Backlight");
-
-    while (!done) {
-        if (keypad.pressed) {
-            keypad.pressed = false;
-            printUpdate = true;
-            switch (keypad.which) {
-                case NEXT_BUTTON:
-                    backlight+=5;
-                    if (backlight > 100) backlight = 100;
-                    lcd.backlight(backlight);
-                    break;
-                case PREV_BUTTON:
-                    backlight-=5;
-                    if (backlight < 0) backlight = 0;
-                    lcd.backlight(backlight);
-                    break;
-                case SELECT_BUTTON:
-                    done = true;
-                    break;    
-            }
-        }
-        if (printUpdate) {
-            printUpdate = false;
-            lcd.pos(0,1);
-            // TODO 3 lcd.printf("%3d%%%-16s", backlight, "");
-        }
-    }
-    
-    return 0;
-}
-
-int reverseScreen(void) {
-    lcd.reverseMode();
-    
-    return 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-// ADC CONVERSION FUNCTIONS
-///////////////////////////////////////////////////////////////////////////////////////////////////////
-
-// returns distance in m for Sharp GP2YOA710K0F
-// to get m and b, I wrote down volt vs. dist by eyeballin the
-// datasheet chart plot. Then used Excel to do linear regression
-//
-float irDistance(const unsigned int adc)
-{
-    float b = 1.0934; // Intercept from Excel
-    float m = 1.4088; // Slope from Excel
-
-    return m / (((float) adc) * 4.95/4096 - b);
-}
--- a/updater.cpp	Thu Nov 29 18:34:22 2018 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,577 +0,0 @@
-#include "mbed.h"
-#include "util.h"
-#include "globals.h"
-#include "updater.h"
-#include "Config.h"
-#include "Actuators.h"
-#include "Sensors.h"
-#include "SystemState.h"
-#include "Venus638flpx.h"
-//#include "Ublox6.h"
-#include "Steering.h"
-#include "Servo.h"
-#include "Mapping.h"
-#include "CartPosition.h"
-#include "GeoPosition.h"
-#include "kalman.h"
-
-#define UPDATE_PERIOD 0.010             // update period in s
-
-#define _x_ 0
-#define _y_ 1
-#define _z_ 2
-
-// The below is for main loop at 50ms = 20hz operation
-//#define CTRL_SKIP 2 // 100ms, 10hz, control update
-//#define MAG_SKIP 1  // 50ms, 20hz, magnetometer update
-//#define LOG_SKIP 1  // 50ms, 20hz, log entry entered into fifo
-
-// The following is for main loop at 10ms = 100hz
-#define HDG_LAG 40      // Number of update steps that the GPS report is behind realtime
-#define CTRL_SKIP 5     // 50ms (20hz), control update
-#define MAG_SKIP 2      // 20ms (50hz), magnetometer update
-#define LOG_SKIP 2      // 20ms (50hz), log entry entered into fifo
-//#define LOG_SKIP 5    // 50ms (20hz), log entry entered into fifo
-
-Ticker sched;                           // scheduler for interrupt driven routines
-
-int control_count=CTRL_SKIP;
-int update_count=MAG_SKIP;              // call Update_mag() every update_count calls to schedHandler()
-int log_count=0;                        // buffer a new status entry for logging every log_count calls to schedHandler
-int tReal;                              // calculate real elapsed time
-int bufCount=0;
-
-extern DigitalOut gpsStatus;
-
-// TODO: 3 better encapsulation, please
-extern Sensors sensors;
-extern SystemState state[SSBUF];
-extern unsigned char inState;
-extern unsigned char outState;
-extern bool ssBufOverrun;
-extern Mapping mapper;
-extern Steering steerCalc;              // steering calculator
-extern Timer timer;
-extern DigitalOut ahrsStatus;           // AHRS status LED
-
-// Navigation
-extern Config config;
-int nextWaypoint = 0;                   // next waypoint destination
-int lastWaypoint = 1;
-double bearing;                         // bearing to next waypoint
-double distance;                        // distance to next waypoint
-float steerAngle;                       // steering angle
-
-// Throttle PID
-float speedDt=0;                        // dt for the speed PID
-float integral=0;                       // error integral for speed PID
-float lastError=0;                      // previous error, used for calculating derivative
-bool go=false;                          // initiate throttle (or not)
-float desiredSpeed;                     // speed set point
-float nowSpeed;
-
-// Pose Estimation
-bool initNav = true;                    // initialize navigation estimates
-bool doLog = false;                     // determines when to start and stop entering log data
-float initialHeading=-999;              // initial heading
-CartPosition cartHere;                  // position estimate, cartesian
-GeoPosition here;                       // position estimate, lat/lon
-int timeZero=0;
-int lastTime=-1;                        // used to calculate dt for KF
-int thisTime;                           // used to calculate dt for KF
-float dt;                               // dt for the KF
-float estLagHeading = 0;                   // lagged heading estimate
-//GeoPosition lagHere;                  // lagged position estimate; use here as the current position estimate
-float errHeading;                         // error between gyro hdg estimate and gps hdg estimate
-float gyroBias=0;                       // exponentially weighted moving average of gyro error
-float Ag = (2.0/(1000.0+1.0));          // Gyro bias filter alpha, gyro; # of 10ms steps
-float Kbias = 0.995;            
-float filtErrRate = 0;
-float biasErrAngle = 0;
-
-#define MAXHIST 128 // must be multiple of 0x08
-#define inc(x)  (x) = ((x)+1)&(MAXHIST-1)
-struct history_rec {
-    float x;        // x coordinate
-    float y;        // y coordinate
-    float hdg;      // heading
-    float dist;     // distance
-    float gyro;     // heading rate
-    //float ghdg;   // uncorrected gyro heading
-    float dt;       // delta time
-} history[MAXHIST]; // fifo for sensor data, position, heading, dt
-
-int hCount;         // history counter; one > HDG_LAG, we can go back in time to reference gyro history
-int now = 0;        // fifo input index, latest entry
-int prev = 0;       // previous fifo iput index, next to latest entry
-int lag = 0;        // fifo output index, entry from 1 second ago (HDG_LAG entries prior)
-int lagPrev = 0;    // previous fifo output index, 101 entries prior
-
-/** attach update to Ticker */
-void startUpdater()
-{
-    // Initialize logging buffer
-    // Needs to happen after we've reset the millisecond timer and after
-    // the schedHandler() fires off at least once more with the new time
-    sched.attach(&update, UPDATE_PERIOD);
-}
-
-/** set flag to initialize navigation at next schedHandler() call */
-void restartNav()
-{
-    go = false;
-    inState = outState = 0;    
-    initNav = true;
-    return;
-}
-
-/** instruct the controller to start running */
-void beginRun()
-{
-    go = true;
-    inState = outState = 0;    
-    timeZero = thisTime; // initialize 
-    bufCount = 0;
-    return;
-}
-
-/** instruct the controller that we're done with the run */
-void endRun()
-{
-    go = false;
-    initNav = true;
-    return;
-}
-
-/** get elasped time in update loop */
-int getUpdateTime()
-{
-    return tReal;
-}
-
-/** Set the desired speed for the controller to attain */
-void setSpeed(float speed) 
-{
-    if (desiredSpeed != speed) {
-        desiredSpeed = speed;
-        integral = 0; // reset the error integral
-    }
-    return;
-}
-
-/** update() runs the data collection, estimation, steering control, and throttle control */
-void update()
-{
-    tReal = timer.read_us();
-    bool useGps=false;
-
-    // TODO 1 do we need to set up the dt stuff after initialization?
-
-    ahrsStatus = 0;
-    thisTime = timer.read_ms();
-    dt = (lastTime < 0) ? 0 : ((float) thisTime - (float) lastTime) / 1000.0; // first pass let dt=0
-    lastTime = thisTime;
-
-    // Add up dt to speedDt
-    // We're adding up distance over several update() calls so have to keep track of total time
-    speedDt += dt;
-    
-    // Log Data Timestamp    
-    int timestamp = timer.read_ms();
-
-    //////////////////////////////////////////////////////////////////////////////
-    // NAVIGATION INIT
-    //////////////////////////////////////////////////////////////////////////////
-    // initNav is set with call to restartNav() when the "go" button is pressed.  Up
-    // to 10ms later this function is called and the code below will initialize the
-    // dead reckoning position and estimated position variables
-    // 
-    if (initNav == true) {
-        initNav = false;
-        here.set(config.wpt[0]);
-        nextWaypoint = 1; // Point to the next waypoint; 0th wpt is the starting point
-        lastWaypoint = 0;
-        
-        // TODO 1 need to start off, briefly, at a slow speed
-        
-        // Initialize lag estimates
-        //lagHere.set( here );
-        hCount = 2; // lag entry and first now entry are two entries
-        now = 0; 
-        // initialize what will become lag data in 1 second from now
-        history[now].dt = 0;
-        history[now].dist = 0;
-        // initial position is waypoint 0
-        history[now].x = config.cwpt[0]._x;
-        history[now].y = config.cwpt[0]._y;
-        cartHere.set(history[now].x, history[now].y);
-        // initialize heading to bearing between waypoint 0 and 1
-        //history[now].hdg = here.bearingTo(config.wpt[nextWaypoint]);
-        initialHeading = history[now].hdg = cartHere.bearingTo(config.cwpt[nextWaypoint]);
-        //history[now].ghdg = history[now].hdg;
-        // Initialize Kalman Filter
-        headingKalmanInit(initialHeading);
-        // point next fifo input to slot 1, slot 0 occupied/initialized, now
-        lag = 0;
-        lagPrev = 0;
-        prev = now; // point to the most recently entered data
-        now = 1;    // new input slot
-    }
-
-
-    //////////////////////////////////////////////////////////////////////////////
-    // SENSOR UPDATES
-    //////////////////////////////////////////////////////////////////////////////
-
-    // TODO 3 This really should run infrequently
-    sensors.Read_Power();
-
-    sensors.Read_Encoders(); 
-    // really need to do some filtering on the speed
-    //nowSpeed = 0.8*nowSpeed + 0.2*sensors.encSpeed; 
-    nowSpeed = sensors.encSpeed;
-
-    sensors.Read_Gyro(); 
-
-    sensors.Read_Rangers();
-
-    sensors.Read_Accel();
-
-    //sensors.Read_Camera();
-
-    //////////////////////////////////////////////////////////////////////////////
-    // Obtain GPS data                        
-    //////////////////////////////////////////////////////////////////////////////
-
-    // synchronize when RMC and GGA sentences received w/ AHRS
-    // Do this in schedHandler??  GPS data is coming in not entirely in sync
-    // with the logging info
-    if (sensors.gps.available()) {
-        // update system status struct for logging
-        gpsStatus = !gpsStatus;
-        state[inState].gpsLatitude = sensors.gps.latitude();
-        state[inState].gpsLongitude = sensors.gps.longitude();
-        state[inState].gpsHDOP = sensors.gps.hdop();
-        state[inState].gpsCourse_deg = sensors.gps.heading_deg();
-        state[inState].gpsSpeed_mps = sensors.gps.speed_mps(); // if need to convert from mph to mps, use *0.44704
-        state[inState].gpsSats = sensors.gps.sat_count();
-        
-        // May 26, 2013, moved the useGps setting in here, so that we'd only use the GPS heading in the
-        // Kalman filter when it has just been received. Before this I had a bug where it was using the
-        // last known GPS data at every call to this function, meaning the more stale the GPS data, the more
-        // it would likely throw off the GPS/gyro error term. Hopefully this will be a tad more acccurate.
-        // Only an issue when heading is changing, I think.
-        
-        // GPS heading is unavailable from this particular GPS at speeds < 0.5 mph
-        // Also, best to only use GPS if we've got at least 4 sats active -- really should be like 5 or 6
-        // Finally, it takes 3-5 secs of runtime for the gps heading to converge.
-        useGps = (state[inState].gpsSats > 4 &&
-                  state[inState].lrEncSpeed > 1.0 &&
-                  state[inState].rrEncSpeed > 1.0 &&
-                  (thisTime-timeZero) > 3000); // gps hdg converges by 3-5 sec.                
-    }
-
-    DigitalOut useGpsStat(LED1);
-    useGpsStat = useGps;
-    
-    //////////////////////////////////////////////////////////////////////////////
-    // HEADING AND POSITION UPDATE
-    //////////////////////////////////////////////////////////////////////////////
-
-    // TODO: 2 Position filtering
-    //    position will be updated based on heading error from heading estimate
-    // TODO: 2 Distance/speed filtering
-    //    this might be useful, but not sure it's worth the effort
-
-    // So the big pain in the ass is that the GPS data coming in represents the
-    // state of the system ~1s ago. Yes, a full second of lag despite running
-    // at 10hz (or whatever).  So if we try and fuse a lagged gps heading with a
-    // relatively current gyro heading rate, the gyro is ignored and the heading
-    // estimate lags reality
-    //
-    // In real life testing, the robot steering control was highly unstable with
-    // too much gain (typical of any negative feedback system with a very high
-    // phase shift and too much feedback). It'd drive around in circles trying to
-    // hunt for the next waypoint.  Dropping the gain restored stability but the
-    // steering overshot significantly, because of the lag.  It sort of worked but
-    // it was ugly. So here's my lame attempt to fix all this. 
-    // 
-    // We'll find out how much error there is between gps heading and the integrated
-    // gyro heading from a second ago.
-
-    // Save current data into history fifo to use 1 second from now
-    history[now].dist = (sensors.lrEncDistance + sensors.rrEncDistance) / 2.0; // current distance traveled
-    history[now].gyro = sensors.gyro[_z_];  // current raw gyro data
-    history[now].dt = dt; // current dt, to address jitter
-    history[now].hdg = clamp360( history[prev].hdg + dt*(history[now].gyro - gyroBias) ); // compute current heading from current gyro
-    float r = PI/180 * history[now].hdg;
-    history[now].x = history[prev].x + history[now].dist * sin(r);    // update current position
-    history[now].y = history[prev].y + history[now].dist * cos(r);
-
-    // We can't do anything until the history buffer is full
-    if (hCount < HDG_LAG) {
-        estLagHeading = history[now].hdg;
-        // Until the fifo is full, only keep track of current gyro heading
-        hCount++; // after n iterations the fifo will be full
-    } else {
-        // Now that the buffer is full, we'll maintain a Kalman Filter estimate that is
-        // time-shifted to the past because the GPS output represents the system state from
-        // the past. We'll also correct our history of gyro readings from the past to the
-        // present
-        
-        ////////////////////////////////////////////////////////////////////////////////
-        // UPDATE LAGGED ESTIMATE
-        
-        // Recover data from 1 second ago which will be used to generate
-        // updated lag estimates
-
-        // This represents the best estimate for heading... for one second ago
-        // If we do nothing else, the robot will think it is located at a position 1 second behind
-        // where it actually is. That means that any control feedback needs to have a longer time
-        // constant than 1 sec or the robot will have unstable heading correction.
-        // Use gps data when available, always use gyro data
-
-        // Clamp heading to initial heading when we're not moving; hopefully this will
-        // give the KF a head start figuring out how to deal with the gyro
-        //
-        // TODO 1 maybe we should only call the gps version after moving
-        if (go) {
-            estLagHeading = headingKalman(history[lag].dt, state[inState].gpsCourse_deg, useGps, history[lag].gyro, true);
-        } else {    
-            estLagHeading = headingKalman(history[lag].dt, initialHeading, true, history[lag].gyro, true);
-        }
-
-        // TODO 1 are we adding history lag to lagprev or should we add lag+1 to lag or what?
-        // Update the lagged position estimate
-        history[lag].x = history[lagPrev].x + history[lag].dist * sin(estLagHeading);
-        history[lag].y = history[lagPrev].y + history[lag].dist * cos(estLagHeading);
-        
-        ////////////////////////////////////////////////////////////////////////////////
-        // UPDATE CURRENT ESTIMATE
-
-        // Now we need to re-calculate the current heading and position, starting with the most recent
-        // heading estimate representing the heading 1 second ago.
-        //        
-        // Nuance: lag and now have already been incremented so that works out beautifully for this loop
-        //
-        // Heading is easy. Original heading - estimated heading gives a tiny error. Add this to all the historical
-        // heading data up to present.
-        //
-        // For position re-calculation, we iterate HDG_LAG times up to present record. Haversine is way, way too slow,
-        // trig calcs is marginal. Update rate is 10ms and we can't hog more than maybe 2-3ms as the outer
-        // loop has logging work to do. Rotating each point is faster; pre-calculate sin/cos, etc. for rotation
-        // matrix.
-
-        // Low pass filter the error correction.  Multiplying by 0.01, it takes HDG_LAG updates to correct a 
-        // consistent error; that's 0.10s/0.01 = 1 sec.  0.005 is 2 sec, 0.0025 is 4 sec, etc.
-        errHeading = clamp180(estLagHeading - history[lag].hdg) * 0.01;  // lopass filter error angle
-
-        //fprintf(stdout, "%d %.2f, %.2f, %.4f %.4f\n", lag, estLagHeading, history[lag].hdg, estLagHeading - history[lag].hdg, errHeading);
-        float cosA = cos(errHeading * PI / 180.0);
-        float sinA = sin(errHeading * PI / 180.0);
-        // Update position & heading from history[lag] through history[now]
-        int i = lag;
-        // TODO 2 parameterize heading lag -- for uBlox it seems to be ~ 600ms, for Venus, about 1000ms
-        for (int j=0; j < HDG_LAG; j++) {
-            //fprintf(stdout, "i=%d n=%d l=%d\n", i, now, lag);
-            // Correct gyro-calculated headings from past to present including history[lag].hdg
-            history[i].hdg = clamp360(history[i].hdg + errHeading);
-            //if (history[i].hdg >= 360.0) history[i].hdg -= 360.0;
-            //if (history[i].hdg < 0) history[i].hdg += 360.0;
-            // Rotate x, y by errHeading around pivot point; no need to rotate pivot point (j=0)
-            if (j > 0) {
-                float dx = history[i].x-history[lag].x;
-                float dy = history[i].y-history[lag].y;
-                // rotation matrix
-                history[i].x = history[lag].x + dx*cosA - dy*sinA;
-                history[i].y = history[lag].y + dx*sinA + dy*cosA;
-            }
-            inc(i);
-        }
-        // increment lag pointer and wrap        
-        lagPrev = lag;
-        inc(lag);
-    }
-    // "here" is the current position
-    cartHere.set(history[now].x, history[now].y);
-
-    //////////////////////////////////////////////////////////////////////////////
-    // NAVIGATION UPDATE
-    //////////////////////////////////////////////////////////////////////////////
-    
-    bearing = cartHere.bearingTo(config.cwpt[nextWaypoint]);
-    distance = cartHere.distanceTo(config.cwpt[nextWaypoint]);
-    float prevDistance = cartHere.distanceTo(config.cwpt[lastWaypoint]);
-
-    // if within config.waypointDist distance threshold move to next waypoint
-    // TODO 3 figure out how to output feedback on wpt arrival external to this function
-    if (go) {
-
-        // if we're within brakeDist of next or previous waypoint, run @ turn speed
-        // This would normally mean we run at turn speed until we're brakeDist away
-        // from waypoint 0, but we trick the algorithm by initializing prevWaypoint to waypoint 1
-        if ( (thisTime - timeZero) < 3000 ) {
-            setSpeed( config.startSpeed );
-        } else if (distance < config.brakeDist || prevDistance < config.brakeDist) {
-            setSpeed( config.turnSpeed );
-        } else {
-            setSpeed( config.topSpeed );
-        }
-
-        if (distance < config.waypointDist) {
-            //fprintf(stdout, "Arrived at wpt %d\n", nextWaypoint);
-            //speaker.beep(3000.0, 0.5); // non-blocking
-            lastWaypoint = nextWaypoint;
-            nextWaypoint++;
-        }
-        
-    } else {
-        setSpeed( 0.0 );
-    }
-    // Are we at the last waypoint?
-    // currently handled external to this routine
-        
-    //////////////////////////////////////////////////////////////////////////////
-    // OBSTACLE DETECTION & AVOIDANCE
-    //////////////////////////////////////////////////////////////////////////////
-    // TODO 2 limit steering angle based on object detection ?
-    // or limit relative brg perhaps?
-    // TODO 2 add vision obstacle detection and filtering
-    // TODO 2 add ranger obstacle detection and filtering/fusion with vision
-
-
-    //////////////////////////////////////////////////////////////////////////////
-    // CONTROL UPDATE
-    //////////////////////////////////////////////////////////////////////////////
-
-    if (--control_count == 0) {
-  
-        steerAngle = steerCalc.pathPursuitSA(history[now].hdg, history[now].x, history[now].y,
-                                             config.cwpt[lastWaypoint]._x, config.cwpt[lastWaypoint]._y,
-                                             config.cwpt[nextWaypoint]._x, config.cwpt[nextWaypoint]._y);
-        
-        // Apply gain factor for near straight line
-        // TODO 3 figure out a better, continuous way to deal with steering gain
-        if (fabs(steerAngle) < config.steerGainAngle) steerAngle *= config.steerGain;
-
-        // Curb avoidance
-        /*
-        if (sensors.rightRanger < config.curbThreshold) {
-            steerAngle -= config.curbGain * (config.curbThreshold - sensors.rightRanger);
-        }
-        */
-                    
-        setSteering( steerAngle );
-
-        // PID control for throttle
-        // TODO: 3 move all this PID crap into Actuators.cpp
-        // TODO: 3 probably should do KF or something for speed/dist; need to address GPS lag, too
-        // if nothing else, at least average the encoder speed over mult. samples
-        if (desiredSpeed <= 0.1) {
-            setThrottle( config.escZero );
-        } else {
-            // PID loop for throttle control
-            // http://www.codeproject.com/Articles/36459/PID-process-control-a-Cruise-Control-example
-            float error = desiredSpeed - nowSpeed; 
-            // track error over time, scaled to the timer interval
-            integral += (error * speedDt);
-            // determine the amount of change from the last time checked
-            float derivative = (error - lastError) / speedDt; 
-            // calculate how much to drive the output in order to get to the 
-            // desired setpoint. 
-            int output = config.escZero + (config.speedKp * error) + (config.speedKi * integral) + (config.speedKd * derivative);
-            if (output > config.escMax) output = config.escMax;
-            if (output < config.escMin) output = config.escMin;
-            //fprintf(stdout, "s=%.1f d=%.1f o=%d\n", nowSpeed, desiredSpeed, output);
-            setThrottle( output );
-            // remember the error for the next time around.
-            lastError = error; 
-        }
-
-        speedDt = 0; // reset dt to begin counting for next time
-        control_count = CTRL_SKIP;
-    }      
-
-    //////////////////////////////////////////////////////////////////////////////
-    // DATA FOR LOGGING
-    //////////////////////////////////////////////////////////////////////////////
-
-    // Periodically, we enter a new SystemState into the FIFO buffer
-    // The main loop handles logging and will catch up to us provided 
-    // we feed in new log entries slowly enough.
-    // log_count initialized to 0 to begin with forcing initialization below
-    // but no further updates until in go mode
-    if (go && (log_count > 0)) --log_count;
-    // Only enter new SystemState data when in "go" mode (armed to run, run,
-    // and end run)
-    // We should really only be adding to the state fifo if we're in 'go' mode
-    if (log_count <= 0) {
-        // Copy data into system state for logging
-        inState++;                      // Get next state struct in the buffer
-        inState &= SSBUF;               // Wrap around
-        ssBufOverrun = (inState == outState);
-        // Need to clear out encoder distance counters; these are incremented
-        // each time this routine is called.
-        // TODO 1 is there anything we can't clear out?
-        // TODO 1 use clearState()
-        state[inState].lrEncDistance = 0;
-        state[inState].rrEncDistance = 0;
-        // initialize gps data
-        state[inState].gpsLatitude = 0;
-        state[inState].gpsLongitude = 0;
-        state[inState].gpsHDOP = 0;
-        state[inState].gpsCourse_deg = 0;
-        state[inState].gpsSpeed_mps = 0;
-        state[inState].gpsSats = 0;
-        log_count = LOG_SKIP;       // reset counter
-        bufCount++;
-    }
-
-    // Log Data Timestamp    
-    state[inState].millis = timestamp;
-
-    // TODO: 3 recursive filtering on each of the state values
-    state[inState].voltage = sensors.voltage;
-    state[inState].current = sensors.current;
-    for (int i=0; i < 3; i++) {
-        state[inState].m[i] = sensors.m[i];
-        state[inState].g[i] = sensors.g[i];
-        state[inState].gyro[i] = sensors.gyro[i];
-        state[inState].a[i] = sensors.a[i];
-    }
-    state[inState].gTemp = sensors.gTemp;
-    state[inState].lrEncSpeed = sensors.lrEncSpeed;
-    state[inState].rrEncSpeed = sensors.rrEncSpeed;
-    state[inState].lrEncDistance += sensors.lrEncDistance;
-    state[inState].rrEncDistance += sensors.rrEncDistance;
-    //state[inState].encHeading += (state[inState].lrEncDistance - state[inState].rrEncDistance) / TRACK;
-    state[inState].estHeading = history[now].hdg; // gyro heading estimate, current, corrected
-    state[inState].estLagHeading = history[lag].hdg; // gyro heading, estimate, lagged
-    mapper.cartToGeo(cartHere, &here);
-    state[inState].estLatitude = here.latitude();
-    state[inState].estLongitude = here.longitude();
-    state[inState].estX = history[now].x;
-    state[inState].estY = history[now].y;
-    state[inState].bearing = bearing;
-    state[inState].distance = distance;
-    state[inState].nextWaypoint = nextWaypoint;
-    state[inState].gbias = gyroBias;
-    state[inState].errHeading = errHeading;
-    //state[inState].leftRanger = sensors.leftRanger;
-    //state[inState].rightRanger = sensors.rightRanger;
-    //state[inState].centerRanger = sensors.centerRanger;
-    state[inState].steerAngle = steerAngle;
-    // Copy AHRS data into logging data
-    //state[inState].roll = ToDeg(ahrs.roll);
-    //state[inState].pitch = ToDeg(ahrs.pitch);
-    //state[inState].yaw = ToDeg(ahrs.yaw);
-
-    // increment fifo pointers with wrap-around
-    prev = now;
-    inc(now);
-
-    // timing
-    tReal = timer.read_us() - tReal;
-
-    ahrsStatus = 1;
-}
\ No newline at end of file
--- a/updater.h	Thu Nov 29 18:34:22 2018 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-#ifndef __SCHEDULER_H
-#define __SCHEDULER_H
-
-/** Updater is the main real time sensor update, estimation, and control routine that is
- * called at 100Hz by a timer interrupt
- */
-
-/** initialize throttle to center position */
-void initThrottle(void);
-
-/** initialize steering to center position */
-void initSteering(void);
-
-/** attach the update routine to Ticker interrupt */
-void startUpdater(void);
-
-/** detach the update routine from Ticker interrupt */
-void stopUpdater(void);
-
-/** Returns the elapsed time taken by the updater routine on its most recent run */
-int getUpdateTime(void);
-
-/** Indicates to the updater that the vehicle should begin its run */
-void beginRun(void);
-
-/** Indicates to the updater that the vehicle should abort its run */
-void endRun(void);
-
-/** Tells the updater to re-initialize the navigation state */
-void restartNav(void);
-
-/** Sets the desired speed of the rover */
-void setSpeed(float speed);
-
-/** Sets the steering angle */
-void setSteering(float steerAngle);
-
-/** The function that is called at 100Hz. It reads sensors, performs estimation, and controls the robot */
-void update(void);
-
-#endif