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

Committer:
shimniok
Date:
Tue May 28 13:58:35 2013 +0000
Revision:
1:cb84b477886c
Parent:
0:a6a169de725f
Child:
2:fbc6e3cf3ed8
Changed initial next/prev waypoint to permit steering calc. Removed unnecessary code, added logging for steering angle to diagnose bug.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shimniok 0:a6a169de725f 1 #include "logging.h"
shimniok 0:a6a169de725f 2 #include "SDHCFileSystem.h"
shimniok 0:a6a169de725f 3 #include "SerialGraphicLCD.h"
shimniok 0:a6a169de725f 4 #include "b64.h"
shimniok 0:a6a169de725f 5
shimniok 0:a6a169de725f 6 extern Serial pc;
shimniok 0:a6a169de725f 7 extern SerialGraphicLCD lcd;
shimniok 0:a6a169de725f 8
shimniok 0:a6a169de725f 9 SDFileSystem sd(p5, p6, p7, p8, "log"); // mosi, miso, sclk, cs
shimniok 0:a6a169de725f 10 static FILE *logp;
shimniok 0:a6a169de725f 11
shimniok 0:a6a169de725f 12 void clearState( SystemState *s )
shimniok 0:a6a169de725f 13 {
shimniok 0:a6a169de725f 14 s->millis = 0;
shimniok 0:a6a169de725f 15 s->current = s->voltage = 0.0;
shimniok 0:a6a169de725f 16 s->g[0] = s->g[1] = s->g[2] = 0;
shimniok 0:a6a169de725f 17 s->gTemp = 0;
shimniok 0:a6a169de725f 18 s->a[0] = s->a[1] = s->a[2] = 0;
shimniok 0:a6a169de725f 19 s->m[0] = s->m[1] = s->m[2] = 0;
shimniok 0:a6a169de725f 20 s->gHeading = s->cHeading = 0.0;
shimniok 0:a6a169de725f 21 //s->roll = s->pitch = s->yaw =0.0;
shimniok 0:a6a169de725f 22 s->gpsLatitude = s->gpsLongitude = s->gpsCourse_deg = s->gpsSpeed_mps = s->gpsHDOP = 0.0;
shimniok 1:cb84b477886c 23 //s->gpsLatitude2 = s->gpsLongitude2 = s->gpsCourse_deg2 = s->gpsSpeed_mps2 = s->gpsHDOP2 = 0.0;
shimniok 0:a6a169de725f 24 s->lrEncDistance = s->rrEncDistance = 0.0;
shimniok 0:a6a169de725f 25 s->lrEncSpeed = s->rrEncSpeed = s->encHeading = 0.0;
shimniok 0:a6a169de725f 26 s->estHeading = s->estLatitude = s->estLongitude = 0.0;
shimniok 0:a6a169de725f 27 //s->estNorthing = s->estEasting =
shimniok 0:a6a169de725f 28 s->estX = s->estY = 0.0;
shimniok 0:a6a169de725f 29 s->nextWaypoint = 0;
shimniok 0:a6a169de725f 30 s->bearing = s->distance = 0.0;
shimniok 0:a6a169de725f 31 }
shimniok 0:a6a169de725f 32
shimniok 0:a6a169de725f 33 Timer logtimer;
shimniok 0:a6a169de725f 34 extern int bufCount;
shimniok 0:a6a169de725f 35
shimniok 0:a6a169de725f 36 /*
shimniok 0:a6a169de725f 37 void logData( const SystemState s ) {
shimniok 0:a6a169de725f 38 unsigned char buf[512]; // for now we really only need ~256 bytes but in case I add more to state...
shimniok 0:a6a169de725f 39 unsigned char *state = (unsigned char *) &s;
shimniok 0:a6a169de725f 40 //unsigned int t1, t2, t3;
shimniok 0:a6a169de725f 41 //logtimer.start();
shimniok 0:a6a169de725f 42 //logtimer.reset();
shimniok 0:a6a169de725f 43 if (logp) {
shimniok 0:a6a169de725f 44 //t1 = logtimer.read_us();
shimniok 0:a6a169de725f 45 encode(state, sizeof(s), buf, 0); // infinite line size
shimniok 0:a6a169de725f 46 //t2 = logtimer.read_us();
shimniok 0:a6a169de725f 47 fputs((char *) buf, logp);
shimniok 0:a6a169de725f 48 fputs("\n", logp);
shimniok 0:a6a169de725f 49 bufCount--;
shimniok 0:a6a169de725f 50 fprintf(stdout, "bufCount: %d\n", bufCount);
shimniok 0:a6a169de725f 51 //t3 = logtimer.read_us();
shimniok 0:a6a169de725f 52 //fprintf(stdout, "%d %d\n", t3-t2, t2-t1);
shimniok 0:a6a169de725f 53 }
shimniok 0:a6a169de725f 54 }
shimniok 0:a6a169de725f 55 */
shimniok 0:a6a169de725f 56
shimniok 0:a6a169de725f 57 // from Arduino source
shimniok 0:a6a169de725f 58 size_t printNumber(FILE *f, unsigned long n)
shimniok 0:a6a169de725f 59 {
shimniok 0:a6a169de725f 60 char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
shimniok 0:a6a169de725f 61 char *str = &buf[sizeof(buf) - 1];
shimniok 0:a6a169de725f 62
shimniok 0:a6a169de725f 63 *str = '\0';
shimniok 0:a6a169de725f 64
shimniok 0:a6a169de725f 65 do {
shimniok 0:a6a169de725f 66 unsigned long m = n;
shimniok 0:a6a169de725f 67 n /= 10;
shimniok 0:a6a169de725f 68 char c = m - 10 * n;
shimniok 0:a6a169de725f 69 *--str = c + '0';
shimniok 0:a6a169de725f 70 } while(n);
shimniok 0:a6a169de725f 71
shimniok 0:a6a169de725f 72 return fputs(str, f);
shimniok 0:a6a169de725f 73 }
shimniok 0:a6a169de725f 74
shimniok 0:a6a169de725f 75 // from Arduino source
shimniok 0:a6a169de725f 76 size_t printInt(FILE *f, long n)
shimniok 0:a6a169de725f 77 {
shimniok 0:a6a169de725f 78 int t = 0;
shimniok 0:a6a169de725f 79 if (n < 0) {
shimniok 0:a6a169de725f 80 t = fputc('-', f);
shimniok 0:a6a169de725f 81 n = -n;
shimniok 0:a6a169de725f 82 }
shimniok 0:a6a169de725f 83 return printNumber(f, n) + t;
shimniok 0:a6a169de725f 84 }
shimniok 0:a6a169de725f 85
shimniok 0:a6a169de725f 86 // from Arduino source
shimniok 0:a6a169de725f 87 size_t printFloat(FILE *f, double number, uint8_t digits)
shimniok 0:a6a169de725f 88 {
shimniok 0:a6a169de725f 89 size_t n=0;
shimniok 0:a6a169de725f 90
shimniok 0:a6a169de725f 91 if (isnan(number)) return fputs("nan", f);
shimniok 0:a6a169de725f 92 if (isinf(number)) return fputs("inf", f);
shimniok 0:a6a169de725f 93 if (number > 4294967040.0) return fputs("ovf", f); // constant determined empirically
shimniok 0:a6a169de725f 94 if (number <-4294967040.0) return fputs("ovf", f); // constant determined empirically
shimniok 0:a6a169de725f 95
shimniok 0:a6a169de725f 96 // Handle negative numbers
shimniok 0:a6a169de725f 97 if (number < 0.0) {
shimniok 0:a6a169de725f 98 n += fputc('-', f);
shimniok 0:a6a169de725f 99 number = -number;
shimniok 0:a6a169de725f 100 }
shimniok 0:a6a169de725f 101
shimniok 0:a6a169de725f 102 // Round correctly so that print(1.999, 2) prints as "2.00"
shimniok 0:a6a169de725f 103 double rounding = 0.5;
shimniok 0:a6a169de725f 104 for (uint8_t i=0; i < digits; ++i)
shimniok 0:a6a169de725f 105 rounding /= 10.0;
shimniok 0:a6a169de725f 106
shimniok 0:a6a169de725f 107 number += rounding;
shimniok 0:a6a169de725f 108
shimniok 0:a6a169de725f 109 // Extract the integer part of the number and print it
shimniok 0:a6a169de725f 110 unsigned long int_part = (unsigned long)number;
shimniok 0:a6a169de725f 111 double remainder = number - (double)int_part;
shimniok 0:a6a169de725f 112 n += printInt(f, int_part);
shimniok 0:a6a169de725f 113
shimniok 0:a6a169de725f 114 // Print the decimal point, but only if there are digits beyond
shimniok 0:a6a169de725f 115 if (digits > 0) {
shimniok 0:a6a169de725f 116 n += fputc('.', f);
shimniok 0:a6a169de725f 117 }
shimniok 0:a6a169de725f 118
shimniok 0:a6a169de725f 119 // Extract digits from the remainder one at a time
shimniok 0:a6a169de725f 120 while (digits-- > 0) {
shimniok 0:a6a169de725f 121 remainder *= 10.0;
shimniok 0:a6a169de725f 122 int toPrint = int(remainder);
shimniok 0:a6a169de725f 123 n += fputc(toPrint+'0', f);
shimniok 0:a6a169de725f 124 remainder -= toPrint;
shimniok 0:a6a169de725f 125 }
shimniok 0:a6a169de725f 126
shimniok 0:a6a169de725f 127 return n;
shimniok 0:a6a169de725f 128 }
shimniok 0:a6a169de725f 129
shimniok 0:a6a169de725f 130
shimniok 0:a6a169de725f 131 // If I use arduino style print routines, logging takes ~1000 / ~8000 usec
shimniok 0:a6a169de725f 132 // the big sprintf takes ~ 700-750 usec all by itself
shimniok 0:a6a169de725f 133 void logData( const SystemState s )
shimniok 0:a6a169de725f 134 {
shimniok 0:a6a169de725f 135 //char buf[256];
shimniok 0:a6a169de725f 136 unsigned int t1, t2;
shimniok 0:a6a169de725f 137 logtimer.start();
shimniok 0:a6a169de725f 138 logtimer.reset();
shimniok 0:a6a169de725f 139 t1 = logtimer.read_us();
shimniok 0:a6a169de725f 140 printInt(logp, s.millis);
shimniok 0:a6a169de725f 141 fputc(',',logp);
shimniok 0:a6a169de725f 142 printFloat(logp, s.current, 2);
shimniok 0:a6a169de725f 143 fputc(',',logp);
shimniok 0:a6a169de725f 144 printFloat(logp, s.voltage, 2);
shimniok 0:a6a169de725f 145 fputc(',',logp);
shimniok 0:a6a169de725f 146 for (int q=0; q < 3; q++) {
shimniok 0:a6a169de725f 147 printInt(logp, s.g[q]);
shimniok 0:a6a169de725f 148 fputc(',',logp);
shimniok 0:a6a169de725f 149 }
shimniok 0:a6a169de725f 150 printInt(logp, s.gTemp);
shimniok 0:a6a169de725f 151 fputc(',',logp);
shimniok 0:a6a169de725f 152 for (int q=0; q < 3; q++) {
shimniok 0:a6a169de725f 153 printInt(logp, s.a[q]);
shimniok 0:a6a169de725f 154 fputc(',',logp);
shimniok 0:a6a169de725f 155 }
shimniok 0:a6a169de725f 156 /*
shimniok 0:a6a169de725f 157 for (int q=0; q < 3; q++) {
shimniok 0:a6a169de725f 158 printInt(logp, s.m[q]);
shimniok 0:a6a169de725f 159 fputc(',',logp);
shimniok 0:a6a169de725f 160 }
shimniok 0:a6a169de725f 161 */
shimniok 0:a6a169de725f 162 printFloat(logp, s.gHeading, 2);
shimniok 0:a6a169de725f 163 fputc(',',logp);
shimniok 0:a6a169de725f 164
shimniok 0:a6a169de725f 165 // GPS 1
shimniok 0:a6a169de725f 166 fprintf(logp, "%.7f,%.7f,", s.gpsLatitude, s.gpsLongitude);
shimniok 0:a6a169de725f 167 //printFloat(logp, s.gpsLatitude, 7);
shimniok 0:a6a169de725f 168 //fputc(',',logp);
shimniok 0:a6a169de725f 169 //printFloat(logp, s.gpsLongitude, 7);
shimniok 0:a6a169de725f 170 //fputc(',',logp);
shimniok 0:a6a169de725f 171 printFloat(logp, s.gpsCourse_deg, 2);
shimniok 0:a6a169de725f 172 fputc(',',logp);
shimniok 0:a6a169de725f 173 printFloat(logp, s.gpsSpeed_mps, 2);
shimniok 0:a6a169de725f 174 fputc(',',logp);
shimniok 0:a6a169de725f 175 printFloat(logp, s.gpsHDOP, 1);
shimniok 0:a6a169de725f 176 fputc(',',logp);
shimniok 0:a6a169de725f 177 printInt(logp, s.gpsSats);
shimniok 0:a6a169de725f 178 fputc(',',logp);
shimniok 1:cb84b477886c 179 // Encoders
shimniok 0:a6a169de725f 180 printFloat(logp, s.lrEncDistance, 7);
shimniok 0:a6a169de725f 181 fputc(',',logp);
shimniok 0:a6a169de725f 182 printFloat(logp, s.rrEncDistance, 7);
shimniok 0:a6a169de725f 183 fputc(',',logp);
shimniok 0:a6a169de725f 184 printFloat(logp, s.lrEncSpeed, 2);
shimniok 0:a6a169de725f 185 fputc(',',logp);
shimniok 0:a6a169de725f 186 printFloat(logp, s.rrEncSpeed, 2);
shimniok 0:a6a169de725f 187 fputc(',',logp);
shimniok 0:a6a169de725f 188 printFloat(logp, s.encHeading, 2);
shimniok 0:a6a169de725f 189 fputc(',',logp);
shimniok 1:cb84b477886c 190 // Estimates
shimniok 0:a6a169de725f 191 printFloat(logp, s.estHeading, 2);
shimniok 0:a6a169de725f 192 fputc(',',logp);
shimniok 1:cb84b477886c 193 printFloat(logp, s.estLagHeading, 2);
shimniok 1:cb84b477886c 194 fputc(',',logp);
shimniok 0:a6a169de725f 195 printFloat(logp, s.estLatitude, 7);
shimniok 0:a6a169de725f 196 fputc(',',logp);
shimniok 0:a6a169de725f 197 printFloat(logp, s.estLongitude, 7);
shimniok 0:a6a169de725f 198 fputc(',',logp);
shimniok 0:a6a169de725f 199 printFloat(logp, s.estX, 4);
shimniok 0:a6a169de725f 200 fputc(',',logp);
shimniok 0:a6a169de725f 201 printFloat(logp, s.estY, 4);
shimniok 0:a6a169de725f 202 fputc(',',logp);
shimniok 1:cb84b477886c 203 // Nav
shimniok 0:a6a169de725f 204 printInt(logp, s.nextWaypoint);
shimniok 0:a6a169de725f 205 fputc(',',logp);
shimniok 0:a6a169de725f 206 printFloat(logp, s.bearing, 2);
shimniok 0:a6a169de725f 207 fputc(',',logp);
shimniok 0:a6a169de725f 208 printFloat(logp, s.distance, 3);
shimniok 0:a6a169de725f 209 fputc(',',logp);
shimniok 1:cb84b477886c 210 printFloat(logp, s.steerAngle, 3);
shimniok 0:a6a169de725f 211 fputc(',',logp);
shimniok 0:a6a169de725f 212 fputc('\n',logp);
shimniok 0:a6a169de725f 213
shimniok 0:a6a169de725f 214 t2 = logtimer.read_us();
shimniok 0:a6a169de725f 215 fprintf(stdout, "%d\n", t2-t1);
shimniok 0:a6a169de725f 216
shimniok 0:a6a169de725f 217 return;
shimniok 0:a6a169de725f 218 }
shimniok 0:a6a169de725f 219
shimniok 0:a6a169de725f 220
shimniok 0:a6a169de725f 221 FILE *openlog(char *prefix)
shimniok 0:a6a169de725f 222 {
shimniok 0:a6a169de725f 223 FILE *fp = 0;
shimniok 0:a6a169de725f 224 char myname[64];
shimniok 0:a6a169de725f 225
shimniok 0:a6a169de725f 226 pc.printf("Opening file...\n");
shimniok 0:a6a169de725f 227
shimniok 0:a6a169de725f 228 while (fp == 0) {
shimniok 0:a6a169de725f 229 if ((fp = fopen("/log/test.txt", "w")) == 0) {
shimniok 0:a6a169de725f 230 pc.printf("Waiting for filesystem to come online...");
shimniok 0:a6a169de725f 231 wait(0.200);
shimniok 0:a6a169de725f 232 lcd.pos(0,1);
shimniok 0:a6a169de725f 233 lcd.printf("%-16s", "Waiting for fs");
shimniok 0:a6a169de725f 234 }
shimniok 0:a6a169de725f 235 }
shimniok 0:a6a169de725f 236 fclose(fp);
shimniok 0:a6a169de725f 237
shimniok 0:a6a169de725f 238 for (int i = 0; i < 1000; i++) {
shimniok 0:a6a169de725f 239 sprintf(myname, "/log/%s%03d.csv", prefix, i);
shimniok 0:a6a169de725f 240 if ((fp = fopen(myname, "r")) == 0) {
shimniok 0:a6a169de725f 241 break;
shimniok 0:a6a169de725f 242 } else {
shimniok 0:a6a169de725f 243 fclose(fp);
shimniok 0:a6a169de725f 244 }
shimniok 0:a6a169de725f 245 }
shimniok 0:a6a169de725f 246 fp = fopen(myname, "w");
shimniok 0:a6a169de725f 247 if (fp == 0) {
shimniok 0:a6a169de725f 248 pc.printf("file write failed: %s\n", myname);
shimniok 0:a6a169de725f 249 } else {
shimniok 0:a6a169de725f 250
shimniok 0:a6a169de725f 251 // TODO -- set error message, get rid of writing to terminal
shimniok 0:a6a169de725f 252
shimniok 0:a6a169de725f 253 //status = true;
shimniok 0:a6a169de725f 254 pc.printf("opened %s for writing\n", myname);
shimniok 0:a6a169de725f 255 lcd.pos(0,1);
shimniok 0:a6a169de725f 256 lcd.printf("%-16s", myname);
shimniok 0:a6a169de725f 257 }
shimniok 0:a6a169de725f 258
shimniok 0:a6a169de725f 259 return fp;
shimniok 0:a6a169de725f 260 }
shimniok 0:a6a169de725f 261
shimniok 0:a6a169de725f 262
shimniok 0:a6a169de725f 263 // Find the next unused filename of the form logger##.csv where # is 0-9
shimniok 0:a6a169de725f 264 //
shimniok 0:a6a169de725f 265 bool initLogfile()
shimniok 0:a6a169de725f 266 {
shimniok 0:a6a169de725f 267 bool status = false;
shimniok 0:a6a169de725f 268
shimniok 0:a6a169de725f 269 logp = openlog("log");
shimniok 0:a6a169de725f 270
shimniok 0:a6a169de725f 271 if (logp != 0) {
shimniok 0:a6a169de725f 272 status = true;
shimniok 0:a6a169de725f 273 //fprintf(logp, "s.millis, s.current, s.voltage, s.gx, s.gy, s.gz, s.gTemp, s.ax, s.ay, s.az, s.mx, s.my, s.mz, s.gHeading, s.cHeading, s.roll, s.pitch, s.yaw, s.gpsLatitude, s.gpsLongitude, s.gpsCourse, s.gpsSpeed, s.gpsHDOP, s.lrEncDistance, s.rrEncDistance, s.lrEncSpeed, s.rrEncSpeed, s.encHeading, s.estHeading, s.estLatitude, s.estLongitude, s.estNorthing, s.estEasting, s.estX, s.estY, s.nextWaypoint, s.bearing, s.distance, s.gbias, s.errAngle, s.leftRanger, s.rightRanger, s.centerRanger, s.crossTrackErr\n");
shimniok 0:a6a169de725f 274 }
shimniok 0:a6a169de725f 275
shimniok 0:a6a169de725f 276 return status;
shimniok 0:a6a169de725f 277 }
shimniok 0:a6a169de725f 278
shimniok 0:a6a169de725f 279 void closeLogfile(void)
shimniok 0:a6a169de725f 280 {
shimniok 0:a6a169de725f 281 if (logp) fclose(logp);
shimniok 0:a6a169de725f 282 }