Control program for a four-legged 12 axis robot.

Dependencies:   CircularBuffer Servo Terminal mbed Radio

Committer:
pclary
Date:
Mon May 27 00:42:22 2013 +0000
Revision:
16:cc1ae2a289ee
Parent:
14:21f932d6069d
Child:
18:8806d24809c2
Added ability to reset legs by pressing a button

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pclary 0:449568595ed9 1 #include "mbed.h"
pclary 0:449568595ed9 2 #include "RobotLeg.h"
pclary 3:6fa07ceb897f 3 #include "Matrix.h"
pclary 2:caf73a1d7827 4 #include "CircularBuffer.h"
pclary 5:475f67175510 5 #include "Radio.h"
pclary 6:0163f2737cc6 6 #include "Terminal.h"
pclary 9:a6d1502f0f20 7 #include "utility.h"
pclary 0:449568595ed9 8 #include <cstring>
pclary 6:0163f2737cc6 9 #include <cmath>
pclary 0:449568595ed9 10
pclary 6:0163f2737cc6 11 #define MAXSPEED 0.1f
pclary 6:0163f2737cc6 12 #define MAXTURN 1.0f
pclary 8:db453051f3f4 13 #define RESET_STEP_TIME 0.4f
pclary 8:db453051f3f4 14 #define DIM_A 0.125f
pclary 8:db453051f3f4 15 #define DIM_B 0.11f
pclary 8:db453051f3f4 16 #define DIM_C 0.0025f
pclary 14:21f932d6069d 17 #define DIM_D 0.0275f
pclary 8:db453051f3f4 18 #define CIRCLE_X 0.095f
pclary 8:db453051f3f4 19 #define CIRCLE_Y 0.095f
pclary 8:db453051f3f4 20 #define CIRCLE_Z -0.12f
pclary 8:db453051f3f4 21 #define CIRCLE_R 0.09f
pclary 11:9ee0214bd410 22 #define PERIOD 0.002f
pclary 6:0163f2737cc6 23
pclary 11:9ee0214bd410 24
pclary 0:449568595ed9 25
pclary 3:6fa07ceb897f 26 CircularBuffer<float,16> dataLog;
pclary 9:a6d1502f0f20 27 Radio radio(p5, p6, p7, p16, p17, p18);
pclary 11:9ee0214bd410 28 RobotLeg legA(p26, p29, p30, false);
pclary 8:db453051f3f4 29 RobotLeg legB(p13, p14, p15, false);
pclary 11:9ee0214bd410 30 RobotLeg legC(p19, p11, p8, false);
pclary 11:9ee0214bd410 31 RobotLeg legD(p25, p24, p23, false);
pclary 6:0163f2737cc6 32
pclary 16:cc1ae2a289ee 33 DigitalOut led1(LED1);
pclary 16:cc1ae2a289ee 34 DigitalOut led2(LED2);
pclary 16:cc1ae2a289ee 35
pclary 13:1c5d255835ce 36
pclary 13:1c5d255835ce 37
pclary 12:a952bd74d363 38 CmdHandler* legpos(Terminal* terminal, const char*)
pclary 12:a952bd74d363 39 {
pclary 12:a952bd74d363 40 char output[256];
pclary 12:a952bd74d363 41 char abuf[64];
pclary 12:a952bd74d363 42 char bbuf[64];
pclary 12:a952bd74d363 43 char cbuf[64];
pclary 12:a952bd74d363 44 char dbuf[64];
pclary 12:a952bd74d363 45 legA.getPosition().print(abuf, 64);
pclary 12:a952bd74d363 46 legB.getPosition().print(bbuf, 64);
pclary 12:a952bd74d363 47 legC.getPosition().print(cbuf, 64);
pclary 12:a952bd74d363 48 legD.getPosition().print(dbuf, 64);
pclary 12:a952bd74d363 49 snprintf(output, 256, "A = [%s]\nB = [%s]\nC = [%s]\nD = [%s]", abuf, bbuf, cbuf, dbuf);
pclary 12:a952bd74d363 50 terminal->write(output);
pclary 12:a952bd74d363 51 return NULL;
pclary 12:a952bd74d363 52 }
pclary 12:a952bd74d363 53
pclary 6:0163f2737cc6 54
pclary 6:0163f2737cc6 55
pclary 6:0163f2737cc6 56 CmdHandler* log(Terminal* terminal, const char* input)
pclary 6:0163f2737cc6 57 {
pclary 6:0163f2737cc6 58 int start = 0;
pclary 6:0163f2737cc6 59 int end = 15;
pclary 6:0163f2737cc6 60 char output[256];
pclary 6:0163f2737cc6 61
pclary 6:0163f2737cc6 62 if (sscanf(input, "log %d %d", &start, &end) == 1)
pclary 6:0163f2737cc6 63 {
pclary 6:0163f2737cc6 64 // Print only one item
pclary 12:a952bd74d363 65 snprintf(output, 256, "%4d: %f\n", start, dataLog[start]);
pclary 6:0163f2737cc6 66 terminal->write(output);
pclary 6:0163f2737cc6 67 }
pclary 6:0163f2737cc6 68 else
pclary 6:0163f2737cc6 69 {
pclary 6:0163f2737cc6 70 // Print a range of items
pclary 6:0163f2737cc6 71 for (int i = start; i <= end; i++)
pclary 6:0163f2737cc6 72 {
pclary 12:a952bd74d363 73 snprintf(output, 256, "%4d: %f\n", i, dataLog[i]);
pclary 6:0163f2737cc6 74 terminal->write(output);
pclary 6:0163f2737cc6 75 }
pclary 6:0163f2737cc6 76 }
pclary 6:0163f2737cc6 77
pclary 6:0163f2737cc6 78 return NULL;
pclary 8:db453051f3f4 79 } // log()
pclary 6:0163f2737cc6 80
pclary 6:0163f2737cc6 81
pclary 6:0163f2737cc6 82
pclary 6:0163f2737cc6 83 int deadzone(int input, int zone)
pclary 6:0163f2737cc6 84 {
pclary 6:0163f2737cc6 85 if (input > zone) return input;
pclary 6:0163f2737cc6 86 else if (input < -zone) return input;
pclary 6:0163f2737cc6 87 else return 0;
pclary 8:db453051f3f4 88 } // deadzone()
pclary 6:0163f2737cc6 89
pclary 6:0163f2737cc6 90
pclary 6:0163f2737cc6 91
pclary 11:9ee0214bd410 92 void setupLegs();
pclary 0:449568595ed9 93
pclary 0:449568595ed9 94
pclary 0:449568595ed9 95
pclary 0:449568595ed9 96 int main()
pclary 0:449568595ed9 97 {
pclary 9:a6d1502f0f20 98 Timer deltaTimer;
pclary 10:dc1ba352667e 99 float xaxis, yaxis, turnaxis, angle;
pclary 11:9ee0214bd410 100 float deltaTime;
pclary 2:caf73a1d7827 101 vector3 v;
pclary 5:475f67175510 102 matrix4 T;
pclary 5:475f67175510 103 matrix4 PA, QA;
pclary 5:475f67175510 104 matrix4 PB, QB;
pclary 5:475f67175510 105 matrix4 PC, QC;
pclary 6:0163f2737cc6 106 matrix4 PD, QD;
pclary 0:449568595ed9 107 Terminal terminal;
pclary 2:caf73a1d7827 108
pclary 2:caf73a1d7827 109 terminal.addCommand("log", &log);
pclary 12:a952bd74d363 110 terminal.addCommand("leg", &legpos);
pclary 2:caf73a1d7827 111
pclary 6:0163f2737cc6 112 radio.reset();
pclary 6:0163f2737cc6 113
pclary 11:9ee0214bd410 114 setupLegs();
pclary 11:9ee0214bd410 115
pclary 11:9ee0214bd410 116 // Create matrices to change base from robot coordinates to leg coordinates
pclary 12:a952bd74d363 117 QA.translate(vector3(0.508f, 0.508f, 0.0f));
pclary 11:9ee0214bd410 118 PA = QA.inverse();
pclary 12:a952bd74d363 119 QB.translate(vector3(-0.508f, -0.508f, 0.0f));
pclary 11:9ee0214bd410 120 QB.a11 = -1.0f; QB.a22 = -1.0f;
pclary 11:9ee0214bd410 121 PB = QB.inverse();
pclary 12:a952bd74d363 122 QC.translate(vector3(-0.508f, 0.508f, 0.0f));
pclary 11:9ee0214bd410 123 QC.a11 = -1.0f;
pclary 11:9ee0214bd410 124 PC = QC.inverse();
pclary 12:a952bd74d363 125 QD.translate(vector3(0.508f, -0.508f, 0.0f));
pclary 11:9ee0214bd410 126 QD.a22 = -1.0f;
pclary 11:9ee0214bd410 127 PD = QD.inverse();
pclary 11:9ee0214bd410 128
pclary 11:9ee0214bd410 129 // Start timer
pclary 11:9ee0214bd410 130 deltaTimer.start();
pclary 11:9ee0214bd410 131
pclary 11:9ee0214bd410 132 while(true)
pclary 11:9ee0214bd410 133 {
pclary 11:9ee0214bd410 134 while (deltaTimer.read() < PERIOD);
pclary 11:9ee0214bd410 135
pclary 11:9ee0214bd410 136 // Read controller input
pclary 11:9ee0214bd410 137 xaxis = 0.0078125f * deadzone((int8_t)((radio.rx_controller>>0)&0xff), 8); // Convert to +/-1.0f range
pclary 11:9ee0214bd410 138 yaxis = -0.0078125f * deadzone((int8_t)((radio.rx_controller>>8)&0xff), 8);
pclary 11:9ee0214bd410 139 turnaxis = -0.0078125f * deadzone((int8_t)((radio.rx_controller>>16)&0xff), 8);
pclary 11:9ee0214bd410 140
pclary 11:9ee0214bd410 141 // Get delta-time
pclary 11:9ee0214bd410 142 deltaTime = deltaTimer.read();
pclary 16:cc1ae2a289ee 143
pclary 16:cc1ae2a289ee 144 if ((radio.rx_controller>>25)&0x1) // reset
pclary 16:cc1ae2a289ee 145 {
pclary 16:cc1ae2a289ee 146 legA.reset(-0.6f);
pclary 16:cc1ae2a289ee 147 while (legA.getStepping()) legA.update(T);
pclary 16:cc1ae2a289ee 148 legB.reset(-0.1f);
pclary 16:cc1ae2a289ee 149 while (legB.getStepping()) legB.update(T);
pclary 16:cc1ae2a289ee 150 legC.reset(0.4f);
pclary 16:cc1ae2a289ee 151 while (legC.getStepping()) legC.update(T);
pclary 16:cc1ae2a289ee 152 legD.reset(0.9f);
pclary 16:cc1ae2a289ee 153 while (legD.getStepping()) legD.update(T);
pclary 16:cc1ae2a289ee 154 }
pclary 16:cc1ae2a289ee 155
pclary 11:9ee0214bd410 156 deltaTimer.reset();
pclary 11:9ee0214bd410 157 dataLog.push(deltaTime);
pclary 11:9ee0214bd410 158
pclary 11:9ee0214bd410 159 // Compute delta movement vector and delta angle
pclary 11:9ee0214bd410 160 v.x = -xaxis;
pclary 11:9ee0214bd410 161 v.y = -yaxis;
pclary 12:a952bd74d363 162 v.z = 0.0f;
pclary 11:9ee0214bd410 163 v = v * MAXSPEED * deltaTime;
pclary 11:9ee0214bd410 164 angle = -turnaxis * MAXTURN * deltaTime;
pclary 11:9ee0214bd410 165
pclary 11:9ee0214bd410 166 // Compute movement transformation in robot coordinates
pclary 11:9ee0214bd410 167 T.identity().rotateZ(angle).translate(v).inverse();
pclary 11:9ee0214bd410 168
pclary 11:9ee0214bd410 169 bool stepping = legA.getStepping() || legB.getStepping() || legC.getStepping() || legD.getStepping();
pclary 11:9ee0214bd410 170 bool lockup = false;
pclary 11:9ee0214bd410 171
pclary 11:9ee0214bd410 172 if (!legA.update(PA*T*QA))
pclary 11:9ee0214bd410 173 {
pclary 11:9ee0214bd410 174 if (stepping) lockup = true;
pclary 11:9ee0214bd410 175 else
pclary 11:9ee0214bd410 176 {
pclary 11:9ee0214bd410 177 legA.reset(0.8);
pclary 11:9ee0214bd410 178 stepping = true;
pclary 11:9ee0214bd410 179 }
pclary 11:9ee0214bd410 180 }
pclary 11:9ee0214bd410 181 if (!legB.update(PB*T*QB))
pclary 11:9ee0214bd410 182 {
pclary 11:9ee0214bd410 183 if (stepping) lockup = true;
pclary 11:9ee0214bd410 184 else
pclary 11:9ee0214bd410 185 {
pclary 11:9ee0214bd410 186 legB.reset(0.8f);
pclary 11:9ee0214bd410 187 stepping = true;
pclary 11:9ee0214bd410 188 }
pclary 11:9ee0214bd410 189 }
pclary 11:9ee0214bd410 190 if (!legC.update(PC*T*QC))
pclary 11:9ee0214bd410 191 {
pclary 11:9ee0214bd410 192 if (stepping) lockup = true;
pclary 11:9ee0214bd410 193 else
pclary 11:9ee0214bd410 194 {
pclary 11:9ee0214bd410 195 legC.reset(0.8f);
pclary 11:9ee0214bd410 196 stepping = true;
pclary 11:9ee0214bd410 197 }
pclary 11:9ee0214bd410 198 }
pclary 11:9ee0214bd410 199 if (!legD.update(PD*T*QD))
pclary 11:9ee0214bd410 200 {
pclary 11:9ee0214bd410 201 if (stepping) lockup = true;
pclary 11:9ee0214bd410 202 else
pclary 11:9ee0214bd410 203 {
pclary 11:9ee0214bd410 204 legD.reset(0.8f);
pclary 11:9ee0214bd410 205 stepping = true;
pclary 11:9ee0214bd410 206 }
pclary 11:9ee0214bd410 207 }
pclary 11:9ee0214bd410 208
pclary 11:9ee0214bd410 209 if (!lockup)
pclary 11:9ee0214bd410 210 {
pclary 11:9ee0214bd410 211 legA.apply();
pclary 11:9ee0214bd410 212 legB.apply();
pclary 11:9ee0214bd410 213 legC.apply();
pclary 11:9ee0214bd410 214 legD.apply();
pclary 11:9ee0214bd410 215 }
pclary 11:9ee0214bd410 216 } // while (true)
pclary 11:9ee0214bd410 217 } // main()
pclary 11:9ee0214bd410 218
pclary 11:9ee0214bd410 219
pclary 11:9ee0214bd410 220
pclary 11:9ee0214bd410 221 void setupLegs()
pclary 11:9ee0214bd410 222 {
pclary 0:449568595ed9 223 // Set leg parameters
pclary 8:db453051f3f4 224 legA.setDimensions(DIM_A, DIM_B, DIM_C, DIM_D);
pclary 8:db453051f3f4 225 legB.setDimensions(DIM_A, DIM_B, DIM_C, DIM_D);
pclary 8:db453051f3f4 226 legC.setDimensions(DIM_A, DIM_B, DIM_C, DIM_D);
pclary 8:db453051f3f4 227 legD.setDimensions(DIM_A, DIM_B, DIM_C, DIM_D);
pclary 5:475f67175510 228 legA.setAngleOffsets(0.7853982f, 0.0f, 0.0f);
pclary 5:475f67175510 229 legB.setAngleOffsets(0.7853982f, 0.0f, 0.0f);
pclary 5:475f67175510 230 legC.setAngleOffsets(0.7853982f, 0.0f, 0.0f);
pclary 5:475f67175510 231 legD.setAngleOffsets(0.7853982f, 0.0f, 0.0f);
pclary 8:db453051f3f4 232 legA.setStepCircle(CIRCLE_X, CIRCLE_Y, CIRCLE_Z, CIRCLE_R);
pclary 8:db453051f3f4 233 legB.setStepCircle(CIRCLE_X, CIRCLE_Y, CIRCLE_Z, CIRCLE_R);
pclary 8:db453051f3f4 234 legC.setStepCircle(CIRCLE_X, CIRCLE_Y, CIRCLE_Z, CIRCLE_R);
pclary 8:db453051f3f4 235 legD.setStepCircle(CIRCLE_X, CIRCLE_Y, CIRCLE_Z, CIRCLE_R);
pclary 14:21f932d6069d 236 legA.theta.calibrate(1130, 2080, 45.0f, -45.0f);
pclary 14:21f932d6069d 237 legA.phi.calibrate(1150, 2080, 70.0f, -45.0f);
pclary 14:21f932d6069d 238 legA.psi.calibrate(1985, 1055, 70.0f, -60.0f);
pclary 14:21f932d6069d 239 legB.theta.calibrate(990, 1940, 45.0f, -45.0f);
pclary 14:21f932d6069d 240 legB.phi.calibrate(1105, 2055, 70.0f, -45.0f);
pclary 14:21f932d6069d 241 legB.psi.calibrate(2090, 1150, 70.0f, -60.0f);
pclary 14:21f932d6069d 242 legC.theta.calibrate(1930, 860, 45.0f, -45.0f);
pclary 14:21f932d6069d 243 legC.phi.calibrate(1945, 1000, 70.0f, -45.0f);
pclary 14:21f932d6069d 244 legC.psi.calibrate(1085, 2005, 70.0f, -60.0f);
pclary 14:21f932d6069d 245 legD.theta.calibrate(2020, 1080, 45.0f, -45.0f);
pclary 14:21f932d6069d 246 legD.phi.calibrate(2085, 1145, 70.0f, -45.0f);
pclary 14:21f932d6069d 247 legD.psi.calibrate(1070, 2010, 70.0f, -60.0f);
pclary 6:0163f2737cc6 248
pclary 6:0163f2737cc6 249 // Initialize leg position deltas
pclary 6:0163f2737cc6 250 legA.nDeltaPosition = vector3(0.0f, 0.01f, 0.0f);
pclary 6:0163f2737cc6 251 legB.nDeltaPosition = vector3(0.0f, -0.01f, 0.0f);
pclary 6:0163f2737cc6 252 legC.nDeltaPosition = vector3(0.0f, 0.01f, 0.0f);
pclary 6:0163f2737cc6 253 legD.nDeltaPosition = vector3(0.0f, -0.01f, 0.0f);
pclary 8:db453051f3f4 254
pclary 2:caf73a1d7827 255 // Go to initial position
pclary 9:a6d1502f0f20 256 legA.move(vector3(0.15f, 0.15f, 0.05f));
pclary 9:a6d1502f0f20 257 legB.move(vector3(0.15f, 0.15f, 0.05f));
pclary 9:a6d1502f0f20 258 legC.move(vector3(0.15f, 0.15f, 0.05f));
pclary 9:a6d1502f0f20 259 legD.move(vector3(0.15f, 0.15f, 0.05f));
pclary 8:db453051f3f4 260 legA.theta.enable(); wait(0.1f);
pclary 8:db453051f3f4 261 legB.theta.enable(); wait(0.1f);
pclary 8:db453051f3f4 262 legC.theta.enable(); wait(0.1f);
pclary 8:db453051f3f4 263 legD.theta.enable(); wait(0.1f);
pclary 8:db453051f3f4 264 legA.phi.enable(); wait(0.1f);
pclary 8:db453051f3f4 265 legB.phi.enable(); wait(0.1f);
pclary 8:db453051f3f4 266 legC.phi.enable(); wait(0.1f);
pclary 8:db453051f3f4 267 legD.phi.enable(); wait(0.1f);
pclary 8:db453051f3f4 268 legA.psi.enable(); wait(0.1f);
pclary 8:db453051f3f4 269 legB.psi.enable(); wait(0.1f);
pclary 8:db453051f3f4 270 legC.psi.enable(); wait(0.1f);
pclary 8:db453051f3f4 271 legD.psi.enable(); wait(0.1f);
pclary 9:a6d1502f0f20 272 wait(0.4f);
pclary 13:1c5d255835ce 273 legA.reset(-0.6f);
pclary 13:1c5d255835ce 274 legB.reset(-0.1f);
pclary 13:1c5d255835ce 275 legC.reset(0.4f);
pclary 13:1c5d255835ce 276 legD.reset(0.9f);
pclary 11:9ee0214bd410 277 }