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: ros_lib_kinetic
main.cpp@18:6533fb7f5a91, 2018-10-10 (annotated)
- Committer:
 - WD40andTape
 - Date:
 - Wed Oct 10 13:36:57 2018 +0000
 - Revision:
 - 18:6533fb7f5a91
 - Parent:
 - 17:bbaf3e8440ad
 - Child:
 - 19:e5acb2183d4e
 
Temporarily disabling sensor feedback due to lag.
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| WD40andTape | 7:5b6a2cefbf3b | 1 | // STANDARD IMPORTS | 
| WD40andTape | 7:5b6a2cefbf3b | 2 | #include "math.h" | 
| WD40andTape | 7:5b6a2cefbf3b | 3 | // MBED IMPORTS | 
| dofydoink | 0:607bc887b6e0 | 4 | #include "mbed.h" | 
| WD40andTape | 6:f0a18e28a322 | 5 | #include "mbed_events.h" | 
| WD40andTape | 7:5b6a2cefbf3b | 6 | // CUSTOM IMPORTS | 
| dofydoink | 12:595ed862e52f | 7 | #include "MLSettings.h" | 
| WD40andTape | 7:5b6a2cefbf3b | 8 | #include "HLComms.h" | 
| WD40andTape | 8:d6657767a182 | 9 | #include "LLComms.h" | 
| dofydoink | 0:607bc887b6e0 | 10 | |
| WD40andTape | 13:a373dfc57b89 | 11 | //DigitalOut pinTesty(PB_8); | 
| WD40andTape | 13:a373dfc57b89 | 12 | |
| dofydoink | 12:595ed862e52f | 13 | // Maximum achievable mm path tolerance plus additional % tolerance | 
| dofydoink | 12:595ed862e52f | 14 | const float FLT_PATH_TOLERANCE = MAX_SPEED_MMPS * PATH_SAMPLE_TIME_S * (1.0f+FLT_PERCENT_PATH_TOLERANCE); | 
| dofydoink | 0:607bc887b6e0 | 15 | |
| WD40andTape | 7:5b6a2cefbf3b | 16 | // PATH VARIABLES | 
| WD40andTape | 7:5b6a2cefbf3b | 17 | double dblVelocity_mmps[N_CHANNELS] = { 0.0 }; // The linear path velocity (not sent to actuator) | 
| WD40andTape | 16:1e2804a4e5bd | 18 | double dblLinearPathCurrentPos_mm[N_CHANNELS]= { 0.0 }; // The current position of the linear path (not sent to actuator) | 
| WD40andTape | 7:5b6a2cefbf3b | 19 | double dblTargetActPos_mm[N_CHANNELS] = { 0.0 }; // The final target position for the actuator | 
| dofydoink | 0:607bc887b6e0 | 20 | |
| dofydoink | 12:595ed862e52f | 21 | // These have to be declared in the global scope or we get a stack overflow. No idea why. | 
| dofydoink | 11:7029367a1840 | 22 | double _dblVelocity_mmps[N_CHANNELS]; | 
| dofydoink | 12:595ed862e52f | 23 | //double _dblLinearPathCurrentPos_mm[N_CHANNELS]; | 
| dofydoink | 12:595ed862e52f | 24 | double dblADCCurrentPosition[N_CHANNELS]; | 
| dofydoink | 11:7029367a1840 | 25 | |
| WD40andTape | 7:5b6a2cefbf3b | 26 | Serial pc(USBTX, USBRX); // tx, rx for usb debugging | 
| dofydoink | 12:595ed862e52f | 27 | LLComms llcomms; | 
| WD40andTape | 16:1e2804a4e5bd | 28 | HLComms hlcomms(SERVER_PORT); | 
| WD40andTape | 3:c83291bf9fd2 | 29 | |
| WD40andTape | 10:1b6daba32452 | 30 | Thread threadLowLevelSPI(osPriorityRealtime); | 
| WD40andTape | 13:a373dfc57b89 | 31 | Thread threadSmoothPathPlan(osPriorityNormal); | 
| WD40andTape | 4:303584310071 | 32 | Thread threadReceiveAndReplan(osPriorityBelowNormal); | 
| WD40andTape | 17:bbaf3e8440ad | 33 | Thread threadSensorFeedback(osPriorityBelowNormal); | 
| dofydoink | 0:607bc887b6e0 | 34 | |
| WD40andTape | 4:303584310071 | 35 | Mutex mutPathIn; | 
| WD40andTape | 7:5b6a2cefbf3b | 36 | Semaphore semPathPlan(1); | 
| WD40andTape | 17:bbaf3e8440ad | 37 | Semaphore semSensorData(1); | 
| dofydoink | 0:607bc887b6e0 | 38 | |
| WD40andTape | 7:5b6a2cefbf3b | 39 | Timer timer; | 
| WD40andTape | 7:5b6a2cefbf3b | 40 | Ticker PathCalculationTicker; | 
| WD40andTape | 17:bbaf3e8440ad | 41 | Ticker SendSensorDataTicker; | 
| WD40andTape | 17:bbaf3e8440ad | 42 | |
| WD40andTape | 17:bbaf3e8440ad | 43 | |
| WD40andTape | 17:bbaf3e8440ad | 44 | void sendSensorData() { | 
| WD40andTape | 17:bbaf3e8440ad | 45 | while( true ) { | 
| WD40andTape | 17:bbaf3e8440ad | 46 | semSensorData.wait(); | 
| WD40andTape | 17:bbaf3e8440ad | 47 | double pressures[N_CHANNELS]; | 
| WD40andTape | 17:bbaf3e8440ad | 48 | // !!! READ ADC PRESSURE ASSUMES THAT LL ARE ON FIRST | 
| WD40andTape | 17:bbaf3e8440ad | 49 | for(short int i=0; i<N_CHANNELS; i++) { | 
| WD40andTape | 17:bbaf3e8440ad | 50 | pressures[i] = llcomms.ReadADCPressure_bar(i); | 
| WD40andTape | 17:bbaf3e8440ad | 51 | } | 
| WD40andTape | 17:bbaf3e8440ad | 52 | int error_code = hlcomms.send_sensor_message(dblLinearPathCurrentPos_mm,pressures); | 
| WD40andTape | 17:bbaf3e8440ad | 53 | /*if( error_code < 0 ) { | 
| WD40andTape | 17:bbaf3e8440ad | 54 | if(IS_PRINT_OUTPUT) printf("Error %i. Could not send data over the TCP socket. " | 
| WD40andTape | 17:bbaf3e8440ad | 55 | "Perhaps the server socket is not bound or not set to listen for connections? " | 
| WD40andTape | 17:bbaf3e8440ad | 56 | "Or the socket is set to non-blocking or timed out?\n\r", error_code); | 
| WD40andTape | 17:bbaf3e8440ad | 57 | hlcomms.close_server(); | 
| WD40andTape | 17:bbaf3e8440ad | 58 | return; | 
| WD40andTape | 17:bbaf3e8440ad | 59 | }*/ | 
| WD40andTape | 17:bbaf3e8440ad | 60 | } | 
| WD40andTape | 17:bbaf3e8440ad | 61 | } | 
| WD40andTape | 17:bbaf3e8440ad | 62 | |
| WD40andTape | 17:bbaf3e8440ad | 63 | void signalSendSensorData() { | 
| WD40andTape | 17:bbaf3e8440ad | 64 | semSensorData.release(); | 
| WD40andTape | 17:bbaf3e8440ad | 65 | } | 
| dofydoink | 0:607bc887b6e0 | 66 | |
| WD40andTape | 7:5b6a2cefbf3b | 67 | void startPathPlan() { // Plan a new linear path after receiving new target data | 
| WD40andTape | 4:303584310071 | 68 | semPathPlan.release(); // Uses threadReceiveAndReplan which is below normal priority to ensure consistent transmission to LL | 
| dofydoink | 0:607bc887b6e0 | 69 | } | 
| dofydoink | 0:607bc887b6e0 | 70 | |
| WD40andTape | 7:5b6a2cefbf3b | 71 | // This function will be called when a new transmission is received from high level | 
| WD40andTape | 7:5b6a2cefbf3b | 72 | void ReceiveAndReplan() { | 
| WD40andTape | 6:f0a18e28a322 | 73 | |
| WD40andTape | 6:f0a18e28a322 | 74 | int error_code; | 
| WD40andTape | 7:5b6a2cefbf3b | 75 | error_code = hlcomms.setup_server(); | 
| WD40andTape | 6:f0a18e28a322 | 76 | if( error_code == -1 ) return; | 
| WD40andTape | 7:5b6a2cefbf3b | 77 | error_code = hlcomms.accept_connection(); | 
| WD40andTape | 7:5b6a2cefbf3b | 78 | if( error_code == -1 ) { | 
| WD40andTape | 7:5b6a2cefbf3b | 79 | hlcomms.close_server(); | 
| WD40andTape | 7:5b6a2cefbf3b | 80 | return; | 
| WD40andTape | 7:5b6a2cefbf3b | 81 | } | 
| WD40andTape | 6:f0a18e28a322 | 82 | |
| WD40andTape | 18:6533fb7f5a91 | 83 | SendSensorDataTicker.attach(&signalSendSensorData, 0.1); // Set up planning thread to recur at fixed intervals | 
| WD40andTape | 17:bbaf3e8440ad | 84 | |
| WD40andTape | 7:5b6a2cefbf3b | 85 | int ii; | 
| WD40andTape | 7:5b6a2cefbf3b | 86 | struct msg_format input; //hlcomms.msg_format | 
| WD40andTape | 4:303584310071 | 87 | |
| WD40andTape | 6:f0a18e28a322 | 88 | while( true ) { | 
| WD40andTape | 6:f0a18e28a322 | 89 | // RECEIVE MESSAGE | 
| WD40andTape | 9:cd3607ba5643 | 90 | error_code = hlcomms.receive_message(); | 
| WD40andTape | 6:f0a18e28a322 | 91 | if( error_code == NSAPI_ERROR_NO_CONNECTION ) { // -3004 | 
| dofydoink | 12:595ed862e52f | 92 | if(IS_PRINT_OUTPUT) printf("Client disconnected.\n\r"); | 
| WD40andTape | 7:5b6a2cefbf3b | 93 | hlcomms.close_server(); | 
| WD40andTape | 6:f0a18e28a322 | 94 | return; | 
| WD40andTape | 6:f0a18e28a322 | 95 | } else if( error_code < 0 ) { | 
| dofydoink | 12:595ed862e52f | 96 | if(IS_PRINT_OUTPUT) printf("Error %i. Could not send data over the TCP socket. " | 
| WD40andTape | 6:f0a18e28a322 | 97 | "Perhaps the server socket is not connected to a remote host? " | 
| WD40andTape | 6:f0a18e28a322 | 98 | "Or the socket is set to non-blocking or timed out?\n\r", error_code); | 
| WD40andTape | 7:5b6a2cefbf3b | 99 | hlcomms.close_server(); | 
| WD40andTape | 6:f0a18e28a322 | 100 | return; | 
| WD40andTape | 6:f0a18e28a322 | 101 | } | 
| WD40andTape | 17:bbaf3e8440ad | 102 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! RECV MUTEX | 
| WD40andTape | 9:cd3607ba5643 | 103 | input = hlcomms.process_message(); | 
| WD40andTape | 1:2a43cf183a62 | 104 | |
| WD40andTape | 7:5b6a2cefbf3b | 105 | // PROCESS INPUT | 
| WD40andTape | 7:5b6a2cefbf3b | 106 | double dblTargetChambLen_mm[N_CHANNELS]; // The currenly assigned final target position (actuator will reach this at end of path) | 
| dofydoink | 12:595ed862e52f | 107 | if(IS_PRINT_OUTPUT) printf("REPLAN, %f\r\n",input.duration); | 
| WD40andTape | 14:54c3759e76ed | 108 | |
| WD40andTape | 14:54c3759e76ed | 109 | //update rear Segment | 
| dofydoink | 11:7029367a1840 | 110 | dblTargetChambLen_mm[3] = input.psi[0][0]*1000; | 
| WD40andTape | 14:54c3759e76ed | 111 | dblTargetChambLen_mm[5] = 0.0;//input.psi[0][1]*1000;//not used | 
| WD40andTape | 14:54c3759e76ed | 112 | dblTargetChambLen_mm[6] = 0.0;//input.psi[0][2]*1000;//not used | 
| WD40andTape | 14:54c3759e76ed | 113 | |
| WD40andTape | 14:54c3759e76ed | 114 | //update mid segment | 
| WD40andTape | 14:54c3759e76ed | 115 | dblTargetChambLen_mm[4] = input.psi[1][0]*1000; | 
| WD40andTape | 14:54c3759e76ed | 116 | dblTargetChambLen_mm[7] = dblTargetChambLen_mm[4]; // Same because two pumps are used | 
| WD40andTape | 14:54c3759e76ed | 117 | |
| WD40andTape | 14:54c3759e76ed | 118 | // Update front segment | 
| dofydoink | 11:7029367a1840 | 119 | dblTargetChambLen_mm[0] = input.psi[2][0]*1000; | 
| dofydoink | 11:7029367a1840 | 120 | dblTargetChambLen_mm[1] = input.psi[2][1]*1000; | 
| dofydoink | 11:7029367a1840 | 121 | dblTargetChambLen_mm[2] = input.psi[2][2]*1000; | 
| dofydoink | 11:7029367a1840 | 122 | |
| dofydoink | 11:7029367a1840 | 123 | mutPathIn.lock(); // Lock variables to avoid race condition | 
| dofydoink | 12:595ed862e52f | 124 | for(int j = 0; j<N_CHANNELS; j++) { | 
| dofydoink | 12:595ed862e52f | 125 | dblADCCurrentPosition[j] = dblLinearPathCurrentPos_mm[j]; | 
| dofydoink | 12:595ed862e52f | 126 | //dblADCCurrentPosition[j] = llcomms.ReadADCPosition_mtrs(j); // Read position from channel | 
| dofydoink | 11:7029367a1840 | 127 | } | 
| dofydoink | 12:595ed862e52f | 128 | |
| dofydoink | 11:7029367a1840 | 129 | mutPathIn.unlock(); // Unlock mutex | 
| dofydoink | 0:607bc887b6e0 | 130 | |
| WD40andTape | 13:a373dfc57b89 | 131 | //bool isTimeChanged = 0; | 
| WD40andTape | 6:f0a18e28a322 | 132 | double dblMaxRecalculatedTime = input.duration; | 
| WD40andTape | 13:a373dfc57b89 | 133 | // Convert from requested chamber to actuator space and limit actuator positions | 
| WD40andTape | 4:303584310071 | 134 | for (ii = 0; ii< N_CHANNELS; ii++) { | 
| WD40andTape | 13:a373dfc57b89 | 135 | // If sent a negative requested position, do NOT replan that actuator | 
| WD40andTape | 14:54c3759e76ed | 136 | if( dblTargetChambLen_mm[ii] < 0.0 ) continue; | 
| dofydoink | 0:607bc887b6e0 | 137 | //check to see if positions are achievable | 
| dofydoink | 12:595ed862e52f | 138 | dblTargetActPos_mm[ii] = dblTargetChambLen_mm[ii]*FLT_ACTUATOR_CONVERSION[ii]; | 
| WD40andTape | 15:59471daef4cb | 139 | dblTargetActPos_mm[ii] = min( max( 0.0 , dblTargetActPos_mm[ii] ) , 40.0 ); | 
| WD40andTape | 6:f0a18e28a322 | 140 | //!! LIMIT CHAMBER LENGTHS TOO | 
| WD40andTape | 6:f0a18e28a322 | 141 | } | 
| WD40andTape | 13:a373dfc57b89 | 142 | // Calculate achievable velocities, and hence time, for the requested move to complete within tolerance | 
| WD40andTape | 6:f0a18e28a322 | 143 | double dblActPosChange; | 
| WD40andTape | 6:f0a18e28a322 | 144 | short sgn; | 
| WD40andTape | 7:5b6a2cefbf3b | 145 | for (ii = 0; ii< N_CHANNELS; ii++) { // Work out new velocities | 
| WD40andTape | 13:a373dfc57b89 | 146 | // If sent a negative requested position, do NOT replan that actuator | 
| WD40andTape | 14:54c3759e76ed | 147 | if( dblTargetChambLen_mm[ii] < 0.0 ) continue; | 
| WD40andTape | 13:a373dfc57b89 | 148 | |
| WD40andTape | 17:bbaf3e8440ad | 149 | //dblActPosChange = 1.0; // or = 0.0; | 
| WD40andTape | 17:bbaf3e8440ad | 150 | //_dblVelocity_mmps[ii] = 0.0; // DOESN'T CRASH | 
| WD40andTape | 17:bbaf3e8440ad | 151 | |
| WD40andTape | 17:bbaf3e8440ad | 152 | //dblActPosChange = dblTargetActPos_mm[ii]; | 
| WD40andTape | 17:bbaf3e8440ad | 153 | //_dblVelocity_mmps[ii] = 0.0; // DOESN'T CRASH | 
| WD40andTape | 17:bbaf3e8440ad | 154 | |
| WD40andTape | 17:bbaf3e8440ad | 155 | //dblActPosChange = _dblLinearPathCurrentPos_mm[ii]; // DOESN'T CRASH | 
| WD40andTape | 17:bbaf3e8440ad | 156 | |
| WD40andTape | 17:bbaf3e8440ad | 157 | //_dblVelocity_mmps[ii] = _dblLinearPathCurrentPos_mm[ii]; // DOESN'T CRASH | 
| WD40andTape | 17:bbaf3e8440ad | 158 | |
| WD40andTape | 17:bbaf3e8440ad | 159 | //dblActPosChange = 0.0; | 
| WD40andTape | 17:bbaf3e8440ad | 160 | //_dblVelocity_mmps[ii] = _dblLinearPathCurrentPos_mm[ii]; // DOESN'T CRASH | 
| dofydoink | 11:7029367a1840 | 161 | |
| dofydoink | 11:7029367a1840 | 162 | // DOES CRASH but not with a return at the end of while OR if _ variables are declared globally | 
| WD40andTape | 17:bbaf3e8440ad | 163 | //dblActPosChange = _dblLinearPathCurrentPos_mm[ii]; | 
| WD40andTape | 17:bbaf3e8440ad | 164 | //_dblVelocity_mmps[ii] = 0.0; | 
| dofydoink | 11:7029367a1840 | 165 | |
| dofydoink | 12:595ed862e52f | 166 | dblActPosChange = dblTargetActPos_mm[ii] - dblADCCurrentPosition[ii]; | 
| WD40andTape | 13:a373dfc57b89 | 167 | if( fabs(dblActPosChange) < FLT_PATH_TOLERANCE ) { // If actuator ii is already within tolerance | 
| WD40andTape | 6:f0a18e28a322 | 168 | dblActPosChange = 0.0; | 
| WD40andTape | 13:a373dfc57b89 | 169 | //isTimeChanged = 1; | 
| dofydoink | 0:607bc887b6e0 | 170 | } | 
| dofydoink | 11:7029367a1840 | 171 | //IS BELOW | 
| WD40andTape | 13:a373dfc57b89 | 172 | if( input.duration < 0.000000001 ) { // If max (safe) velocity was requested | 
| WD40andTape | 6:f0a18e28a322 | 173 | sgn = (dblActPosChange > 0) ? 1 : ((dblActPosChange < 0) ? -1 : 0); | 
| dofydoink | 11:7029367a1840 | 174 | _dblVelocity_mmps[ii] = sgn * MAX_SPEED_MMPS; | 
| WD40andTape | 13:a373dfc57b89 | 175 | //isTimeChanged = 1; | 
| WD40andTape | 6:f0a18e28a322 | 176 | } else { | 
| dofydoink | 11:7029367a1840 | 177 | _dblVelocity_mmps[ii] = dblActPosChange / input.duration; | 
| WD40andTape | 6:f0a18e28a322 | 178 | } | 
| dofydoink | 11:7029367a1840 | 179 | //IS ABOVE | 
| WD40andTape | 13:a373dfc57b89 | 180 | // Check to see if velocities are achievable -- this can move into the else section of the above if statement | 
| dofydoink | 11:7029367a1840 | 181 | if(abs(_dblVelocity_mmps[ii]) > MAX_SPEED_MMPS) { | 
| dofydoink | 11:7029367a1840 | 182 | if(_dblVelocity_mmps[ii]>0) { | 
| dofydoink | 11:7029367a1840 | 183 | _dblVelocity_mmps[ii] = MAX_SPEED_MMPS; | 
| WD40andTape | 6:f0a18e28a322 | 184 | } else { | 
| dofydoink | 11:7029367a1840 | 185 | _dblVelocity_mmps[ii] = -1*MAX_SPEED_MMPS; | 
| WD40andTape | 6:f0a18e28a322 | 186 | } | 
| WD40andTape | 13:a373dfc57b89 | 187 | //isTimeChanged = 1; | 
| WD40andTape | 6:f0a18e28a322 | 188 | } | 
| WD40andTape | 13:a373dfc57b89 | 189 | // Recalculate the move's time after altering the position and/or velocity | 
| WD40andTape | 6:f0a18e28a322 | 190 | double dblRecalculatedTime; | 
| dofydoink | 11:7029367a1840 | 191 | if( fabs(_dblVelocity_mmps[ii]) < 0.000000001 ) { | 
| WD40andTape | 6:f0a18e28a322 | 192 | dblRecalculatedTime = 0; | 
| WD40andTape | 6:f0a18e28a322 | 193 | } else { | 
| dofydoink | 11:7029367a1840 | 194 | dblRecalculatedTime = dblActPosChange / _dblVelocity_mmps[ii]; | 
| WD40andTape | 6:f0a18e28a322 | 195 | } | 
| WD40andTape | 13:a373dfc57b89 | 196 | // Find the maximum time for any actuator's move for synchronization | 
| WD40andTape | 6:f0a18e28a322 | 197 | if( dblRecalculatedTime > dblMaxRecalculatedTime ) { | 
| WD40andTape | 6:f0a18e28a322 | 198 | dblMaxRecalculatedTime = dblRecalculatedTime; | 
| WD40andTape | 6:f0a18e28a322 | 199 | } | 
| WD40andTape | 6:f0a18e28a322 | 200 | } | 
| WD40andTape | 13:a373dfc57b89 | 201 | // Finally recalculate all of the velocities based upon this maximum time for synchronization | 
| WD40andTape | 13:a373dfc57b89 | 202 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!MUTEX FOR dblVelocity_mmps and dblTargetActPos_mm?? | 
| WD40andTape | 13:a373dfc57b89 | 203 | for (ii = 0; ii< N_CHANNELS; ii++) { // Work out new velocities | 
| WD40andTape | 13:a373dfc57b89 | 204 | // If sent a negative requested position, do NOT replan that actuator | 
| WD40andTape | 14:54c3759e76ed | 205 | if( dblTargetChambLen_mm[ii] < 0.0 ) continue; | 
| WD40andTape | 13:a373dfc57b89 | 206 | |
| WD40andTape | 13:a373dfc57b89 | 207 | _dblVelocity_mmps[ii] = (dblTargetActPos_mm[ii] - dblADCCurrentPosition[ii]) / dblMaxRecalculatedTime; | 
| WD40andTape | 13:a373dfc57b89 | 208 | dblVelocity_mmps[ii] = _dblVelocity_mmps[ii]; | 
| WD40andTape | 6:f0a18e28a322 | 209 | } | 
| WD40andTape | 6:f0a18e28a322 | 210 | // SEND MESSAGE | 
| WD40andTape | 17:bbaf3e8440ad | 211 | error_code = hlcomms.send_duration_message(&dblMaxRecalculatedTime); | 
| WD40andTape | 6:f0a18e28a322 | 212 | if( error_code < 0 ) { | 
| dofydoink | 12:595ed862e52f | 213 | if(IS_PRINT_OUTPUT) printf("Error %i. Could not send data over the TCP socket. " | 
| WD40andTape | 6:f0a18e28a322 | 214 | "Perhaps the server socket is not bound or not set to listen for connections? " | 
| WD40andTape | 6:f0a18e28a322 | 215 | "Or the socket is set to non-blocking or timed out?\n\r", error_code); | 
| WD40andTape | 7:5b6a2cefbf3b | 216 | hlcomms.close_server(); | 
| WD40andTape | 6:f0a18e28a322 | 217 | return; | 
| WD40andTape | 6:f0a18e28a322 | 218 | } | 
| WD40andTape | 6:f0a18e28a322 | 219 | } | 
| WD40andTape | 6:f0a18e28a322 | 220 | |
| dofydoink | 0:607bc887b6e0 | 221 | } | 
| dofydoink | 0:607bc887b6e0 | 222 | |
| WD40andTape | 4:303584310071 | 223 | void CalculateSmoothPath() { | 
| dofydoink | 5:712e7634c779 | 224 | int jj; | 
| WD40andTape | 1:2a43cf183a62 | 225 | double dblMeasuredSampleTime; | 
| WD40andTape | 7:5b6a2cefbf3b | 226 | double dblSmoothPathCurrentPos_mm[N_CHANNELS] = { 0.0 }; // The current position of the smooth path (not sent to actuator) | 
| WD40andTape | 7:5b6a2cefbf3b | 227 | //double dblPosition_mtrs[N_CHANNELS]; // The actual chamber lengths in meters given as the change in length relative to neutral (should always be >=0) | 
| WD40andTape | 7:5b6a2cefbf3b | 228 | //double dblPressure_bar[N_CHANNELS]; // The pressure in a given chamber in bar (1 bar = 100,000 Pa) | 
| WD40andTape | 4:303584310071 | 229 | while(1) { | 
| dofydoink | 0:607bc887b6e0 | 230 | semPathPlan.wait(); | 
| WD40andTape | 13:a373dfc57b89 | 231 | //pinTesty = 1; | 
| WD40andTape | 1:2a43cf183a62 | 232 | // If run time is more than 50 us from expected, calculate from measured time step | 
| WD40andTape | 4:303584310071 | 233 | if (fabs(PATH_SAMPLE_TIME_S*1000000 - timer.read_us()) > 50) { | 
| dofydoink | 5:712e7634c779 | 234 | dblMeasuredSampleTime = timer.read(); | 
| WD40andTape | 4:303584310071 | 235 | } else { | 
| WD40andTape | 1:2a43cf183a62 | 236 | dblMeasuredSampleTime = PATH_SAMPLE_TIME_S; | 
| WD40andTape | 1:2a43cf183a62 | 237 | } | 
| WD40andTape | 4:303584310071 | 238 | timer.reset(); | 
| WD40andTape | 1:2a43cf183a62 | 239 | |
| dofydoink | 5:712e7634c779 | 240 | for(jj = 0; jj < N_CHANNELS; jj++) { | 
| WD40andTape | 7:5b6a2cefbf3b | 241 | //dblPressure_bar[jj] = ReadADCPressure_bar(jj); // Read pressure from channel | 
| WD40andTape | 7:5b6a2cefbf3b | 242 | //dblPosition_mtrs[jj] = ReadADCPosition_mtrs(jj); // Read position from channel | 
| WD40andTape | 1:2a43cf183a62 | 243 | |
| WD40andTape | 7:5b6a2cefbf3b | 244 | // Calculate next step in linear path | 
| WD40andTape | 7:5b6a2cefbf3b | 245 | mutPathIn.lock(); // Lock relevant mutex | 
| WD40andTape | 7:5b6a2cefbf3b | 246 | // Check tolerance | 
| dofydoink | 12:595ed862e52f | 247 | if (fabs(dblLinearPathCurrentPos_mm[jj] - dblTargetActPos_mm[jj]) <= FLT_PATH_TOLERANCE) { | 
| WD40andTape | 7:5b6a2cefbf3b | 248 | dblVelocity_mmps[jj] = 0.0; // Stop linear path generation when linear path is within tolerance of target position | 
| WD40andTape | 7:5b6a2cefbf3b | 249 | } | 
| dofydoink | 11:7029367a1840 | 250 | dblLinearPathCurrentPos_mm[jj] = dblLinearPathCurrentPos_mm[jj] + dblVelocity_mmps[jj]*dblMeasuredSampleTime; | 
| WD40andTape | 15:59471daef4cb | 251 | dblLinearPathCurrentPos_mm[jj] = min( max( 0.0 , dblLinearPathCurrentPos_mm[jj] ) , 40.0 ); | 
| WD40andTape | 7:5b6a2cefbf3b | 252 | mutPathIn.unlock(); // Unlock relevant mutex | 
| dofydoink | 0:607bc887b6e0 | 253 | |
| WD40andTape | 7:5b6a2cefbf3b | 254 | // Calculate next step in smooth path | 
| dofydoink | 12:595ed862e52f | 255 | dblSmoothPathCurrentPos_mm[jj] = FLT_SMOOTHING_FACTOR*dblLinearPathCurrentPos_mm[jj] + (1.0f-FLT_SMOOTHING_FACTOR)*dblSmoothPathCurrentPos_mm[jj]; | 
| dofydoink | 11:7029367a1840 | 256 | dblSmoothPathCurrentPos_mm[jj] = max( 0.0 , dblSmoothPathCurrentPos_mm[jj] ); | 
| dofydoink | 11:7029367a1840 | 257 | llcomms.mutChannel[jj].lock(); // MUTEX LOCK | 
| WD40andTape | 10:1b6daba32452 | 258 | llcomms.demandPosition[jj] = (int) ((dblSmoothPathCurrentPos_mm[jj]/MAX_ACTUATOR_LENGTH)*8191);// Convert to a 13-bit number | 
| WD40andTape | 10:1b6daba32452 | 259 | llcomms.demandPosition[jj] = llcomms.demandPosition[jj] & 0x1FFF; // Ensure number is 13-bit | 
| WD40andTape | 8:d6657767a182 | 260 | llcomms.mutChannel[jj].unlock(); // MUTEX UNLOCK | 
| dofydoink | 0:607bc887b6e0 | 261 | |
| WD40andTape | 10:1b6daba32452 | 262 | llcomms.isDataReady[jj] = 1; // Signal that data ready | 
| WD40andTape | 4:303584310071 | 263 | } // end for | 
| WD40andTape | 7:5b6a2cefbf3b | 264 | |
| dofydoink | 12:595ed862e52f | 265 | //if(IS_PRINT_OUTPUT) printf("%f, %d\r\n",dblSmoothPathCurrentPos_mm[0], intDemandPos_Tx[0]); | 
| dofydoink | 12:595ed862e52f | 266 | //if(IS_PRINT_OUTPUT) printf("%f, %f, %f, %f, %f, %f, %f, %f\r\n",dblLinearPathCurrentPos_mm[0],dblLinearPathCurrentPos_mm[1],dblLinearPathCurrentPos_mm[2], | 
| dofydoink | 11:7029367a1840 | 267 | // dblLinearPathCurrentPos_mm[3],dblLinearPathCurrentPos_mm[4],dblLinearPathCurrentPos_mm[5],dblLinearPathCurrentPos_mm[6],dblLinearPathCurrentPos_mm[7]); | 
| dofydoink | 12:595ed862e52f | 268 | //if(IS_PRINT_OUTPUT) printf("%f\r\n",dblLinearPathCurrentPos_mm[0]); | 
| WD40andTape | 13:a373dfc57b89 | 269 | //pinTesty = 0; | 
| WD40andTape | 4:303584310071 | 270 | } // end while | 
| WD40andTape | 3:c83291bf9fd2 | 271 | } | 
| dofydoink | 0:607bc887b6e0 | 272 | |
| WD40andTape | 13:a373dfc57b89 | 273 | int main() { | 
| WD40andTape | 7:5b6a2cefbf3b | 274 | pc.baud(BAUD_RATE); | 
| WD40andTape | 17:bbaf3e8440ad | 275 | printf("ML engage. Compiled at %s\r\n.",__TIME__); | 
| dofydoink | 5:712e7634c779 | 276 | wait(3); | 
| WD40andTape | 9:cd3607ba5643 | 277 | |
| dofydoink | 0:607bc887b6e0 | 278 | timer.start(); | 
| WD40andTape | 7:5b6a2cefbf3b | 279 | |
| WD40andTape | 10:1b6daba32452 | 280 | threadLowLevelSPI.start(callback(&llcomms.queue, &EventQueue::dispatch_forever)); // Start the event queue | 
| WD40andTape | 7:5b6a2cefbf3b | 281 | threadReceiveAndReplan.start(ReceiveAndReplan);// Start replanning thread | 
| WD40andTape | 7:5b6a2cefbf3b | 282 | threadSmoothPathPlan.start(CalculateSmoothPath); // Start planning thread | 
| WD40andTape | 17:bbaf3e8440ad | 283 | threadSensorFeedback.start(sendSensorData); // Start sensor feedback thread | 
| WD40andTape | 7:5b6a2cefbf3b | 284 | |
| WD40andTape | 7:5b6a2cefbf3b | 285 | PathCalculationTicker.attach(&startPathPlan, PATH_SAMPLE_TIME_S); // Set up planning thread to recur at fixed intervals | 
| dofydoink | 0:607bc887b6e0 | 286 | |
| WD40andTape | 7:5b6a2cefbf3b | 287 | Thread::wait(1); | 
| WD40andTape | 1:2a43cf183a62 | 288 | while(1) { | 
| WD40andTape | 1:2a43cf183a62 | 289 | Thread::wait(osWaitForever); | 
| dofydoink | 0:607bc887b6e0 | 290 | } | 
| WD40andTape | 7:5b6a2cefbf3b | 291 | } |