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: ExperimentServer QEI_pmw MotorShield
Revision 26:f67075d64cb3, committed 2021-12-04
- Comitter:
- davepreiss
- Date:
- Sat Dec 04 20:46:13 2021 +0000
- Parent:
- 25:52b378e89f42
- Commit message:
- davetrying to export;
Changed in this revision
| BezierCurve.cpp | Show annotated file Show diff for this revision Revisions of this file |
| main.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/BezierCurve.cpp Tue Sep 29 21:09:51 2020 +0000
+++ b/BezierCurve.cpp Sat Dec 04 20:46:13 2021 +0000
@@ -48,6 +48,7 @@
void BezierCurve::evaluate(float time, float point[]) {
//float *_point = new float[_dim];
+ // fill up point with dim number of zeros
for(int i=0; i< _dim ; i++) {
point[i] = 0;
}
--- a/main.cpp Tue Sep 29 21:09:51 2020 +0000
+++ b/main.cpp Sat Dec 04 20:46:13 2021 +0000
@@ -7,8 +7,11 @@
#include "MotorShield.h"
#include "HardwareSetup.h"
-#define BEZIER_ORDER_FOOT 7
-#define NUM_INPUTS (12 + 2*(BEZIER_ORDER_FOOT+1))
+#define BEZIER_ORDER_JUMP 7
+#define BEZIER_ORDER_FLIGHT 7
+#define BEZIER_ORDER_LAND 7
+
+#define NUM_INPUTS (12 + 2*(BEZIER_ORDER_JUMP+1) + 2*(BEZIER_ORDER_FLIGHT+1) + 2*(BEZIER_ORDER_LAND+1) + 2*(BEZIER_ORDER_FLIGHT+1))
#define NUM_OUTPUTS 19
#define PULSE_TO_RAD (2.0f*3.14159f / 1200.0f)
@@ -47,15 +50,16 @@
float angle2_init;
// Fixed kinematic parameters
-const float l_OA=.011;
-const float l_OB=.042;
+const float l_OA=.03673;
+const float l_OB=.06773;
const float l_AC=.096;
-const float l_DE=.091;
+const float l_DE=.127-(l_OB-l_OA);
// Timing parameters
float current_control_period_us = 200.0f; // 5kHz current control loop
float impedance_control_period_us = 1000.0f; // 1kHz impedance control loop
float start_period, traj_period, end_period;
+float jump_period, flight_period, land_period;
// Control parameters
float current_Kp = 4.0f;
@@ -75,11 +79,17 @@
float k_t = 0.18f; // motor torque constant
float nu = 0.0005; // motor viscous friction
+// Foot Sensor Parameters
+bool airborne = 0;
+bool landCheck = false;
+uint8_t gaitState = 0;
+uint8_t hopCount = 0;
+uint8_t hopCountLim = 4; // 0 means 1 hop
+
// Current control interrupt function
void CurrentLoop()
{
// This loop sets the motor voltage commands using PI current controllers with feedforward terms.
-
//use the motor shield as follows:
//motorShield.motorAWrite(DUTY CYCLE, DIRECTION), DIRECTION = 0 is forward, DIRECTION =1 is backwards.
@@ -127,9 +137,10 @@
int main (void)
{
-
// Object for 7th order Cartesian foot trajectory
- BezierCurve rDesFoot_bez(2,BEZIER_ORDER_FOOT);
+ BezierCurve rDesJump_bez(2,BEZIER_ORDER_JUMP);
+ BezierCurve rDesFlight_bez(2,BEZIER_ORDER_FLIGHT);
+ BezierCurve rDesLand_bez(2,BEZIER_ORDER_LAND);
// Link the terminal with our server and start it up
server.attachTerminal(pc);
@@ -139,16 +150,23 @@
float input_params[NUM_INPUTS];
pc.printf("%f",input_params[0]);
+ // Setup our foot sensor input
+ DigitalIn footContactPin(PC_6);
+
+ // NOW WE STAY IN THIS WHILE STATEMENT FOREVER -------------------------------------------------------------------
while(1) {
-
- // If there are new inputs, this code will run
+ // EVERYTHING IS NOW WAITING FOR SERIAL COMMUNICATION TO RUN BELOW, OTHERWISE WE ARE LOOPING THIS IF STATEMENT, this still only runs once per jump
if (server.getParams(input_params,NUM_INPUTS)) {
-
- // Get inputs from MATLAB
- start_period = input_params[0]; // First buffer time, before trajectory
- traj_period = input_params[1]; // Trajectory time/length
- end_period = input_params[2]; // Second buffer time, after trajectory
+ // Get inputs from MATLAB, note that these are formatted in Experiment_trajectory
+ gaitState = 0;
+ landCheck = 0;
+ start_period = 1.5; // removed it as a parameter but we have a 1 second delay before starting the jump
+ traj_period = 5.0;
+ end_period = 1.0;
+ jump_period = input_params[0]; // First buffer time, before trajectory
+ flight_period = input_params[1]; // Trajectory time/length
+ land_period = input_params[2]; // Second buffer time, after trajectory
angle1_init = input_params[3]; // Initial angle for q1 (rad)
angle2_init = input_params[4]; // Initial angle for q2 (rad)
@@ -161,12 +179,46 @@
D_xy = input_params[10]; // Foot damping N/(m/s)
duty_max = input_params[11]; // Maximum duty factor
- // Get foot trajectory points
- float foot_pts[2*(BEZIER_ORDER_FOOT+1)];
- for(int i = 0; i<2*(BEZIER_ORDER_FOOT+1);i++) {
- foot_pts[i] = input_params[12+i];
+ // Get foot trajectory points - start by initializing an empty array for each curve
+ float jump_pts[2*(BEZIER_ORDER_JUMP+1)]; // foot_pts is a matrix sized for the bezier order
+ float flight_pts[2*(BEZIER_ORDER_FLIGHT+1)];
+ float land_pts[2*(BEZIER_ORDER_LAND+1)];
+
+ // Now fill each array up with its respective points
+ for(int i = 0; i<2*(BEZIER_ORDER_JUMP+1);i++) {
+ jump_pts[i] = input_params[12+i]; // assign the proper input parameters to each foot position
+ flight_pts[i] = input_params[12+BEZIER_ORDER_JUMP+1 +i];
+ land_pts[i] = input_params[12+BEZIER_ORDER_JUMP+1 + BEZIER_ORDER_FLIGHT+1 +i];
+ // Adding this line to try and get the proper flight in
+ //flight_pts[i] = input_params[12+BEZIER_ORDER_JUMP+1 + BEZIER_ORDER_FLIGHT+1 + BEZIER_ORDER_FLIGHT+1 +i];
}
- rDesFoot_bez.setPoints(foot_pts);
+ //pc.printf("%f" " = flight points \n\r",flight_pts[1]);
+ //float flight_pts[2][8] = {{0.0651000,0.0650000,0.0650000,0.0417000,-0.0169000,-0.0700000,-0.0700000,-0.0700000},
+ //{-0.215000,-0.215000,-0.215000,-0.159700,-0.147000,-0.175000,-0.175000,-0.175100}};
+
+ flight_pts[0] = .065000;
+ flight_pts[1] = -.215000;
+ flight_pts[2] = .065000;
+ flight_pts[3] = -.215000;
+ flight_pts[4] = .065000;
+ flight_pts[5] = -.215000;
+ flight_pts[6] = .0417;
+ flight_pts[7] = -.1597;
+ flight_pts[8] = -.0169;
+ flight_pts[9] = -.147;
+ flight_pts[10] = -.0700000;
+ flight_pts[11] = -.175;
+ flight_pts[12] = -.0700000;
+ flight_pts[13] = -.175;
+ flight_pts[14] = -.0700000;
+ flight_pts[15] = -.175;
+
+
+ //pc.printf("%f" " = flight points \n\r",flight_pts[1]);
+
+ rDesJump_bez.setPoints(jump_pts);
+ rDesFlight_bez.setPoints(flight_pts);
+ rDesLand_bez.setPoints(land_pts);
// Attach current loop interrupt
currentLoop.attach_us(CurrentLoop,current_control_period_us);
@@ -181,14 +233,21 @@
motorShield.motorAWrite(0, 0); //turn motor A off
motorShield.motorBWrite(0, 0); //turn motor B off
+
+ hopCount = 0;
- // Run experiment
- while( t.read() < start_period + traj_period + end_period) {
-
+ // Run experiment HERE's THE REAL MAIN LOOP ---------------------------------------------------------------------------------------------------------------------------
+ while(gaitState < 5) {
+ //while( t.read() < 8.0) {
+ // Check to see if we are airborne or not, where airborne = 1 means we are not touching the ground
+ if(footContactPin == true) {
+ airborne = true;}
+ else {airborne = false;}
+ // pc.printf("%d" " = Airborne? \n\r",airborne); // confirmed to be working
+
// Read encoders to get motor states
angle1 = encoderA.getPulses() *PULSE_TO_RAD + angle1_init;
velocity1 = encoderA.getVelocity() * PULSE_TO_RAD;
-
angle2 = encoderB.getPulses() * PULSE_TO_RAD + angle2_init;
velocity2 = encoderB.getVelocity() * PULSE_TO_RAD;
@@ -198,55 +257,128 @@
const float dth2= velocity2;
// Calculate the Jacobian
- float Jx_th1 = 0;
- float Jx_th2 = 0;
- float Jy_th1 = 0;
- float Jy_th2 = 0;
+ float Jx_th1 = l_AC*cos(th1 + th2) + l_DE*cos(th1) + l_OB*cos(th1);
+ float Jx_th2 = l_AC*cos(th1 + th2);
+ float Jy_th1 = l_AC*sin(th1 + th2) + l_DE*sin(th1) + l_OB*sin(th1);
+ float Jy_th2 = l_AC*sin(th1 + th2);
// Calculate the forward kinematics (position and velocity)
- float xFoot = 0;
- float yFoot = 0;
- float dxFoot = 0;
- float dyFoot = 0;
+ float xFoot = l_AC*sin(th1 + th2) + l_DE*sin(th1) + l_OB*sin(th1);
+ float yFoot = - l_AC*cos(th1 + th2) - l_DE*cos(th1) - l_OB*cos(th1);
+ float dxFoot = dth1*(l_AC*cos(th1 + th2) + l_DE*cos(th1) + l_OB*cos(th1)) + dth2*l_AC*cos(th1 + th2);
+ float dyFoot = dth1*(l_AC*sin(th1 + th2) + l_DE*sin(th1) + l_OB*sin(th1)) + dth2*l_AC*sin(th1 + th2);
// Set gains based on buffer and traj times, then calculate desired x,y from Bezier trajectory at current time if necessary
float teff = 0;
float vMult = 0;
+
+
+ // HERE IS WHERE WE CHECK WHERE WE ARE IN THE GAIT ----------------------------------------------------------------------------------------------
+ // gaitState 0 is just a buffer time before the jump holding the intial position
if( t < start_period) {
if (K_xx > 0 || K_yy > 0) {
- K_xx = 1; // for joint space control, set this to 1; for Cartesian space control, set this to 50
- K_yy = 1; // for joint space control, set this to 1; for Cartesian space control, set this to 50
- D_xx = 0.1; // for joint space control, set this to 0.1; for Cartesian space control, set this to 2
- D_yy = 0.1; // for joint space control, set this to 0.1; for Cartesian space control, set this to 2
- K_xy = 0;
- D_xy = 0;
+ K_xx = input_params[5]; // Foot stiffness N/m
+ K_yy = input_params[6]; // Foot stiffness N/m
+ K_xy = input_params[7]; // Foot stiffness N/m
+ D_xx = input_params[8]; // Foot damping N/(m/s)
+ D_yy = input_params[9]; // Foot damping N/(m/s)
+ D_xy = input_params[10]; // Foot damping N/(m/s)
+ gaitState = 0;
}
teff = 0;
+ //pc.printf("%f" " Start Phase \n\r",teff);
}
- else if (t < start_period + traj_period)
- {
+ // Jump Phase = gait 1
+ else if (t < start_period + jump_period) {
+ // Lets only update the gains if we need to, this will be the last one for now
K_xx = input_params[5]; // Foot stiffness N/m
K_yy = input_params[6]; // Foot stiffness N/m
K_xy = input_params[7]; // Foot stiffness N/m
D_xx = input_params[8]; // Foot damping N/(m/s)
D_yy = input_params[9]; // Foot damping N/(m/s)
D_xy = input_params[10]; // Foot damping N/(m/s)
- teff = (t-start_period);
vMult = 1;
+ teff = (t - start_period);
+ gaitState = 1;
+// pc.printf("%f" " Jump Phase \n\r",teff);
+ }
+ // Flight Phase = gait 2, we should not be touching the ground here
+ // If t is lower than expected
+ else if (t < start_period + jump_period + land_period + 1.6 && landCheck == false) {
+ teff = (t - start_period - jump_period);
+ gaitState = 2;
+// pc.printf("%f" " Flight Phase \n\r",teff);
+
+ // If we land, or if we are 1 second past the expected flight phase, continue to the land gait
+ if (airborne == 0 || t > start_period + jump_period + flight_period + 1.5) {
+// pc.printf("%f" " < FLIGHT PHASE OVER, AIRBORNE FOR THIS LONG \n\r",teff);
+ landCheck = true;
+ flight_period = (t - start_period - jump_period);
+ gaitState = 3;
+ teff = (t - start_period - jump_period - flight_period);
+ }
}
- else
- {
- teff = traj_period;
- vMult = 0;
+ // Land Phase = gait 3
+ else if (gaitState == 3) {
+ teff = (t - start_period - jump_period - flight_period);
+ gaitState = 3;
+// pc.printf("%f" " Land Phase \n\r",teff);
+ if (t > start_period + jump_period + flight_period + land_period) {
+ gaitState = 4;
+ vMult = 0;
+ }
+ }
+ else {
+ if (hopCount <= hopCountLim) {
+ hopCount = hopCount + 1;
+ t.reset();
+ t.start();
+ }
+ else {
+ gaitState = 5;
+ vMult = 0;
+ }
+ hopCount = hopCount + 1;
}
- // Get desired foot positions and velocities
+ // Get desired foot positions and velocities
float rDesFoot[2] , vDesFoot[2];
- rDesFoot_bez.evaluate(teff/traj_period,rDesFoot);
- rDesFoot_bez.evaluateDerivative(teff/traj_period,vDesFoot);
- vDesFoot[0]/=traj_period;
- vDesFoot[1]/=traj_period;
- vDesFoot[0]*=vMult;
+ // Evaluate the correct gait (bezier curve) at the % detemined by how far into teff we are. There are 4 gaitStates...
+ if (gaitState == 0){
+ rDesFoot[0] = jump_pts[0];
+ rDesFoot[1] = jump_pts[1];
+ vDesFoot[0] = 0.0;
+ vDesFoot[1] = 0.0;
+ }
+ else if (gaitState == 1){
+// pc.printf("%d" " 1=JUMP \n\r",gaitState);
+ rDesJump_bez.evaluate(teff/jump_period, rDesFoot);
+ rDesJump_bez.evaluateDerivative(teff/jump_period, vDesFoot);
+ vDesFoot[0] /= jump_period;
+ vDesFoot[1] /= jump_period;
+ }
+ else if (gaitState == 2){
+// pc.printf("%d" " 2=FLIGHT \n\r",gaitState);
+ rDesFlight_bez.evaluate(teff/flight_period, rDesFoot);
+ rDesFlight_bez.evaluateDerivative(teff/flight_period, vDesFoot);
+ vDesFoot[0] /= flight_period;
+ vDesFoot[1] /= flight_period;
+ if (teff > jump_period) {
+ rDesFoot[0] = flight_pts[14];
+ rDesFoot[1] = flight_pts[15];
+ vDesFoot[0] = 0.0;
+ vDesFoot[1] = 0.0;
+ }
+ }
+ else if (gaitState == 3){
+// pc.printf("%d" " 3=LAND \n\r",gaitState);
+ rDesLand_bez.evaluate(teff/land_period, rDesFoot);
+ rDesLand_bez.evaluateDerivative(teff/land_period, vDesFoot);
+ vDesFoot[0] /= land_period;
+ vDesFoot[1] /= land_period;
+ }
+ // if we are past the trajectory period multiply by 0
+ vDesFoot[0]*=vMult;
vDesFoot[1]*=vMult;
// Calculate the inverse kinematics (joint positions and velocities) for desired joint angles
@@ -262,34 +394,41 @@
float dth2_des = (1.0f/dd) * ( -Jy_th1*vDesFoot[0] + Jx_th1*vDesFoot[1] );
// Calculate error variables
- float e_x = 0;
- float e_y = 0;
- float de_x = 0;
- float de_y = 0;
+ float e_x = xFoot_inv - xFoot;
+ float e_y = yFoot_inv - yFoot;
+ float de_x = vDesFoot[0] - dxFoot;
+ float de_y = vDesFoot[1] - dyFoot;
// Calculate virtual force on foot
- float fx = 0;
- float fy = 0;
-
- // Set desired currents
- current_des1 = 0;
- current_des2 = 0;
-
+ float fx = K_xx*(e_x) + K_xy*(e_y) + D_xx*(de_x) + D_xy*(de_y);
+ float fy = K_xy*(e_x) + K_yy*(e_y) + D_xy*(de_x) + D_yy*(de_y);
+
+ float tau1 = Jx_th1*fx + Jy_th1*fy;
+ float tau2 = Jx_th2*fx + Jy_th2*fy;
+
+ current_des1 = tau1/k_t;
+ current_des2 = tau2/k_t;
+
+ // All of the above was to set these current_des values which will get fed into the CurrentLoop function running on an interrupt
+
// Joint impedance
// sub Kxx for K1, Dxx for D1, Kyy for K2, Dyy for D2
// Note: Be careful with signs now that you have non-zero desired angles!
// Your equations should be of the form i_d = K1*(q1_d - q1) + D1*(dq1_d - dq1)
-// current_des1 = 0;
-// current_des2 = 0;
-
+ //current_des1 = (K_xx*(angle1_init - angle1) + D_xx*(0.0 - velocity1))/k_t;
+ //current_des2 = (K_yy*(angle2_init - angle2) + D_yy*(0.0 - velocity2))/k_t;
+ //current_des1 = 0;
+ //current_des2 = 0;
+
// Cartesian impedance
// Note: As with the joint space laws, be careful with signs!
-// current_des1 = 0;
-// current_des2 = 0;
+ //current_des1 = (K_xx*(th1_des - angle1) + D_xx*(th1_des - velocity1))/k_t;
+ //current_des2 = (K_yy*(th2_des - angle2) + D_yy*(th2_des - velocity2))/k_t;
// Form output to send to MATLAB
float output_data[NUM_OUTPUTS];
+
// current time
output_data[0] = t.read();
// motor 1 state
@@ -332,3 +471,24 @@
} // end main
+/*
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[0]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[1]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[2]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[3]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[4]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[5]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[6]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[7]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[8]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[9]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[10]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[11]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[12]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[13]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[14]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[15]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[16]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[17]);
+pc.printf("%f" " OUTPUT DATA 0 \n\r",output_data[18]);
+*/
\ No newline at end of file