Patrick Clary / Mbed 2 deprecated WalkingRobot

Dependencies:   CircularBuffer Servo Terminal mbed Radio

Committer:
pclary
Date:
Wed May 22 23:48:24 2013 +0000
Revision:
15:ab358f19cf76
Parent:
13:1c5d255835ce
Preliminary orientation support

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 15:ab358f19cf76 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 15:ab358f19cf76 75 if (orientation != NULL)
pclary 15:ab358f19cf76 76 {
pclary 15:ab358f19cf76 77 dest = (*orientation) * dest;
pclary 15:ab358f19cf76 78 }
pclary 15:ab358f19cf76 79
pclary 3:6fa07ceb897f 80 // Calculate new angles
pclary 3:6fa07ceb897f 81 L = sqrt(dest.x*dest.x + dest.y*dest.y - c*c) - d;
pclary 3:6fa07ceb897f 82 thetaAngle = atan2( ((L + d)*dest.y - c*dest.x), ((L + d)*dest.x + c*dest.y) ) - oth;
pclary 12:a952bd74d363 83 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 84 psiAngle = acos((a*a + b*b - L*L - dest.z*dest.z)/(2.0f*a*b)) - ops - pi2;
pclary 3:6fa07ceb897f 85
pclary 3:6fa07ceb897f 86 // Convert radians to degrees
pclary 3:6fa07ceb897f 87 thetaAngle *= rad2deg;
pclary 3:6fa07ceb897f 88 phiAngle *= rad2deg;
pclary 3:6fa07ceb897f 89 psiAngle *= rad2deg;
pclary 3:6fa07ceb897f 90
pclary 3:6fa07ceb897f 91 // Return true if angle is reachable
pclary 3:6fa07ceb897f 92 if (thetaAngle <= theta.upperLimit && thetaAngle >= theta.lowerLimit &&
pclary 3:6fa07ceb897f 93 phiAngle <= phi.upperLimit && phiAngle >= phi.lowerLimit &&
pclary 3:6fa07ceb897f 94 psiAngle <= psi.upperLimit && psiAngle >= psi.lowerLimit)
pclary 3:6fa07ceb897f 95 {
pclary 3:6fa07ceb897f 96 // Set new angles
pclary 3:6fa07ceb897f 97 theta = thetaAngle;
pclary 3:6fa07ceb897f 98 phi = phiAngle;
pclary 3:6fa07ceb897f 99 psi = psiAngle;
pclary 3:6fa07ceb897f 100
pclary 3:6fa07ceb897f 101 return true;
pclary 3:6fa07ceb897f 102 }
pclary 3:6fa07ceb897f 103 else
pclary 3:6fa07ceb897f 104 {
pclary 3:6fa07ceb897f 105 return false;
pclary 3:6fa07ceb897f 106 }
pclary 3:6fa07ceb897f 107 }
pclary 3:6fa07ceb897f 108
pclary 3:6fa07ceb897f 109
pclary 3:6fa07ceb897f 110
pclary 3:6fa07ceb897f 111 void RobotLeg::step(vector3 dest)
pclary 3:6fa07ceb897f 112 {
pclary 15:ab358f19cf76 113 //position = getPosition();
pclary 15:ab358f19cf76 114 stepA = getPosition();
pclary 3:6fa07ceb897f 115 stepB = dest;
pclary 3:6fa07ceb897f 116
pclary 3:6fa07ceb897f 117 stepTimer.reset();
pclary 3:6fa07ceb897f 118 stepTimer.start();
pclary 3:6fa07ceb897f 119 state = stepping;
pclary 3:6fa07ceb897f 120 }
pclary 3:6fa07ceb897f 121
pclary 3:6fa07ceb897f 122
pclary 3:6fa07ceb897f 123
pclary 9:a6d1502f0f20 124 vector3 RobotLeg::reset(float f)
pclary 5:475f67175510 125 {
pclary 5:475f67175510 126 vector3 newPosition;
pclary 5:475f67175510 127 newPosition = circleCenter + nDeltaPosition.unit() * circleRadius * f;
pclary 5:475f67175510 128 step(newPosition);
pclary 9:a6d1502f0f20 129 return nDeltaPosition;
pclary 5:475f67175510 130 }
pclary 5:475f67175510 131
pclary 5:475f67175510 132
pclary 5:475f67175510 133
pclary 15:ab358f19cf76 134 bool RobotLeg::update(const matrix4& deltaTransform, matrix4* orientation_)
pclary 3:6fa07ceb897f 135 {
pclary 10:dc1ba352667e 136 float t, d;
pclary 11:9ee0214bd410 137 vector3 newNDeltaPosition, v;
pclary 11:9ee0214bd410 138 const float eps = 0.00001f;
pclary 15:ab358f19cf76 139
pclary 15:ab358f19cf76 140 orientation = orientation_;
pclary 3:6fa07ceb897f 141
pclary 3:6fa07ceb897f 142 switch (state)
pclary 3:6fa07ceb897f 143 {
pclary 3:6fa07ceb897f 144 case neutral:
pclary 10:dc1ba352667e 145 // Calculate new position and position delta
pclary 15:ab358f19cf76 146 newPosition = deltaTransform*getPosition();
pclary 15:ab358f19cf76 147 newNDeltaPosition = getPosition() - newPosition;
pclary 12:a952bd74d363 148 newNDeltaPosition.z = 0.0f;
pclary 12:a952bd74d363 149 if (fabs(newNDeltaPosition.x) > eps || fabs(newNDeltaPosition.y) > eps)
pclary 9:a6d1502f0f20 150 nDeltaPosition = newNDeltaPosition;
pclary 10:dc1ba352667e 151
pclary 10:dc1ba352667e 152 // Check if new position is outside the step circle
pclary 11:9ee0214bd410 153 v = newPosition - circleCenter;
pclary 10:dc1ba352667e 154 d = sqrt(v.x*v.x + v.y*v.y);
pclary 10:dc1ba352667e 155
pclary 10:dc1ba352667e 156 // Attempt to move to the new position
pclary 11:9ee0214bd410 157 return d < circleRadius;
pclary 3:6fa07ceb897f 158
pclary 3:6fa07ceb897f 159 case stepping:
pclary 11:9ee0214bd410 160 // Compute new position along step trajectory
pclary 3:6fa07ceb897f 161 t = stepTimer.read();
pclary 3:6fa07ceb897f 162 newPosition.x = stepA.x + (stepB.x - stepA.x)*0.5f*(1 - cos(stepDelta*t));
pclary 3:6fa07ceb897f 163 newPosition.y = stepA.y + (stepB.y - stepA.y)*0.5f*(1 - cos(stepDelta*t));
pclary 3:6fa07ceb897f 164 newPosition.z = stepA.z + (stepB.z - stepA.z)*stepDelta*t + stepHeight*sin(stepDelta*t);
pclary 3:6fa07ceb897f 165
pclary 6:0163f2737cc6 166 if (t < stepTime)
pclary 3:6fa07ceb897f 167 {
pclary 3:6fa07ceb897f 168 move(newPosition);
pclary 3:6fa07ceb897f 169 }
pclary 3:6fa07ceb897f 170 else
pclary 3:6fa07ceb897f 171 {
pclary 3:6fa07ceb897f 172 move(stepB);
pclary 3:6fa07ceb897f 173 state = neutral;
pclary 3:6fa07ceb897f 174 stepTimer.stop();
pclary 15:ab358f19cf76 175 //position = getPosition();
pclary 15:ab358f19cf76 176 newPosition = stepB;
pclary 3:6fa07ceb897f 177 }
pclary 11:9ee0214bd410 178
pclary 11:9ee0214bd410 179 return true;
pclary 3:6fa07ceb897f 180 }
pclary 5:475f67175510 181
pclary 12:a952bd74d363 182 // Should never reach here
pclary 11:9ee0214bd410 183 return false;
pclary 11:9ee0214bd410 184 }
pclary 11:9ee0214bd410 185
pclary 11:9ee0214bd410 186
pclary 11:9ee0214bd410 187
pclary 11:9ee0214bd410 188 void RobotLeg::apply()
pclary 11:9ee0214bd410 189 {
pclary 11:9ee0214bd410 190 if (neutral == state)
pclary 11:9ee0214bd410 191 {
pclary 15:ab358f19cf76 192 //position = newPosition;
pclary 15:ab358f19cf76 193 move(newPosition);
pclary 11:9ee0214bd410 194 }
pclary 11:9ee0214bd410 195 }
pclary 11:9ee0214bd410 196
pclary 11:9ee0214bd410 197
pclary 11:9ee0214bd410 198
pclary 11:9ee0214bd410 199 bool RobotLeg::getStepping()
pclary 11:9ee0214bd410 200 {
pclary 11:9ee0214bd410 201 return stepping == state;
pclary 11:9ee0214bd410 202 }