Used for the Biorobotics Project: Calculates the position of the hands based on the shoulder rotations and vice versa.
Fork of compute by
compute.cpp
- Committer:
- AeroKev
- Date:
- 2015-10-22
- Revision:
- 6:f36e6aaf64e2
- Parent:
- 5:5f75399596f3
- Child:
- 7:a301b6123068
File content as of revision 6:f36e6aaf64e2:
#include <iostream> #include <math.h> #include <stdlib.h> #include <stdio.h> #include <fstream> #include "mbed.h" #include "compute.h" using namespace std; const double k = 18.77; const double l = 26.72; const int Ax = -7; const int Ay = 0; const int Bx = 7; const int By = 0; const float upper_arm_lim = 150*(M_PI/180); const float lower_arm_lim = 0; ofstream info_stream; Serial pc4(USBTX,USBRX); float calcGamma(float ApBp) { return acos(((pow(ApBp,2))/(2*l*ApBp))); } float calcOmega(float Apx, float Apy, float Bpx, float Bpy) { return atan((Bpy-Apy)/(Bpx-Apx)); } /* Calculate Px in a different frame. This is the first row of the homogenous matrix (below) to calculate Px: [cos(omega) -sin(omega) Ax] [sin(omega) cos(omega) Ay] [0 0 1 ] Input: omega (float) = the angle omega fPx (float) = x-coordinate of P in frame 1 fPy (float) = y-coordinate of P in frame 1 Apx (float) = A'x Output: Px in different frame (float) */ float homogenousX(float omega, float fPx, float fPy, float Apx) { return (cos(omega)*fPx) - (sin(omega)*fPy) + Apx; } /* Calculate Py in a different frame. This is the second row of the homogenous matrix (below) to calculate Py: [cos(omega) -sin(omega) Ax] [sin(omega) cos(omega) Ay] [0 0 1 ] Input: omega (float) = the angle omega fPx (float) = x-coordinate of P in frame 1 fPy (float) = y-coordinate of P in frame 1 Apy (float) = A'y Output: Py in different frame (float) */ float homogenousY(float omega, float fPx, float fPy, float Apy) { return (sin(omega)*fPx) + (cos(omega)*fPy) + Apy; } /* Calculate the angle between two points A and B */ float calcTanDifference(double Ax, double Ay, double Bx, double By) { return atan2((Ay-By), (Ax-Bx)); } float calcLengthPoints(float Ax, float Ay, float Bx, float By) { return sqrt(pow(Ax-Bx,2) + pow(Ay-By,2)); } float calcCosAngle(double line) { return acos((pow(line,2) + pow(k,2) - pow(l,2)) / (2*k*line)); } float calcTanDirected(float Ax, float Ay, float Bx, float By, float Ox, float Oy) { float rads = atan2((Ay-Oy), (Ax-Ox)) - atan2((By-Oy), (Bx-Ox)); return (rads > 0 ? rads : (2*M_PI+rads)); } bool checkArm(float arm) { return (arm < upper_arm_lim && arm > lower_arm_lim); } int rad2deg(float rad) { return floor(rad*180); } float deg2rad(float deg) { return (deg/180); } /* Calculate the position of Point P given two angles, alpha and beta. Input: alpha (int) = angle alpha beta (int) = angle beta float& Px, Py = needed to change Px, Py Output: - */ void Angles2Point(float alpha, float beta, float& Px, float& Py) { alpha = alpha*M_PI; beta = beta*M_PI; // Calculate A' and B' (x and y coordinate seperately) float Apx = k*cos(alpha)+Ax; float Apy = k*sin(alpha)+Ay; float Bpx = k*cos(beta)+Bx; float Bpy = k*sin(beta)+By; float ApBp = calcLengthPoints(Apx, Apy, Bpx, Bpy); // Calculate gamma float gamma = calcGamma(ApBp); // Calculate Px and Py in frame 1 float fPx = l*cos(gamma); float fPy = l*sin(gamma); // Calculate omega, angle between frame 0 and frame 1 float omega = calcOmega(Apx, Apy, Bpx, Bpy); // Calculate Px and Py in frame 0 and update it Px = homogenousX(omega, fPx, fPy, Apx); Py = homogenousY(omega, fPx, fPy, Apy); // Check physical constraints float armA = calcTanDirected(Px, Py, Ax, Ay, Apx, Apy); float armB = calcTanDirected(Bx, By, Px, Py, Bpx, Bpy); if(!(checkArm(armA) && checkArm(armB))) { return; } } void Point2Angles(double Px, double Py, double& a, double& b) { // Calculate gamma of the arm A and arm B float gamma_a = calcTanDifference(Px, Py, Ax, Ay); float gamma_b = calcTanDifference(Px, Py, Bx, By)*(-1); // Calculate |AP| and |BP| float AP = calcLengthPoints(Px, Py, Ax, Ay); float BP = calcLengthPoints(Px, Py, Bx, By); // Calculate omega of the arm A and arm B float omega_a = calcCosAngle(AP); float omega_b = calcCosAngle(BP); // Calculate A'(A'x, A'y) and B'(A'x, A'y) in the new frame float Apx2 = k*cos(omega_a); float Apy2 = k*sin(omega_a); float Bpx2 = k*cos(omega_b); float Bpy2 = k*sin(omega_b); // Translate and rotate A' and B' from frame 2 to frame 1 using gamma. float Apx = homogenousX(gamma_a, Apx2, Apy2, Ax); float Apy = homogenousY(gamma_a, Apx2, Apy2, Ay); float Bpx = homogenousX(gamma_b, Bpx2, Bpy2, Bx); float Bpy = homogenousY(gamma_b, Bpx2, Bpy2, By); // Calculate alpha and beta a = calcTanDifference(Apx, Apy, Ax, Ay); b = calcTanDifference(Bpx, Bpy, Bx, By)*(-1); // If alpha < 0, make alpha positive if(a<0) { float alpha = (2*M_PI)+a; a = alpha; } // Check physical constraints float armA = calcTanDirected(Px, Py, Ax, Ay, Apx, Apy)/M_PI; float armB = calcTanDirected(Bx, By, Px, Py, Bpx, Bpy*(-1))/M_PI; if(armA*180>170 || armB*180>170) { a = 100; b = 100; } a = a/M_PI; b = b/M_PI; } int max(char dir, int pos) { double a,b; float high = (dir=='X') ? 35 : 44; float cur = (high/2); float low = 0; while(abs(high-low)>0.00001) { if(dir=='X') Point2Angles(cur, pos, a, b); else Point2Angles(pos, cur, a, b); if(a < 31 && b < 31) { low = cur; cur = (high+low)/2; if(cur>high) cur = high; } else { high = cur; cur = (high+low)/2; if(cur<low) cur = low; } } return (dir == 'X') ? low : (low-1); }