Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: HIDScope MODSERIAL QEI biquadFilter mbed
Fork of Robot-Software_jesse by
main.cpp
- Committer:
- Spekdon
- Date:
- 2018-10-31
- Revision:
- 14:c4dbce7de430
- Parent:
- 13:3482d315877c
File content as of revision 14:c4dbce7de430:
#include "mbed.h" #include "MODSERIAL.h" #include "QEI.h" #include "BiQuad.h" #include "math.h" #include <vector> // CHECK PwmOut pwmpin(D6); PwmOut pwmpin2(D5); DigitalOut directionpin2(D4); DigitalOut directionpin(D7); MODSERIAL pc(USBTX, USBRX); //Serial pc(USBTX, USBRX); QEI wheel2 (D13, D12, NC, 32, QEI::X2_ENCODING); QEI wheel1 (D11, D10, NC, 32, QEI::X2_ENCODING); float u1,u2 = 0; // for trajectory control: double T = 1; // time to get to destination double currentx, currenty; double currentq1, currentq2; // end int pulses1, pulses2 = 0; float angle1, angle2; int realangle1, realangle2; double error1; double error2; double actualoutput1, actualoutput2 = 0; bool reached; Ticker adjust_ref; Ticker pid; float angle_resolution = (360.0/32.0)*(1.0/131.0); //degrees/counts double Kp = 0.1; double Ki = 0.4; double Kd = 4; extern double samplingfreq = 1000; double L1 = 0.4388; double L2 = 0.4508; double x01 = 0.0; double y01 = 0.0; double ref1, ref2; double t = 0.0; vector<double> inv_kin_ref; vector<double> newconfig; vector<double> currentxy; double timetogetthere = 0.01; double vx_des = 0.05; double vy_des = -0.05; float maxpwm = 1; void PID_controller(double error1, double error2, float &u1, float &u2, double actualoutput1, double actualoutput2) { static double error_prev1 = error1; // initialization with this value only done once! static double error_prev2 = error2; // initialization with this value only done once! double u_pid2, u_pid1; static double error_integral1, error_integral2 = 0; double u_k1 = Kp * error1; double u_k2 = Kp * error2; static BiQuad LowPassFilter1(0.0640, 0.1279, 0.0640, -1.1683, 0.4241); static BiQuad LowPassFilter2(0.0640, 0.1279, 0.0640, -1.1683, 0.4241); double error_derivative1 = (error1 - error_prev1)*1/samplingfreq; double filtered_error_derivative1 = LowPassFilter1.step(error_derivative1); double u_d1 = Kd * filtered_error_derivative1; double error_derivative2 = (error2 - error_prev2)*1/samplingfreq; double filtered_error_derivative2 = LowPassFilter2.step(error_derivative2); double u_d2 = Kd * filtered_error_derivative2; error_integral1 = error_integral1 +( error1 * 1/samplingfreq); error_integral2 = error_integral2 +( error2 * 1/samplingfreq); if (error_integral1 > 1){ error_integral1 = 1; } else if (error_integral1 < -1){ error_integral1 = -1; } if (error_integral2 > 1){ error_integral2 = 1; } else if (error_integral2 < -1){ error_integral2 = -1; } double u_i1 = Ki*error_integral1; double u_i2 = Ki*error_integral2; u_pid1 = u_k1 + u_d1 + u_i1; u_pid2 = u_k2 + u_d2 + u_i2; u1 = -u_pid1; u2 = -u_pid2; error_prev1 = error1; error_prev2 = error2; } vector<double> forwardkinematics_function(double& q1, double& q2) { // input are joint angles, output are x and y position of end effector q1 = (q1 + 90)*(3.14/180); q2 = (q2 + 180)*(3.14/180); currentx = x01 + L1*cos(q1)-L2*cos(q2); currenty = y01 + L1 * sin(q1) - L2 * sin(q2); vector<double> xy; xy.push_back(currentx); xy.push_back(currenty); return xy; } vector<double> inversekinematics_function(const double& T, double& q1, double& q2, double& des_vx, double& des_vy, double ref1, double ref2) { // x, y: positions of end effector | T: time to hold current velocity | qref1, qref2: reference thetas | q1, q2: current thetas | vx, vy: desired x, y velocities // pseudo inverse jacobian to get joint speeds // input are desired vx and vy of end effector, output joint angle speeds double q1_star_des; // desired joint velocity of q1_star double q2_star_des; // same as above but then for q2_star double C; double qref1, qref2; // The calculation below assumes that the end effector position is calculated before this function is executed // In our case the determinant will not equal zero, hence no problems with singularies I think. // // q1 = (ref1 + 90)*(3.14/180); q2 = (ref2 + 180)*(3.14/180); C = L1*L2*sin(q1)*cos(q2) - L1*L2*sin(q2)*cos(q1); q1_star_des = double(1/C)*(-L2*cos(q2)*des_vy - L2*sin(q2)*des_vx); q2_star_des = double(1/C)*((L2*cos(q2)-L1*cos(q1))*des_vy + (L2*sin(q2)-L1*sin(q1))*des_vx); qref1 = T*q1_star_des; qref2 = T*(q2_star_des+q1_star_des); qref1 = qref1*(180/3.14); qref2 = qref2*(180/3.14); double testq1 = ref1+qref1; double testq2 = ref2+qref2; newconfig = forwardkinematics_function(testq1, testq2); if (sqrt(pow(newconfig[0],2)+pow(newconfig[1],2)) > 0.73) { qref1 = ref1; qref2 = ref2; } else { qref1 = ref1 + qref1; qref2 = ref2 + qref2; } vector<double> thetas; thetas.push_back(qref1); thetas.push_back(qref2); return thetas; } void control(){ // Calculate angle of motor 1 pulses1 = wheel1.getPulses(); angle1 = -pulses1*angle_resolution; realangle1 = int(angle1) % 360; // Calculate angle of motor 2 pulses2 = wheel2.getPulses(); angle2 = pulses2*angle_resolution; realangle2 = int(angle2) % 360; // Q1 and Q2 current currentq1 = angle1; currentq2 = angle2; // modify the current x and y pos currentxy = forwardkinematics_function(currentq1, currentq2); currentx = currentxy[0]; currenty = currentxy[1]; // calculate the reference position using inverse kinematics: inv_kin_ref = inversekinematics_function(timetogetthere, currentq1, currentq2, vx_des, vy_des, ref1, ref2); ref1 = inv_kin_ref[0]; ref2 = inv_kin_ref[1]; error1 = ref1 - realangle1; error2 = ref2 - realangle2; // control stuff: PID_controller(error1, error2, u1, u2, actualoutput1, actualoutput2); // Check if output is larger than maximum pwm if (abs(u1) > maxpwm){ if (u1 > 0){ u1 = maxpwm; } else{ u1 = -maxpwm; } } if (abs(u2) > maxpwm){ if (u2 > 0){ u2 = maxpwm; } else{ u2 = -maxpwm; } } pwmpin = fabs(u1); pwmpin2 = fabs(u2); // 1/true is negative, 0/false is positive directionpin2 = u2 < 0; directionpin = u1 < 0; } void measure() { } int main() { pc.baud(115200); pwmpin.period_us(60); pid.attach(&control,0.01); ref1 = 0; ref2 = 0; while (true) { pc.printf("error1: %f, error2: %f, pwm1: %f, pwm2: %f \r \n", error1, error2, u1, u2); vector<double> currentthing; currentthing = forwardkinematics_function(ref1,ref2); double cx = currentthing[0]; double cy = currentthing[1]; pc.printf("x: %f, y: %f \r\n",cx,cy); } }