Control program for a four-legged 12 axis robot.

Dependencies:   CircularBuffer Servo Terminal mbed Radio

Committer:
pclary
Date:
Wed May 22 05:46:45 2013 +0000
Revision:
14:21f932d6069d
Parent:
13:1c5d255835ce
Child:
16:cc1ae2a289ee
Recalibrated servos

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