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
Diff: updater.cpp
- Revision:
- 2:fbc6e3cf3ed8
- Parent:
- 1:cb84b477886c
- Child:
- 3:42f3821c4e54
--- a/updater.cpp Tue May 28 13:58:35 2013 +0000 +++ b/updater.cpp Thu Jun 06 13:40:23 2013 +0000 @@ -1,4 +1,6 @@ #include "mbed.h" +#include "util.h" +#include "globals.h" #include "updater.h" #include "Config.h" #include "Actuators.h" @@ -25,6 +27,7 @@ //#define LOG_SKIP 1 // 50ms, 20hz, log entry entered into fifo // The following is for main loop at 10ms = 100hz +#define HDG_LAG 100 #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 @@ -98,10 +101,10 @@ float dt; // delta time } history[MAXHIST]; // fifo for sensor data, position, heading, dt -int hCount; // history counter; one > 100, we can go back in time to reference gyro history +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 (100 entries prior) +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 */ @@ -122,7 +125,7 @@ return; } -/** instruct the controller to arm, begin estimation */ +/** instruct the controller to start running */ void beginRun() { go = true; @@ -298,15 +301,16 @@ 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 = history[prev].hdg + dt*history[now].gyro; // compute current heading from current gyro - if (history[now].hdg >= 360.0) history[now].hdg -= 360.0; - if (history[now].hdg < 0) history[now].hdg += 360.0; + history[now].hdg = history[prev].hdg + dt*(history[now].gyro - gyroBias); // compute current heading from current gyro + clamp(history[now].hdg, 0, 360.0); + //if (history[now].hdg >= 360.0) history[now].hdg -= 360.0; + //if (history[now].hdg < 0) history[now].hdg += 360.0; 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 < 100) { + 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 @@ -354,25 +358,33 @@ // 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 100 times up to present record. Haversine is way, way too slow, + // 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. - // - // initialize these once - errAngle = (estLagHeading - history[lag].hdg); - if (errAngle <= -180.0) errAngle += 360.0; - if (errAngle > 180) errAngle -= 360.0; + + // 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. + errAngle = (estLagHeading - history[lag].hdg); + // low pass filter error angle: + clamp(errAngle, -180.0, 180.0); + //if (errAngle > 180.0) errAngle -= 360.0; + //if (errAngle <= -180.0) errAngle += 360.0; + errAngle *= 0.01; // multiply only after clamping to -180:180 range. //fprintf(stdout, "%d %.2f, %.2f, %.4f %.4f\n", lag, estLagHeading, history[lag].hdg, estLagHeading - history[lag].hdg, errAngle); float cosA = cos(errAngle * PI / 180.0); float sinA = sin(errAngle * PI / 180.0); // Update position & heading from history[lag] through history[now] int i = lag; - for (int j=0; j < 100; j++) { + // 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 += errAngle; + clamp(history[i].hdg, 0, 360.0); + //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 errAngle around pivot point; no need to rotate pivot point (j=0) if (j > 0) { float dx = history[i].x-history[lag].x; @@ -399,9 +411,9 @@ float prevDistance = cartHere.distanceTo(config.cwpt[lastWaypoint]); double relativeBrg = bearing - history[now].hdg; // if correction angle is < -180, express as negative degree - // TODO 3 turn this into a function - if (relativeBrg < -180.0) relativeBrg += 360.0; - if (relativeBrg > 180.0) relativeBrg -= 360.0; + clamp(relativeBrg, -180.0, 180.0); + //if (relativeBrg < -180.0) relativeBrg += 360.0; + //if (relativeBrg > 180.0) relativeBrg -= 360.0; // 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 @@ -410,10 +422,10 @@ // 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 (distance < config.brakeDist || prevDistance < config.brakeDist) { + if ( (thisTime - timeZero) < 3000 ) { + setSpeed( config.startSpeed ); + } else if (distance < config.brakeDist || prevDistance < config.brakeDist) { setSpeed( config.turnSpeed ); - } else if ( (thisTime - timeZero) < 1000 ) { - setSpeed( config.startSpeed ); } else { setSpeed( config.topSpeed ); } @@ -568,7 +580,7 @@ state[inState].bearing = bearing; state[inState].distance = distance; state[inState].nextWaypoint = nextWaypoint; - //state[inState].gbias = gyroBias; + state[inState].gbias = gyroBias; state[inState].errAngle = biasErrAngle; //state[inState].leftRanger = sensors.leftRanger; //state[inState].rightRanger = sensors.rightRanger;