Control program for a four-legged 12 axis robot.

Dependencies:   CircularBuffer Servo Terminal mbed Radio

Committer:
pclary
Date:
Tue May 21 04:27:58 2013 +0000
Revision:
12:a952bd74d363
Parent:
11:9ee0214bd410
Child:
13:1c5d255835ce
Fixed turning

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