Code used to localize a robot using IMU with PID control
Dependencies: IMUfilter LSM9DS0 Motordriver mbed
Fork of Robot_feedback_ir by
main.cpp@1:e71cba217586, 2015-10-20 (annotated)
- Committer:
- cardenb
- Date:
- Tue Oct 20 19:13:05 2015 +0000
- Revision:
- 1:e71cba217586
- Parent:
- 0:98baffd99476
Codebase for the robot IMU localization
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
awinata | 0:98baffd99476 | 1 | #include "mbed.h" |
awinata | 0:98baffd99476 | 2 | #include "motordriver.h" |
awinata | 0:98baffd99476 | 3 | #include "LSM9DS0.h" |
cardenb | 1:e71cba217586 | 4 | #include "IMUfilter.h" |
cardenb | 1:e71cba217586 | 5 | |
cardenb | 1:e71cba217586 | 6 | #define RATE 0.1 |
cardenb | 1:e71cba217586 | 7 | |
cardenb | 1:e71cba217586 | 8 | // Callback to update the PID controller |
cardenb | 1:e71cba217586 | 9 | Ticker pid_updater; |
cardenb | 1:e71cba217586 | 10 | // Set a PID update rate of 10 Hz |
cardenb | 1:e71cba217586 | 11 | const float PID_RATE = 0.1; |
cardenb | 1:e71cba217586 | 12 | // Call back to update the IMU samples |
cardenb | 1:e71cba217586 | 13 | Ticker imu_updater; |
cardenb | 1:e71cba217586 | 14 | Ticker heading_reseter; |
cardenb | 1:e71cba217586 | 15 | // Set a sample rate of 200 Hz for the IMU |
cardenb | 1:e71cba217586 | 16 | const float IMU_RATE = 0.025; |
cardenb | 1:e71cba217586 | 17 | const int NUM_IMU_SAMPLES = 4; |
cardenb | 1:e71cba217586 | 18 | // Count the number of times the IMU is sampled to average every 100 samples. |
cardenb | 1:e71cba217586 | 19 | int imu_count = 0; |
cardenb | 1:e71cba217586 | 20 | Ticker dist_updater; |
cardenb | 1:e71cba217586 | 21 | const float DIST_RATE = 0.1; |
cardenb | 1:e71cba217586 | 22 | const float DIST_LIMIT = 0.5; |
cardenb | 1:e71cba217586 | 23 | |
cardenb | 1:e71cba217586 | 24 | const float INITIAL_SPEED_LEFT = 0.7; |
cardenb | 1:e71cba217586 | 25 | const float INITIAL_SPEED_RIGHT = 0.609; |
cardenb | 1:e71cba217586 | 26 | |
cardenb | 1:e71cba217586 | 27 | const float TURN_TIME = 0.55; |
awinata | 0:98baffd99476 | 28 | |
awinata | 0:98baffd99476 | 29 | /*/////// PID control gains |
awinata | 0:98baffd99476 | 30 | / These values need to be adjusted in accordance with the individual |
awinata | 0:98baffd99476 | 31 | / actuators (motors) either by trial and error or computation. The information |
cardenb | 1:e71cba217586 | 32 | / here should help: |
awinata | 0:98baffd99476 | 33 | *//////// |
cardenb | 1:e71cba217586 | 34 | /* |
cardenb | 1:e71cba217586 | 35 | * Done with Ziegler-Nichols method |
cardenb | 1:e71cba217586 | 36 | |
cardenb | 1:e71cba217586 | 37 | #define Kp 0.002 |
cardenb | 1:e71cba217586 | 38 | #define Ki 0.00002 |
cardenb | 1:e71cba217586 | 39 | #define Kd 0.075 |
cardenb | 1:e71cba217586 | 40 | */ |
cardenb | 1:e71cba217586 | 41 | /* |
cardenb | 1:e71cba217586 | 42 | * Done with random method from stack overflow which is more upvoted than Ziegler-Nichols |
cardenb | 1:e71cba217586 | 43 | |
cardenb | 1:e71cba217586 | 44 | #define Kp 0.192 |
cardenb | 1:e71cba217586 | 45 | #define Ki 0.0 |
cardenb | 1:e71cba217586 | 46 | #define Kd 0.048 |
cardenb | 1:e71cba217586 | 47 | */ |
awinata | 0:98baffd99476 | 48 | |
cardenb | 1:e71cba217586 | 49 | #define Kp 0.0001 |
cardenb | 1:e71cba217586 | 50 | #define Ki 0.0 |
cardenb | 1:e71cba217586 | 51 | #define Kd 0.00001 |
cardenb | 1:e71cba217586 | 52 | /* |
cardenb | 1:e71cba217586 | 53 | */ |
awinata | 0:98baffd99476 | 54 | // SDO_XM and SDO_G are pulled up, so our addresses are: |
awinata | 0:98baffd99476 | 55 | #define LSM9DS0_XM_ADDR 0x1D // Would be 0x1E if SDO_XM is LOW |
awinata | 0:98baffd99476 | 56 | #define LSM9DS0_G_ADDR 0x6B // Would be 0x6A if SDO_G is LOW |
awinata | 0:98baffd99476 | 57 | |
awinata | 0:98baffd99476 | 58 | // peripheral objects |
awinata | 0:98baffd99476 | 59 | DigitalOut f(LED1); // forward |
awinata | 0:98baffd99476 | 60 | DigitalOut b(LED2); // backward |
awinata | 0:98baffd99476 | 61 | DigitalOut l(LED3); // left |
awinata | 0:98baffd99476 | 62 | DigitalOut r(LED4); // right |
awinata | 0:98baffd99476 | 63 | //See http://mbed.org/cookbook/Motor |
awinata | 0:98baffd99476 | 64 | //Connections to dual H-brdige driver for the two drive motors |
awinata | 0:98baffd99476 | 65 | Motor left(p21, p22, p23, 1); // pwm, fwd, rev, has brake feature |
awinata | 0:98baffd99476 | 66 | Motor right(p26, p25, p24, 1); |
awinata | 0:98baffd99476 | 67 | LSM9DS0 imu(p9, p10, LSM9DS0_G_ADDR, LSM9DS0_XM_ADDR); // imu sensor |
awinata | 0:98baffd99476 | 68 | Serial pc(USBTX, USBRX); // usb serial for debugging |
awinata | 0:98baffd99476 | 69 | |
awinata | 0:98baffd99476 | 70 | // function prototypes |
awinata | 0:98baffd99476 | 71 | void setup(); |
awinata | 0:98baffd99476 | 72 | void initIMU(); |
awinata | 0:98baffd99476 | 73 | float getHeading(); |
cardenb | 1:e71cba217586 | 74 | void updatePID(); |
cardenb | 1:e71cba217586 | 75 | void updateIMU(); |
cardenb | 1:e71cba217586 | 76 | float GetAvgHeading(); |
cardenb | 1:e71cba217586 | 77 | void UpdateMotorSpeed(float pid_output); |
cardenb | 1:e71cba217586 | 78 | void updateDist(); |
cardenb | 1:e71cba217586 | 79 | void headingReset(); |
cardenb | 1:e71cba217586 | 80 | void turnRight(); |
cardenb | 1:e71cba217586 | 81 | void turnLeft(); |
cardenb | 1:e71cba217586 | 82 | void calibrateAccel(); |
cardenb | 1:e71cba217586 | 83 | void turnToAngle(float angle); |
awinata | 0:98baffd99476 | 84 | |
awinata | 0:98baffd99476 | 85 | // global variables |
awinata | 0:98baffd99476 | 86 | int count; // counter for IR |
cardenb | 1:e71cba217586 | 87 | |
awinata | 0:98baffd99476 | 88 | float calcHeading; // calculated heading |
awinata | 0:98baffd99476 | 89 | float heading[1]; // index 0 = goal, index 1 = current |
cardenb | 1:e71cba217586 | 90 | float heading_avg[NUM_IMU_SAMPLES]; // moving average array |
awinata | 0:98baffd99476 | 91 | float sum; |
cardenb | 1:e71cba217586 | 92 | |
awinata | 0:98baffd99476 | 93 | float previousError; // previous error |
awinata | 0:98baffd99476 | 94 | float pidError; // error |
awinata | 0:98baffd99476 | 95 | float steadyError; // steady-state error |
cardenb | 1:e71cba217586 | 96 | |
awinata | 0:98baffd99476 | 97 | float P; // proportional error |
awinata | 0:98baffd99476 | 98 | float I; // integral error |
awinata | 0:98baffd99476 | 99 | float D; // derivative error |
cardenb | 1:e71cba217586 | 100 | |
awinata | 0:98baffd99476 | 101 | float kp; // proportional constant |
awinata | 0:98baffd99476 | 102 | float ki; // integral constant |
awinata | 0:98baffd99476 | 103 | float kd; // derivative constant |
cardenb | 1:e71cba217586 | 104 | |
awinata | 0:98baffd99476 | 105 | float output; // PID controller output |
cardenb | 1:e71cba217586 | 106 | |
cardenb | 1:e71cba217586 | 107 | float dt; // update frequency |
cardenb | 1:e71cba217586 | 108 | |
awinata | 0:98baffd99476 | 109 | float motorSpeed1; // motor speed for left motor |
awinata | 0:98baffd99476 | 110 | float motorSpeed2; // motor speed for right motor |
cardenb | 1:e71cba217586 | 111 | float dist[2]; // 0 = x, 1 = y |
cardenb | 1:e71cba217586 | 112 | float vel[2]; // 0 = x, 1 = y |
cardenb | 1:e71cba217586 | 113 | float accel[2]; // 0 = x, 1 = y |
cardenb | 1:e71cba217586 | 114 | float cur_dist; // resultant distance |
cardenb | 1:e71cba217586 | 115 | |
cardenb | 1:e71cba217586 | 116 | |
awinata | 0:98baffd99476 | 117 | |
awinata | 0:98baffd99476 | 118 | // function implementations |
awinata | 0:98baffd99476 | 119 | void setup() |
awinata | 0:98baffd99476 | 120 | { |
awinata | 0:98baffd99476 | 121 | // Use the begin() function to initialize the LSM9DS0 library. |
awinata | 0:98baffd99476 | 122 | // You can either call it with no parameters (the easy way): |
awinata | 0:98baffd99476 | 123 | uint16_t status = imu.begin(); |
awinata | 0:98baffd99476 | 124 | |
cardenb | 1:e71cba217586 | 125 | // Make sure communication is working |
awinata | 0:98baffd99476 | 126 | pc.printf("LSM9DS0 WHO_AM_I's returned: 0x%X\n", status); |
awinata | 0:98baffd99476 | 127 | pc.printf("Should be 0x49D4\n\n"); |
cardenb | 1:e71cba217586 | 128 | initIMU(); |
cardenb | 1:e71cba217586 | 129 | |
cardenb | 1:e71cba217586 | 130 | // Initialize motor speeds |
cardenb | 1:e71cba217586 | 131 | motorSpeed1 = INITIAL_SPEED_LEFT; |
cardenb | 1:e71cba217586 | 132 | motorSpeed2 = INITIAL_SPEED_RIGHT; |
cardenb | 1:e71cba217586 | 133 | // Attach the PID Update routine to a callback |
cardenb | 1:e71cba217586 | 134 | pid_updater.attach(&updatePID, PID_RATE); |
cardenb | 1:e71cba217586 | 135 | // Attach the IMU update routine to a callback to computer a moving average |
cardenb | 1:e71cba217586 | 136 | imu_updater.attach(&updateIMU, IMU_RATE); |
cardenb | 1:e71cba217586 | 137 | dist_updater.attach(&updateDist, DIST_RATE); |
cardenb | 1:e71cba217586 | 138 | // set motor speeds |
cardenb | 1:e71cba217586 | 139 | left.speed(motorSpeed1); |
cardenb | 1:e71cba217586 | 140 | right.speed(motorSpeed2); |
awinata | 0:98baffd99476 | 141 | } |
awinata | 0:98baffd99476 | 142 | |
awinata | 0:98baffd99476 | 143 | // obtains the initial heading upon bootup |
awinata | 0:98baffd99476 | 144 | void initIMU() |
awinata | 0:98baffd99476 | 145 | { |
awinata | 0:98baffd99476 | 146 | imu.readMag(); |
cardenb | 1:e71cba217586 | 147 | imu.readAccel(); |
cardenb | 1:e71cba217586 | 148 | imu.calcBias(); |
cardenb | 1:e71cba217586 | 149 | imu.readMag(); |
cardenb | 1:e71cba217586 | 150 | wait(0.1); |
cardenb | 1:e71cba217586 | 151 | // initial heading |
cardenb | 1:e71cba217586 | 152 | float sum = 0; |
cardenb | 1:e71cba217586 | 153 | for( int i = 0; i < NUM_IMU_SAMPLES; ++i) { |
cardenb | 1:e71cba217586 | 154 | sum += getHeading(); |
cardenb | 1:e71cba217586 | 155 | } |
cardenb | 1:e71cba217586 | 156 | float initHeading = sum/NUM_IMU_SAMPLES; |
cardenb | 1:e71cba217586 | 157 | |
awinata | 0:98baffd99476 | 158 | heading[0] = initHeading; |
awinata | 0:98baffd99476 | 159 | heading[1] = initHeading; |
awinata | 0:98baffd99476 | 160 | } |
awinata | 0:98baffd99476 | 161 | |
awinata | 0:98baffd99476 | 162 | // obtains an updated heading |
awinata | 0:98baffd99476 | 163 | float getHeading() |
awinata | 0:98baffd99476 | 164 | { |
awinata | 0:98baffd99476 | 165 | imu.readMag(); // reads current value |
awinata | 0:98baffd99476 | 166 | calcHeading = imu.calcHeading(); // sets current value |
awinata | 0:98baffd99476 | 167 | |
cardenb | 1:e71cba217586 | 168 | // pc.printf("Compass Heading (in degrees): "); |
cardenb | 1:e71cba217586 | 169 | // pc.printf("%2f\r\n",calcHeading); |
cardenb | 1:e71cba217586 | 170 | // pc.printf("%2f\r\n",heading[0]); |
awinata | 0:98baffd99476 | 171 | |
awinata | 0:98baffd99476 | 172 | return calcHeading; |
awinata | 0:98baffd99476 | 173 | } |
awinata | 0:98baffd99476 | 174 | |
cardenb | 1:e71cba217586 | 175 | // PID update attached to a ticker. |
cardenb | 1:e71cba217586 | 176 | void updatePID() |
awinata | 0:98baffd99476 | 177 | { |
cardenb | 1:e71cba217586 | 178 | float current = heading[1]; |
cardenb | 1:e71cba217586 | 179 | float target = heading[0]; |
cardenb | 1:e71cba217586 | 180 | float dt = PID_RATE; |
cardenb | 1:e71cba217586 | 181 | // pc.printf("current=%0.2f, target=%0.2f, dt=%0.2f\r\n", current, target, dt); |
awinata | 0:98baffd99476 | 182 | // calculate difference between actual and goal values |
awinata | 0:98baffd99476 | 183 | pidError = target - current; |
awinata | 0:98baffd99476 | 184 | if (pidError < -270) pidError += 360; |
awinata | 0:98baffd99476 | 185 | if (pidError > 270) pidError -= 360; |
awinata | 0:98baffd99476 | 186 | |
awinata | 0:98baffd99476 | 187 | // accumulates error over time |
awinata | 0:98baffd99476 | 188 | steadyError += pidError*dt; |
awinata | 0:98baffd99476 | 189 | |
awinata | 0:98baffd99476 | 190 | // integrator windup compensation (saturates to actuator's output) |
awinata | 0:98baffd99476 | 191 | if (steadyError < -10.0) steadyError = -10.0; |
awinata | 0:98baffd99476 | 192 | if (steadyError > 10.0) steadyError = 10.0; |
awinata | 0:98baffd99476 | 193 | |
awinata | 0:98baffd99476 | 194 | P = kp*pidError; // proportional error |
awinata | 0:98baffd99476 | 195 | I = ki*steadyError; // integral error |
awinata | 0:98baffd99476 | 196 | D = kd*(pidError - previousError)/dt; // derivative error |
awinata | 0:98baffd99476 | 197 | |
awinata | 0:98baffd99476 | 198 | // save current error |
awinata | 0:98baffd99476 | 199 | previousError = pidError; |
awinata | 0:98baffd99476 | 200 | |
awinata | 0:98baffd99476 | 201 | float pidOutput = P + I + D; // calculate the PID output |
cardenb | 1:e71cba217586 | 202 | pidOutput /= 300.0; // scale it down to get it within the range of the actuator - probably needs tuning |
awinata | 0:98baffd99476 | 203 | if(pidOutput < -0.1) pidOutput = -0.1; |
awinata | 0:98baffd99476 | 204 | if(pidOutput > 0.1) pidOutput = 0.1; |
awinata | 0:98baffd99476 | 205 | |
cardenb | 1:e71cba217586 | 206 | // pc.printf("P = %f | I = %f | D = %f | Output = %f\r\n",P,I,D,pidOutput); |
cardenb | 1:e71cba217586 | 207 | UpdateMotorSpeed(pidOutput); |
cardenb | 1:e71cba217586 | 208 | } |
cardenb | 1:e71cba217586 | 209 | |
cardenb | 1:e71cba217586 | 210 | void UpdateMotorSpeed(float pid_output) { |
cardenb | 1:e71cba217586 | 211 | // updates new motor speeds |
cardenb | 1:e71cba217586 | 212 | motorSpeed1 -= pid_output; |
cardenb | 1:e71cba217586 | 213 | motorSpeed2 += pid_output; |
cardenb | 1:e71cba217586 | 214 | |
cardenb | 1:e71cba217586 | 215 | // pc.printf("Wheel speed difference = %0.2f\r\n", motorSpeed1-motorSpeed2); |
cardenb | 1:e71cba217586 | 216 | // set motor speeds |
cardenb | 1:e71cba217586 | 217 | left.speed(motorSpeed1); |
cardenb | 1:e71cba217586 | 218 | right.speed(motorSpeed2); |
cardenb | 1:e71cba217586 | 219 | } |
cardenb | 1:e71cba217586 | 220 | |
cardenb | 1:e71cba217586 | 221 | float GetAvgHeading() { |
cardenb | 1:e71cba217586 | 222 | float sum = 0; |
cardenb | 1:e71cba217586 | 223 | for( int i = 0; i < NUM_IMU_SAMPLES; ++i ) { |
cardenb | 1:e71cba217586 | 224 | sum += heading_avg[i]; |
cardenb | 1:e71cba217586 | 225 | } |
cardenb | 1:e71cba217586 | 226 | return sum/NUM_IMU_SAMPLES; |
cardenb | 1:e71cba217586 | 227 | } |
cardenb | 1:e71cba217586 | 228 | |
cardenb | 1:e71cba217586 | 229 | |
cardenb | 1:e71cba217586 | 230 | // Get reach the minimum number of samples and then use a moving average filter |
cardenb | 1:e71cba217586 | 231 | // Keep the count below 2*num_samples to prevent overflow, but keep at a minimum of 1*num_samples |
cardenb | 1:e71cba217586 | 232 | void updateIMU() { |
cardenb | 1:e71cba217586 | 233 | // Get current index into the ring buffer (heading_avg) |
cardenb | 1:e71cba217586 | 234 | int moving_idx = imu_count % NUM_IMU_SAMPLES; |
cardenb | 1:e71cba217586 | 235 | // Add the current heading into the buffer |
cardenb | 1:e71cba217586 | 236 | heading_avg[moving_idx] = getHeading(); |
cardenb | 1:e71cba217586 | 237 | |
cardenb | 1:e71cba217586 | 238 | // Keep the IMU count between num_samples & 2*num_samples |
cardenb | 1:e71cba217586 | 239 | // Get the average heading as long as the minimum number of samples have been reached. |
cardenb | 1:e71cba217586 | 240 | if( imu_count >= NUM_IMU_SAMPLES && imu_count <= 2*NUM_IMU_SAMPLES ) { |
cardenb | 1:e71cba217586 | 241 | if( imu_count == 2*NUM_IMU_SAMPLES ) { |
cardenb | 1:e71cba217586 | 242 | imu_count = NUM_IMU_SAMPLES; |
cardenb | 1:e71cba217586 | 243 | } |
cardenb | 1:e71cba217586 | 244 | heading[1] = GetAvgHeading(); |
cardenb | 1:e71cba217586 | 245 | // pc.printf("av_heading=%0.2f\r\n", heading[1]); |
cardenb | 1:e71cba217586 | 246 | } |
cardenb | 1:e71cba217586 | 247 | imu_count += 1; |
cardenb | 1:e71cba217586 | 248 | } |
awinata | 0:98baffd99476 | 249 | |
cardenb | 1:e71cba217586 | 250 | // Update acceleration, velocity, and distance vectors. |
cardenb | 1:e71cba217586 | 251 | void updateDist() { |
cardenb | 1:e71cba217586 | 252 | // Get latest acceleration reading. |
cardenb | 1:e71cba217586 | 253 | imu.readAccel(); |
cardenb | 1:e71cba217586 | 254 | |
cardenb | 1:e71cba217586 | 255 | // Get acceleration vector |
cardenb | 1:e71cba217586 | 256 | accel[0] = imu.ax - imu.abias[0]; |
cardenb | 1:e71cba217586 | 257 | accel[1] = imu.ay - imu.abias[1]; |
cardenb | 1:e71cba217586 | 258 | |
cardenb | 1:e71cba217586 | 259 | // Get velocity vector |
cardenb | 1:e71cba217586 | 260 | vel[0] += accel[0]*RATE; |
cardenb | 1:e71cba217586 | 261 | vel[1] += accel[1]*RATE; |
cardenb | 1:e71cba217586 | 262 | |
cardenb | 1:e71cba217586 | 263 | // Get distance vector |
cardenb | 1:e71cba217586 | 264 | dist[0] += vel[0]*RATE; |
cardenb | 1:e71cba217586 | 265 | dist[1] += vel[1]*RATE; |
cardenb | 1:e71cba217586 | 266 | |
cardenb | 1:e71cba217586 | 267 | // Get resultant distance |
cardenb | 1:e71cba217586 | 268 | // d = (dx^2 + dy^2)^(1/2) |
cardenb | 1:e71cba217586 | 269 | cur_dist = sqrt(dist[0]*dist[0] + dist[1]*dist[1]); |
cardenb | 1:e71cba217586 | 270 | if( cur_dist > DIST_LIMIT ) { |
cardenb | 1:e71cba217586 | 271 | turnRight(); |
cardenb | 1:e71cba217586 | 272 | // Reset vel and dist to get accurate distance measurement to next move |
cardenb | 1:e71cba217586 | 273 | vel[0] = 0; |
cardenb | 1:e71cba217586 | 274 | vel[1] = 0; |
cardenb | 1:e71cba217586 | 275 | dist[0] = 0; |
cardenb | 1:e71cba217586 | 276 | dist[1] = 0; |
cardenb | 1:e71cba217586 | 277 | cur_dist = 0; |
cardenb | 1:e71cba217586 | 278 | pidError = 0; |
cardenb | 1:e71cba217586 | 279 | previousError = 0; |
cardenb | 1:e71cba217586 | 280 | } |
cardenb | 1:e71cba217586 | 281 | // pc.printf("ax=%0.2f, ay=%0.2f\r\nvx=%0.2f, vy=%0.2f\r\ndx=%0.2f, dy=%0.2f, d=%0.2f\r\n", accel[0], accel[1], vel[0], vel[1], dist[0], dist[1], cur_dist); |
cardenb | 1:e71cba217586 | 282 | } |
cardenb | 1:e71cba217586 | 283 | |
cardenb | 1:e71cba217586 | 284 | void headingReset() { |
cardenb | 1:e71cba217586 | 285 | motorSpeed1 = INITIAL_SPEED_LEFT; |
cardenb | 1:e71cba217586 | 286 | motorSpeed2 = INITIAL_SPEED_RIGHT; |
cardenb | 1:e71cba217586 | 287 | |
cardenb | 1:e71cba217586 | 288 | // set motor speeds |
cardenb | 1:e71cba217586 | 289 | left.speed(motorSpeed1); |
cardenb | 1:e71cba217586 | 290 | right.speed(motorSpeed2); |
cardenb | 1:e71cba217586 | 291 | |
cardenb | 1:e71cba217586 | 292 | heading[0] = getHeading(); |
cardenb | 1:e71cba217586 | 293 | heading[1] = getHeading(); |
cardenb | 1:e71cba217586 | 294 | } |
cardenb | 1:e71cba217586 | 295 | |
cardenb | 1:e71cba217586 | 296 | void turnRight() { |
cardenb | 1:e71cba217586 | 297 | |
cardenb | 1:e71cba217586 | 298 | left.stop(0); |
cardenb | 1:e71cba217586 | 299 | right.stop(0); |
cardenb | 1:e71cba217586 | 300 | left.speed(-1); |
cardenb | 1:e71cba217586 | 301 | right.speed(1); |
cardenb | 1:e71cba217586 | 302 | |
cardenb | 1:e71cba217586 | 303 | /* |
cardenb | 1:e71cba217586 | 304 | int turn_ang = heading[0] + 90; |
cardenb | 1:e71cba217586 | 305 | turn_ang = turn_ang% 360; |
cardenb | 1:e71cba217586 | 306 | turnToAngle(turn_ang); |
cardenb | 1:e71cba217586 | 307 | */ |
cardenb | 1:e71cba217586 | 308 | |
cardenb | 1:e71cba217586 | 309 | wait(TURN_TIME); |
cardenb | 1:e71cba217586 | 310 | headingReset(); |
cardenb | 1:e71cba217586 | 311 | } |
cardenb | 1:e71cba217586 | 312 | |
cardenb | 1:e71cba217586 | 313 | void turnToAngle(float angle) { |
cardenb | 1:e71cba217586 | 314 | bool hasTurned = false; |
cardenb | 1:e71cba217586 | 315 | left.stop(0); |
cardenb | 1:e71cba217586 | 316 | right.stop(0); |
cardenb | 1:e71cba217586 | 317 | left.speed(-1); |
cardenb | 1:e71cba217586 | 318 | right.speed(1); |
cardenb | 1:e71cba217586 | 319 | while(!hasTurned) { |
cardenb | 1:e71cba217586 | 320 | float cur_head = getHeading(); |
cardenb | 1:e71cba217586 | 321 | pc.printf("%0.2f, %0.2f\r\n", cur_head, angle); |
cardenb | 1:e71cba217586 | 322 | if( cur_head > angle - 20 && cur_head < angle + 20 ) { |
cardenb | 1:e71cba217586 | 323 | hasTurned = true; |
cardenb | 1:e71cba217586 | 324 | heading[0] = cur_head; |
cardenb | 1:e71cba217586 | 325 | left.stop(0); |
cardenb | 1:e71cba217586 | 326 | right.stop(0); |
cardenb | 1:e71cba217586 | 327 | } |
cardenb | 1:e71cba217586 | 328 | |
cardenb | 1:e71cba217586 | 329 | } |
cardenb | 1:e71cba217586 | 330 | } |
cardenb | 1:e71cba217586 | 331 | void turnLeft() { |
cardenb | 1:e71cba217586 | 332 | left.stop(0); |
cardenb | 1:e71cba217586 | 333 | right.stop(0); |
cardenb | 1:e71cba217586 | 334 | left.speed(1); |
cardenb | 1:e71cba217586 | 335 | right.speed(-1); |
cardenb | 1:e71cba217586 | 336 | |
cardenb | 1:e71cba217586 | 337 | /* |
cardenb | 1:e71cba217586 | 338 | int turn_ang = heading[0] - 90; |
cardenb | 1:e71cba217586 | 339 | turn_ang = turn_ang% 360; |
cardenb | 1:e71cba217586 | 340 | turnToAngle(turn_ang); |
cardenb | 1:e71cba217586 | 341 | */ |
cardenb | 1:e71cba217586 | 342 | |
cardenb | 1:e71cba217586 | 343 | wait(TURN_TIME); |
cardenb | 1:e71cba217586 | 344 | headingReset(); |
awinata | 0:98baffd99476 | 345 | } |
awinata | 0:98baffd99476 | 346 | |
awinata | 0:98baffd99476 | 347 | int main() |
awinata | 0:98baffd99476 | 348 | { |
awinata | 0:98baffd99476 | 349 | // initialization functions |
awinata | 0:98baffd99476 | 350 | setup(); |
awinata | 0:98baffd99476 | 351 | |
awinata | 0:98baffd99476 | 352 | // variables |
awinata | 0:98baffd99476 | 353 | dt = RATE; |
awinata | 0:98baffd99476 | 354 | kp = Kp; |
awinata | 0:98baffd99476 | 355 | ki = Ki; |
awinata | 0:98baffd99476 | 356 | kd = Kd; |
cardenb | 1:e71cba217586 | 357 | |
cardenb | 1:e71cba217586 | 358 | /* |
cardenb | 1:e71cba217586 | 359 | // Attach the PID Update routine to a callback |
cardenb | 1:e71cba217586 | 360 | pid_updater.attach(&updatePID, PID_RATE); |
cardenb | 1:e71cba217586 | 361 | // Attach the IMU update routine to a callback to computer a moving average |
cardenb | 1:e71cba217586 | 362 | imu_updater.attach(&updateIMU, IMU_RATE); |
cardenb | 1:e71cba217586 | 363 | dist_updater.attach(&updateDist, DIST_RATE); |
awinata | 0:98baffd99476 | 364 | |
cardenb | 1:e71cba217586 | 365 | */ |
cardenb | 1:e71cba217586 | 366 | // spin in the main loop. Updates will happen asychronously. |
awinata | 0:98baffd99476 | 367 | while(1) { |
awinata | 0:98baffd99476 | 368 | } |
awinata | 0:98baffd99476 | 369 | } |