Patrick Clary / Mbed 2 deprecated WalkingRobot

Dependencies:   CircularBuffer Servo Terminal mbed Radio

Committer:
pclary
Date:
Tue May 21 19:58:01 2013 +0000
Revision:
13:1c5d255835ce
Parent:
12:a952bd74d363
Child:
15:ab358f19cf76
Child:
17:4ec59e8b52a6
Fixed bug

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pclary 3:6fa07ceb897f 1 #include "RobotLeg.h"
pclary 3:6fa07ceb897f 2
pclary 3:6fa07ceb897f 3
pclary 3:6fa07ceb897f 4
pclary 8:db453051f3f4 5 RobotLeg::RobotLeg(PinName thetaPin, PinName phiPin, PinName psiPin, bool start) : theta(thetaPin, start), phi(phiPin, start), psi(psiPin, start)
pclary 3:6fa07ceb897f 6 {
pclary 3:6fa07ceb897f 7 setDimensions(0.1f, 0.1f, 0.0f, 0.0f);
pclary 3:6fa07ceb897f 8 setAngleOffsets(0.0f, 0.0f, 0.0f);
pclary 3:6fa07ceb897f 9
pclary 3:6fa07ceb897f 10 state = neutral;
pclary 6:0163f2737cc6 11 stepTime = 0.4f;
pclary 6:0163f2737cc6 12 stepDelta = 3.141593f / stepTime;
pclary 3:6fa07ceb897f 13 stepHeight = 0.05f;
pclary 3:6fa07ceb897f 14
pclary 3:6fa07ceb897f 15 position = getPosition();
pclary 3:6fa07ceb897f 16 }
pclary 3:6fa07ceb897f 17
pclary 3:6fa07ceb897f 18
pclary 3:6fa07ceb897f 19
pclary 3:6fa07ceb897f 20 void RobotLeg::setDimensions(float a, float b, float c, float d)
pclary 3:6fa07ceb897f 21 {
pclary 3:6fa07ceb897f 22 this->a = a;
pclary 3:6fa07ceb897f 23 this->b = b;
pclary 3:6fa07ceb897f 24 this->c = c;
pclary 3:6fa07ceb897f 25 this->d = d;
pclary 3:6fa07ceb897f 26 }
pclary 3:6fa07ceb897f 27
pclary 3:6fa07ceb897f 28
pclary 3:6fa07ceb897f 29
pclary 3:6fa07ceb897f 30 void RobotLeg::setAngleOffsets(float oth, float oph, float ops)
pclary 3:6fa07ceb897f 31 {
pclary 3:6fa07ceb897f 32 this->oth = oth;
pclary 3:6fa07ceb897f 33 this->oph = oph;
pclary 3:6fa07ceb897f 34 this->ops = ops;
pclary 3:6fa07ceb897f 35 }
pclary 3:6fa07ceb897f 36
pclary 3:6fa07ceb897f 37
pclary 3:6fa07ceb897f 38
pclary 5:475f67175510 39 void RobotLeg::setStepCircle(float xc, float yc, float zc, float rc)
pclary 5:475f67175510 40 {
pclary 5:475f67175510 41 circleCenter = vector3(xc, yc, zc);
pclary 5:475f67175510 42 circleRadius = rc;
pclary 5:475f67175510 43 }
pclary 5:475f67175510 44
pclary 5:475f67175510 45
pclary 5:475f67175510 46
pclary 3:6fa07ceb897f 47 vector3 RobotLeg::getPosition()
pclary 3:6fa07ceb897f 48 {
pclary 3:6fa07ceb897f 49 const float deg2rad = 0.01745329f;
pclary 3:6fa07ceb897f 50 vector3 p;
pclary 3:6fa07ceb897f 51 float L, thetaR, phiR, psiR;
pclary 3:6fa07ceb897f 52
pclary 3:6fa07ceb897f 53 // Convert degrees to radians
pclary 3:6fa07ceb897f 54 thetaR = theta.read() * deg2rad;
pclary 3:6fa07ceb897f 55 phiR = phi.read() * deg2rad;
pclary 3:6fa07ceb897f 56 psiR = psi.read() * deg2rad;
pclary 3:6fa07ceb897f 57
pclary 3:6fa07ceb897f 58 // Calculate forward kinematics
pclary 3:6fa07ceb897f 59 L = a*cos(phiR + oph) + b*sin(phiR + oph + psiR + ops);
pclary 3:6fa07ceb897f 60 p.x = -c*sin(thetaR + oth) + (L + d)*cos(thetaR + oth);
pclary 3:6fa07ceb897f 61 p.y = c*cos(thetaR + oth) + (L + d)*sin(thetaR + oth);
pclary 3:6fa07ceb897f 62 p.z = a*sin(phiR + oph) - b*cos(phiR + oph + psiR + ops);
pclary 3:6fa07ceb897f 63
pclary 3:6fa07ceb897f 64 return p;
pclary 3:6fa07ceb897f 65 }
pclary 3:6fa07ceb897f 66
pclary 3:6fa07ceb897f 67
pclary 3:6fa07ceb897f 68
pclary 3:6fa07ceb897f 69 bool RobotLeg::move(vector3 dest)
pclary 3:6fa07ceb897f 70 {
pclary 3:6fa07ceb897f 71 const float pi2 = 1.5707963;
pclary 3:6fa07ceb897f 72 const float rad2deg = 57.2958;
pclary 3:6fa07ceb897f 73 float L;
pclary 3:6fa07ceb897f 74
pclary 3:6fa07ceb897f 75 // Calculate new angles
pclary 3:6fa07ceb897f 76 L = sqrt(dest.x*dest.x + dest.y*dest.y - c*c) - d;
pclary 3:6fa07ceb897f 77 thetaAngle = atan2( ((L + d)*dest.y - c*dest.x), ((L + d)*dest.x + c*dest.y) ) - oth;
pclary 12:a952bd74d363 78 phiAngle = atan2(dest.z, L) + acos((a*a + L*L + dest.z*dest.z - b*b)/(2.0f*a*sqrt(L*L + dest.z*dest.z))) - oph;
pclary 12:a952bd74d363 79 psiAngle = acos((a*a + b*b - L*L - dest.z*dest.z)/(2.0f*a*b)) - ops - pi2;
pclary 3:6fa07ceb897f 80
pclary 3:6fa07ceb897f 81 // Convert radians to degrees
pclary 3:6fa07ceb897f 82 thetaAngle *= rad2deg;
pclary 3:6fa07ceb897f 83 phiAngle *= rad2deg;
pclary 3:6fa07ceb897f 84 psiAngle *= rad2deg;
pclary 3:6fa07ceb897f 85
pclary 3:6fa07ceb897f 86 // Return true if angle is reachable
pclary 3:6fa07ceb897f 87 if (thetaAngle <= theta.upperLimit && thetaAngle >= theta.lowerLimit &&
pclary 3:6fa07ceb897f 88 phiAngle <= phi.upperLimit && phiAngle >= phi.lowerLimit &&
pclary 3:6fa07ceb897f 89 psiAngle <= psi.upperLimit && psiAngle >= psi.lowerLimit)
pclary 3:6fa07ceb897f 90 {
pclary 3:6fa07ceb897f 91 // Set new angles
pclary 3:6fa07ceb897f 92 theta = thetaAngle;
pclary 3:6fa07ceb897f 93 phi = phiAngle;
pclary 3:6fa07ceb897f 94 psi = psiAngle;
pclary 3:6fa07ceb897f 95
pclary 3:6fa07ceb897f 96 return true;
pclary 3:6fa07ceb897f 97 }
pclary 3:6fa07ceb897f 98 else
pclary 3:6fa07ceb897f 99 {
pclary 3:6fa07ceb897f 100 return false;
pclary 3:6fa07ceb897f 101 }
pclary 3:6fa07ceb897f 102 }
pclary 3:6fa07ceb897f 103
pclary 3:6fa07ceb897f 104
pclary 3:6fa07ceb897f 105
pclary 3:6fa07ceb897f 106 void RobotLeg::step(vector3 dest)
pclary 3:6fa07ceb897f 107 {
pclary 13:1c5d255835ce 108 position = getPosition();
pclary 13:1c5d255835ce 109 stepA = position;
pclary 3:6fa07ceb897f 110 stepB = dest;
pclary 3:6fa07ceb897f 111
pclary 3:6fa07ceb897f 112 stepTimer.reset();
pclary 3:6fa07ceb897f 113 stepTimer.start();
pclary 3:6fa07ceb897f 114 state = stepping;
pclary 3:6fa07ceb897f 115 }
pclary 3:6fa07ceb897f 116
pclary 3:6fa07ceb897f 117
pclary 3:6fa07ceb897f 118
pclary 9:a6d1502f0f20 119 vector3 RobotLeg::reset(float f)
pclary 5:475f67175510 120 {
pclary 5:475f67175510 121 vector3 newPosition;
pclary 5:475f67175510 122 newPosition = circleCenter + nDeltaPosition.unit() * circleRadius * f;
pclary 5:475f67175510 123 step(newPosition);
pclary 9:a6d1502f0f20 124 return nDeltaPosition;
pclary 5:475f67175510 125 }
pclary 5:475f67175510 126
pclary 5:475f67175510 127
pclary 5:475f67175510 128
pclary 5:475f67175510 129 bool RobotLeg::update(const matrix4& deltaTransform)
pclary 3:6fa07ceb897f 130 {
pclary 10:dc1ba352667e 131 float t, d;
pclary 11:9ee0214bd410 132 vector3 newNDeltaPosition, v;
pclary 11:9ee0214bd410 133 const float eps = 0.00001f;
pclary 3:6fa07ceb897f 134
pclary 3:6fa07ceb897f 135 switch (state)
pclary 3:6fa07ceb897f 136 {
pclary 3:6fa07ceb897f 137 case neutral:
pclary 10:dc1ba352667e 138 // Calculate new position and position delta
pclary 5:475f67175510 139 newPosition = deltaTransform*position;
pclary 9:a6d1502f0f20 140 newNDeltaPosition = position - newPosition;
pclary 12:a952bd74d363 141 newNDeltaPosition.z = 0.0f;
pclary 12:a952bd74d363 142 if (fabs(newNDeltaPosition.x) > eps || fabs(newNDeltaPosition.y) > eps)
pclary 9:a6d1502f0f20 143 nDeltaPosition = newNDeltaPosition;
pclary 10:dc1ba352667e 144
pclary 10:dc1ba352667e 145 // Check if new position is outside the step circle
pclary 11:9ee0214bd410 146 v = newPosition - circleCenter;
pclary 10:dc1ba352667e 147 d = sqrt(v.x*v.x + v.y*v.y);
pclary 10:dc1ba352667e 148
pclary 10:dc1ba352667e 149 // Attempt to move to the new position
pclary 11:9ee0214bd410 150 return d < circleRadius;
pclary 3:6fa07ceb897f 151
pclary 3:6fa07ceb897f 152 case stepping:
pclary 11:9ee0214bd410 153 // Compute new position along step trajectory
pclary 3:6fa07ceb897f 154 t = stepTimer.read();
pclary 3:6fa07ceb897f 155 newPosition.x = stepA.x + (stepB.x - stepA.x)*0.5f*(1 - cos(stepDelta*t));
pclary 3:6fa07ceb897f 156 newPosition.y = stepA.y + (stepB.y - stepA.y)*0.5f*(1 - cos(stepDelta*t));
pclary 3:6fa07ceb897f 157 newPosition.z = stepA.z + (stepB.z - stepA.z)*stepDelta*t + stepHeight*sin(stepDelta*t);
pclary 3:6fa07ceb897f 158
pclary 6:0163f2737cc6 159 if (t < stepTime)
pclary 3:6fa07ceb897f 160 {
pclary 3:6fa07ceb897f 161 move(newPosition);
pclary 3:6fa07ceb897f 162 }
pclary 3:6fa07ceb897f 163 else
pclary 3:6fa07ceb897f 164 {
pclary 3:6fa07ceb897f 165 move(stepB);
pclary 3:6fa07ceb897f 166 state = neutral;
pclary 3:6fa07ceb897f 167 stepTimer.stop();
pclary 3:6fa07ceb897f 168 position = getPosition();
pclary 13:1c5d255835ce 169 newPosition = position;
pclary 3:6fa07ceb897f 170 }
pclary 11:9ee0214bd410 171
pclary 11:9ee0214bd410 172 return true;
pclary 3:6fa07ceb897f 173 }
pclary 5:475f67175510 174
pclary 12:a952bd74d363 175 // Should never reach here
pclary 11:9ee0214bd410 176 return false;
pclary 11:9ee0214bd410 177 }
pclary 11:9ee0214bd410 178
pclary 11:9ee0214bd410 179
pclary 11:9ee0214bd410 180
pclary 11:9ee0214bd410 181 void RobotLeg::apply()
pclary 11:9ee0214bd410 182 {
pclary 11:9ee0214bd410 183 if (neutral == state)
pclary 11:9ee0214bd410 184 {
pclary 11:9ee0214bd410 185 position = newPosition;
pclary 11:9ee0214bd410 186 move(position);
pclary 11:9ee0214bd410 187 }
pclary 11:9ee0214bd410 188 }
pclary 11:9ee0214bd410 189
pclary 11:9ee0214bd410 190
pclary 11:9ee0214bd410 191
pclary 11:9ee0214bd410 192 bool RobotLeg::getStepping()
pclary 11:9ee0214bd410 193 {
pclary 11:9ee0214bd410 194 return stepping == state;
pclary 11:9ee0214bd410 195 }