Basic Mid-Level control for the rebuilt MorphGI control unit, using PWM to communicate with the low level controllers.

Dependencies:   ros_lib_kinetic

Committer:
WD40andTape
Date:
Fri Aug 03 11:08:12 2018 +0000
Revision:
6:f0a18e28a322
Parent:
5:712e7634c779
Child:
7:5b6a2cefbf3b
Successfully tested full HL/ML/SL setup.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dofydoink 0:607bc887b6e0 1 #include "mbed.h"
dofydoink 0:607bc887b6e0 2 #include "math.h"
WD40andTape 6:f0a18e28a322 3 #include "mbed_events.h"
dofydoink 0:607bc887b6e0 4
WD40andTape 6:f0a18e28a322 5 // COMMS IMPORTS
WD40andTape 6:f0a18e28a322 6 #include <sstream> // stringstream
WD40andTape 6:f0a18e28a322 7 #include <vector> // vector
WD40andTape 6:f0a18e28a322 8 #include <string.h> // strtok
dofydoink 0:607bc887b6e0 9 //#include "mbed.h"
WD40andTape 6:f0a18e28a322 10 #include "EthernetInterface.h"
WD40andTape 6:f0a18e28a322 11 #include "TCPServer.h"
WD40andTape 6:f0a18e28a322 12 #include "TCPSocket.h"
WD40andTape 6:f0a18e28a322 13
WD40andTape 6:f0a18e28a322 14 // COMMS SETTINGS
WD40andTape 6:f0a18e28a322 15 const bool IS_DHCP = false;
WD40andTape 6:f0a18e28a322 16 #define PORT 80
WD40andTape 6:f0a18e28a322 17
WD40andTape 6:f0a18e28a322 18 // COMMS STRUCT DECLARATIONS
WD40andTape 6:f0a18e28a322 19 struct msg_format {
WD40andTape 6:f0a18e28a322 20 double psi[3][3];
WD40andTape 6:f0a18e28a322 21 double duration;
WD40andTape 6:f0a18e28a322 22 };
WD40andTape 6:f0a18e28a322 23 struct comms_interfaces {
WD40andTape 6:f0a18e28a322 24 EthernetInterface eth; // Indicates which NetworkInterface the socket should be created on
WD40andTape 6:f0a18e28a322 25 TCPServer srv; // Provides the ability to accept incoming TCP connections
WD40andTape 6:f0a18e28a322 26 TCPSocket clt_sock; // Provides the ability to send a stream of data over TCP
WD40andTape 6:f0a18e28a322 27 SocketAddress clt_addr; // Represents the IP address and port pair of a unique network endpoint
WD40andTape 6:f0a18e28a322 28 };
WD40andTape 6:f0a18e28a322 29
WD40andTape 6:f0a18e28a322 30 // COMMS FUNCTION DECLARATIONS
WD40andTape 6:f0a18e28a322 31 int setup_server(void);
WD40andTape 6:f0a18e28a322 32 int accept_connection(void);
WD40andTape 6:f0a18e28a322 33 void close_server(void);
WD40andTape 6:f0a18e28a322 34 msg_format consume_message( unsigned char * msg );
WD40andTape 6:f0a18e28a322 35
WD40andTape 6:f0a18e28a322 36 // COMMS GLOBAL VARIABLES
WD40andTape 6:f0a18e28a322 37 struct comms_interfaces comms;
dofydoink 0:607bc887b6e0 38
dofydoink 0:607bc887b6e0 39 //ADC SPI stuff
dofydoink 0:607bc887b6e0 40 #define PREAMBLE 0x06
dofydoink 0:607bc887b6e0 41 #define CHAN_1 0x30
dofydoink 0:607bc887b6e0 42 #define CHAN_2 0x70
dofydoink 0:607bc887b6e0 43 #define CHAN_3 0xB0
dofydoink 0:607bc887b6e0 44 #define CHAN_4 0xF0
dofydoink 0:607bc887b6e0 45
dofydoink 0:607bc887b6e0 46 #define DATA_MASK 0x0F
dofydoink 0:607bc887b6e0 47
WD40andTape 1:2a43cf183a62 48 //simple channel selection
dofydoink 0:607bc887b6e0 49 #define ADC_PRESSURE 1
dofydoink 0:607bc887b6e0 50 #define ADC_POSITION 3
WD40andTape 1:2a43cf183a62 51 //---------------------
dofydoink 0:607bc887b6e0 52
dofydoink 0:607bc887b6e0 53 #define N_CHANNELS 8 //number of channels to control
dofydoink 0:607bc887b6e0 54 //1-3: front segment
dofydoink 0:607bc887b6e0 55 //4-6: rear segment
dofydoink 0:607bc887b6e0 56 //7-8: mid segment
dofydoink 0:607bc887b6e0 57
dofydoink 0:607bc887b6e0 58 //parameters to manually change
dofydoink 0:607bc887b6e0 59 #define LOW_LEVEL_SPI_FREQUENCY 10000000
dofydoink 0:607bc887b6e0 60
WD40andTape 6:f0a18e28a322 61 #define PATH_SAMPLE_TIME_S 0.005 //0.109
dofydoink 0:607bc887b6e0 62
dofydoink 0:607bc887b6e0 63 #define MAX_LENGTH_MM 100.0
WD40andTape 3:c83291bf9fd2 64 #define MAX_ACTUATOR_LENGTH 52.2
dofydoink 0:607bc887b6e0 65 #define MAX_SPEED_MMPS 24.3457
WD40andTape 4:303584310071 66 #define PATH_TOLERANCE_MM 0.2 //how close the linear path must get to the target position before considering it a success.
dofydoink 0:607bc887b6e0 67
WD40andTape 6:f0a18e28a322 68 //const double DBL_MAX_CHAMBER_LENGTHS_MM[N_CHANNELS] = {80.0,80.0,80.0,80.0,80.0,80.0,80.0,80.0};
WD40andTape 6:f0a18e28a322 69 //const double DBL_ACTUATOR_CONVERSION[N_CHANNELS] = {0.30586,0.30586,0.30586,0.30586,0.30586,0.4588,0.4588};// covert from chamber lengths to actuator lengths
WD40andTape 6:f0a18e28a322 70 const double DBL_ACTUATOR_CONVERSION[N_CHANNELS] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0};// convert from chamber lengths to actuator
WD40andTape 4:303584310071 71 const double DBL_SMOOTHING_FACTOR = 0.5; // 0<x<=1, where 1 is no smoothing
WD40andTape 6:f0a18e28a322 72 const double DBL_PATH_TOLERANCE = MAX_SPEED_MMPS * PATH_SAMPLE_TIME_S * 1.05; //path tolerance in mm with 5% tolerance
WD40andTape 4:303584310071 73 //-----These are the variables being shared between High-Level and Mid-Level-----------------------------------------------//
dofydoink 0:607bc887b6e0 74
dofydoink 0:607bc887b6e0 75 //
dofydoink 0:607bc887b6e0 76 Semaphore semReplan(1);// this must be set every time new high-level transmissions are received to allow replanning to take place!
dofydoink 0:607bc887b6e0 77 //--------------------------------------------------------------------------------------------------------------------------//
dofydoink 0:607bc887b6e0 78
dofydoink 0:607bc887b6e0 79 //boolean flag to indicate that new target information has been received
dofydoink 0:607bc887b6e0 80 //bool blnReplan;//set this when new transmission is received over ethernet
dofydoink 0:607bc887b6e0 81
dofydoink 0:607bc887b6e0 82 //path variables
WD40andTape 4:303584310071 83 double dblVelocity_mmps[N_CHANNELS] = { 0.0 };//the linear path velocity (not sent to actuator) KEEP GLOBAL
WD40andTape 4:303584310071 84 double dblLinearPathCurrentPos_mm[N_CHANNELS]={ 0.0 }; //the current position of the linear path (not sent to actuator) //KEEP GLOBAL
WD40andTape 4:303584310071 85 double dblTargetActPos_mm[N_CHANNELS] = { 0.0 }; //The final target position for the actuator KEEP GLOBAL
dofydoink 0:607bc887b6e0 86
WD40andTape 4:303584310071 87 int intDemandPos_Tx[N_CHANNELS]; //13-bit value to be sent to the actuator KEEP GLOBAL
dofydoink 0:607bc887b6e0 88
WD40andTape 4:303584310071 89 char chrErrorFlag[N_CHANNELS];// 3 error bits from LL KEEP GLOBAL
dofydoink 0:607bc887b6e0 90
WD40andTape 4:303584310071 91 //pin declarations----------------
dofydoink 0:607bc887b6e0 92 Serial pc(USBTX, USBRX); // tx, rx for usb debugging
dofydoink 0:607bc887b6e0 93
WD40andTape 3:c83291bf9fd2 94 InterruptIn pinGate6(PE_11); //this pin HAS TO BE defined before SPI set up. No Clue Why.
WD40andTape 3:c83291bf9fd2 95
WD40andTape 3:c83291bf9fd2 96 SPI spi(PC_12, PC_11, PC_10); // mosi, miso, sclk
WD40andTape 3:c83291bf9fd2 97
WD40andTape 3:c83291bf9fd2 98 DigitalOut cs_LL[N_CHANNELS] = {PD_15, PE_10, PD_14, PD_11, PE_7, PD_12, PF_10, PD_13};//chip select for low level controller
WD40andTape 3:c83291bf9fd2 99 DigitalOut cs_ADC[N_CHANNELS] = {PG_12, PG_9, PE_1, PG_0, PD_0, PD_1, PF_0, PF_1}; //chip select for ADC
WD40andTape 3:c83291bf9fd2 100
WD40andTape 3:c83291bf9fd2 101 DigitalOut pinCheck(PE_5);
WD40andTape 3:c83291bf9fd2 102
WD40andTape 3:c83291bf9fd2 103 //these interrupt pins have to be declared AFTER SPI declaration. No Clue Why.
WD40andTape 3:c83291bf9fd2 104 InterruptIn pinGate0(PF_11);
WD40andTape 3:c83291bf9fd2 105 InterruptIn pinGate1(PG_14);
WD40andTape 3:c83291bf9fd2 106 InterruptIn pinGate2(PF_15);
WD40andTape 3:c83291bf9fd2 107 InterruptIn pinGate3(PF_12);
WD40andTape 3:c83291bf9fd2 108 InterruptIn pinGate4(PF_3);
WD40andTape 3:c83291bf9fd2 109 InterruptIn pinGate5(PF_13);
WD40andTape 4:303584310071 110 //InterruptIn pinGate6(PE_11); //see above nonsense
WD40andTape 3:c83291bf9fd2 111 InterruptIn pinGate7(PE_13);
dofydoink 0:607bc887b6e0 112
dofydoink 0:607bc887b6e0 113 DigitalOut pinReset(PD_2); //reset pin for all controllers.
dofydoink 0:607bc887b6e0 114
WD40andTape 3:c83291bf9fd2 115
dofydoink 0:607bc887b6e0 116 EventQueue queue(32 * EVENTS_EVENT_SIZE);
dofydoink 0:607bc887b6e0 117
dofydoink 0:607bc887b6e0 118 Thread t(osPriorityRealtime);
dofydoink 0:607bc887b6e0 119
WD40andTape 4:303584310071 120 Thread threadReceiveAndReplan(osPriorityBelowNormal);
WD40andTape 4:303584310071 121 Thread threadSmoothPathPlan(osPriorityNormal);
dofydoink 0:607bc887b6e0 122
dofydoink 0:607bc887b6e0 123 Thread threadSimulateDemand(osPriorityHigh);
dofydoink 0:607bc887b6e0 124
WD40andTape 1:2a43cf183a62 125 Mutex mutChannel[N_CHANNELS];
WD40andTape 4:303584310071 126 Mutex mutPathIn;
dofydoink 0:607bc887b6e0 127
dofydoink 0:607bc887b6e0 128 Semaphore semPathPlan(1);//
dofydoink 0:607bc887b6e0 129
dofydoink 0:607bc887b6e0 130 Timer timer;//timers are nice
dofydoink 0:607bc887b6e0 131
dofydoink 0:607bc887b6e0 132 int ThreadID[N_CHANNELS];
dofydoink 0:607bc887b6e0 133
WD40andTape 1:2a43cf183a62 134 bool isDataReady[N_CHANNELS]; // flag to indicate path data is ready for transmission to low level.
dofydoink 0:607bc887b6e0 135
dofydoink 5:712e7634c779 136 double dblGlobalTest;
dofydoink 5:712e7634c779 137 int intGlobalTest;
WD40andTape 4:303584310071 138 double ReadADCPosition_mtrs(int channel)
dofydoink 0:607bc887b6e0 139 {
dofydoink 0:607bc887b6e0 140 unsigned int outputA;
dofydoink 0:607bc887b6e0 141 unsigned int outputB;
WD40andTape 3:c83291bf9fd2 142 int output;
WD40andTape 3:c83291bf9fd2 143 double dblOutput;
dofydoink 0:607bc887b6e0 144
dofydoink 0:607bc887b6e0 145 spi.format(8,0);
dofydoink 0:607bc887b6e0 146 spi.frequency(1000000);
dofydoink 0:607bc887b6e0 147
dofydoink 0:607bc887b6e0 148 cs_ADC[channel] = 0;
dofydoink 0:607bc887b6e0 149 spi.write(PREAMBLE);
dofydoink 0:607bc887b6e0 150 outputA = spi.write(CHAN_3);
dofydoink 0:607bc887b6e0 151 outputB = spi.write(0xFF);
WD40andTape 1:2a43cf183a62 152 cs_ADC[channel]= 1;
dofydoink 0:607bc887b6e0 153
dofydoink 0:607bc887b6e0 154 outputA = outputA & DATA_MASK;
dofydoink 0:607bc887b6e0 155 outputA = outputA<<8;
dofydoink 0:607bc887b6e0 156 output = (outputA | outputB);
WD40andTape 3:c83291bf9fd2 157 output = 4095- output;
dofydoink 5:712e7634c779 158 dblOutput = (double) (output);
dofydoink 5:712e7634c779 159 dblOutput = dblOutput*0.0229 - 21.582;
dofydoink 5:712e7634c779 160 //dblOutput = dblOutput - 21.78;
WD40andTape 3:c83291bf9fd2 161 return dblOutput;
dofydoink 5:712e7634c779 162 //dblOutput = (double) ((output/4095)*100.0);
dofydoink 5:712e7634c779 163 // dblOutput = dblOutput - 36.727717;
dofydoink 5:712e7634c779 164 // return dblOutput;
dofydoink 0:607bc887b6e0 165 }
dofydoink 0:607bc887b6e0 166
WD40andTape 4:303584310071 167 double ReadADCPressure_bar(int channel)
dofydoink 0:607bc887b6e0 168 {
dofydoink 0:607bc887b6e0 169 unsigned int outputA;
dofydoink 0:607bc887b6e0 170 unsigned int outputB;
WD40andTape 3:c83291bf9fd2 171 int output;
WD40andTape 3:c83291bf9fd2 172 double dblOutput;
dofydoink 0:607bc887b6e0 173
dofydoink 0:607bc887b6e0 174 spi.format(8,0);
dofydoink 0:607bc887b6e0 175 spi.frequency(1000000);
dofydoink 0:607bc887b6e0 176
dofydoink 0:607bc887b6e0 177 cs_ADC[channel] = 0;
dofydoink 0:607bc887b6e0 178 spi.write(PREAMBLE);
dofydoink 0:607bc887b6e0 179 outputA = spi.write(CHAN_1);
dofydoink 0:607bc887b6e0 180 outputB = spi.write(0xFF);
dofydoink 0:607bc887b6e0 181 cs_ADC[channel] = 1;
dofydoink 0:607bc887b6e0 182
dofydoink 0:607bc887b6e0 183 outputA = outputA & DATA_MASK;
dofydoink 0:607bc887b6e0 184 outputA = outputA<<8;
dofydoink 0:607bc887b6e0 185 output = (outputA | outputB);
dofydoink 0:607bc887b6e0 186
dofydoink 5:712e7634c779 187 dblOutput = (double)(output);
dofydoink 5:712e7634c779 188 dblOutput = dblOutput-502.0;
dofydoink 5:712e7634c779 189 dblOutput = dblOutput/4095.0*8.0;
WD40andTape 3:c83291bf9fd2 190 return dblOutput;
dofydoink 0:607bc887b6e0 191 }
dofydoink 0:607bc887b6e0 192
WD40andTape 1:2a43cf183a62 193 void SendReceiveData(int channel)
dofydoink 0:607bc887b6e0 194 {
WD40andTape 3:c83291bf9fd2 195
WD40andTape 4:303584310071 196
WD40andTape 4:303584310071 197 int intPosSPI_Rx[N_CHANNELS]; //13 bit value received over SPI from the actuator
WD40andTape 4:303584310071 198
WD40andTape 4:303584310071 199
dofydoink 0:607bc887b6e0 200 //get data from controller
dofydoink 0:607bc887b6e0 201 spi.format(16,2);
dofydoink 0:607bc887b6e0 202 spi.frequency(LOW_LEVEL_SPI_FREQUENCY);
WD40andTape 4:303584310071 203 mutChannel[channel].lock();//lock mutex for specific Channel
dofydoink 0:607bc887b6e0 204 cs_LL[channel] = 0;//select relevant chip
WD40andTape 1:2a43cf183a62 205 intPosSPI_Rx[channel] = spi.write(intDemandPos_Tx[channel]); //transmit & receive
dofydoink 0:607bc887b6e0 206 cs_LL[channel] = 1;//deselect chip
WD40andTape 1:2a43cf183a62 207 isDataReady[channel] = 0;//data no longer ready, i.e. we now require new data
dofydoink 5:712e7634c779 208 if(channel == 0) {
dofydoink 5:712e7634c779 209 intGlobalTest = intPosSPI_Rx[channel];
dofydoink 5:712e7634c779 210 dblGlobalTest = ((double) (intPosSPI_Rx[channel])/8191.0*52.2);
dofydoink 5:712e7634c779 211 }
WD40andTape 1:2a43cf183a62 212
dofydoink 0:607bc887b6e0 213
dofydoink 0:607bc887b6e0 214 //sort out received data
dofydoink 0:607bc887b6e0 215 chrErrorFlag[channel] = intPosSPI_Rx[channel]>>13;
WD40andTape 4:303584310071 216
dofydoink 0:607bc887b6e0 217 intPosSPI_Rx[channel] = intPosSPI_Rx[channel] & 0x1FFF;
WD40andTape 4:303584310071 218 //dblPosition_mtrs[channel] = (double)intPosSPI_Rx[channel]/8191*(MAX_ACTUATOR_LENGTH/DBL_ACTUATOR_CONVERSION[channel])/1000;
WD40andTape 4:303584310071 219 mutChannel[channel].unlock();//unlock mutex for specific channel
WD40andTape 3:c83291bf9fd2 220 //printf("%d, %d\r\n",intPosSPI_Rx[0],intDemandPos_Tx[0]);
WD40andTape 3:c83291bf9fd2 221
WD40andTape 3:c83291bf9fd2 222 }
WD40andTape 3:c83291bf9fd2 223
WD40andTape 4:303584310071 224
dofydoink 0:607bc887b6e0 225
dofydoink 0:607bc887b6e0 226 //common rise handler function
dofydoink 0:607bc887b6e0 227
dofydoink 0:607bc887b6e0 228 void common_rise_handler(int channel)
dofydoink 0:607bc887b6e0 229 {
WD40andTape 3:c83291bf9fd2 230 pinCheck = 1;
dofydoink 0:607bc887b6e0 231 //check if data is ready for tranmission
WD40andTape 1:2a43cf183a62 232 if (isDataReady[channel])
dofydoink 0:607bc887b6e0 233 {
dofydoink 0:607bc887b6e0 234 // Add transmit task to event queue
WD40andTape 1:2a43cf183a62 235 ThreadID[channel] = queue.call(SendReceiveData,channel);//schedule transmission
dofydoink 0:607bc887b6e0 236 }
dofydoink 0:607bc887b6e0 237 }
dofydoink 0:607bc887b6e0 238
WD40andTape 3:c83291bf9fd2 239
dofydoink 0:607bc887b6e0 240
dofydoink 0:607bc887b6e0 241
dofydoink 0:607bc887b6e0 242 //common_fall handler functions
dofydoink 0:607bc887b6e0 243 void common_fall_handler(int channel)
dofydoink 0:607bc887b6e0 244 {
WD40andTape 3:c83291bf9fd2 245 pinCheck = 0;
dofydoink 0:607bc887b6e0 246 //cancel relevant queued event
dofydoink 0:607bc887b6e0 247 queue.cancel(ThreadID[channel]);
dofydoink 0:607bc887b6e0 248 }
dofydoink 0:607bc887b6e0 249
dofydoink 0:607bc887b6e0 250 //stub rise functions
dofydoink 0:607bc887b6e0 251 void rise0(void) { common_rise_handler(0); }
dofydoink 0:607bc887b6e0 252 void rise1(void) { common_rise_handler(1); }
dofydoink 0:607bc887b6e0 253 void rise2(void) { common_rise_handler(2); }
dofydoink 0:607bc887b6e0 254 void rise3(void) { common_rise_handler(3); }
dofydoink 0:607bc887b6e0 255 void rise4(void) { common_rise_handler(4); }
dofydoink 0:607bc887b6e0 256 void rise5(void) { common_rise_handler(5); }
dofydoink 0:607bc887b6e0 257 void rise6(void) { common_rise_handler(6); }
dofydoink 0:607bc887b6e0 258 void rise7(void) { common_rise_handler(7); }
dofydoink 0:607bc887b6e0 259
dofydoink 0:607bc887b6e0 260 //stub fall functions
dofydoink 0:607bc887b6e0 261 void fall0(void) { common_fall_handler(0); }
dofydoink 0:607bc887b6e0 262 void fall1(void) { common_fall_handler(1); }
dofydoink 0:607bc887b6e0 263 void fall2(void) { common_fall_handler(2); }
dofydoink 0:607bc887b6e0 264 void fall3(void) { common_fall_handler(3); }
dofydoink 0:607bc887b6e0 265 void fall4(void) { common_fall_handler(4); }
dofydoink 0:607bc887b6e0 266 void fall5(void) { common_fall_handler(5); }
dofydoink 0:607bc887b6e0 267 void fall6(void) { common_fall_handler(6); }
dofydoink 0:607bc887b6e0 268 void fall7(void) { common_fall_handler(7); }
dofydoink 0:607bc887b6e0 269
WD40andTape 1:2a43cf183a62 270 void startPathPlan() // Plan a new linear path after receiving new target data
dofydoink 0:607bc887b6e0 271 {
WD40andTape 4:303584310071 272 semPathPlan.release(); // Uses threadReceiveAndReplan which is below normal priority to ensure consistent transmission to LL
dofydoink 0:607bc887b6e0 273 }
dofydoink 0:607bc887b6e0 274
dofydoink 5:712e7634c779 275 double somedumbthing;
dofydoink 5:712e7634c779 276
dofydoink 0:607bc887b6e0 277 //this function will be called when a new transmission is received from high level
WD40andTape 4:303584310071 278 void ReceiveAndReplan()
dofydoink 0:607bc887b6e0 279 {
WD40andTape 4:303584310071 280 int ii;
WD40andTape 4:303584310071 281
WD40andTape 6:f0a18e28a322 282 //double dblPSI[3][3]; //the message from high-level containing the chamber lengths in meters in following format:
WD40andTape 4:303584310071 283 /*
WD40andTape 4:303584310071 284 {L(front,1), L(front,2), L(front,3);
WD40andTape 4:303584310071 285 L(mid,1) , L(mid,2) , L(mid,3);
WD40andTape 4:303584310071 286 L(rear,1) , L(rear,2) , L(rear,3);}
WD40andTape 4:303584310071 287 */
WD40andTape 6:f0a18e28a322 288 //double dblTargetTime_s; //the time in seconds desired to reach the target (>0...!)
dofydoink 5:712e7634c779 289 //double dblPosition_mtrs[N_CHANNELS]; //the actual chamber lengths in meters given as the change in length relative to neutral (should always be >=0)
dofydoink 5:712e7634c779 290 // double dblPressure_bar[N_CHANNELS]; //the pressure in a given chamber in bar (1 bar = 100,000 Pa).
dofydoink 5:712e7634c779 291
WD40andTape 4:303584310071 292
WD40andTape 4:303584310071 293 //!!!!!!!!!!!!!!! If received messages faster than path replanning, will get increasingly behind time --> need to throw away some instructions
WD40andTape 2:eea12b149dba 294
WD40andTape 4:303584310071 295 //receive
WD40andTape 4:303584310071 296
WD40andTape 6:f0a18e28a322 297 // Error codes: https://github.com/ARMmbed/mbed-os/blob/master/features/netsocket/nsapi_types.h
WD40andTape 6:f0a18e28a322 298 // http://man7.org/linux/man-pages/man3/errno.3.html
WD40andTape 6:f0a18e28a322 299
WD40andTape 6:f0a18e28a322 300 int error_code;
WD40andTape 6:f0a18e28a322 301
WD40andTape 6:f0a18e28a322 302 error_code = setup_server();
WD40andTape 6:f0a18e28a322 303 if( error_code == -1 ) return;
WD40andTape 6:f0a18e28a322 304 error_code = accept_connection();
WD40andTape 6:f0a18e28a322 305 if( error_code == -1 ) return;
WD40andTape 6:f0a18e28a322 306
WD40andTape 6:f0a18e28a322 307 unsigned char recv_buffer[1024];
WD40andTape 6:f0a18e28a322 308 struct msg_format input;
WD40andTape 6:f0a18e28a322 309 char send_buffer[65];
WD40andTape 6:f0a18e28a322 310 char * message_to_send;
WD40andTape 4:303584310071 311
WD40andTape 6:f0a18e28a322 312 while( true ) {
WD40andTape 6:f0a18e28a322 313 // RECEIVE MESSAGE
WD40andTape 6:f0a18e28a322 314 memset(recv_buffer, 0, sizeof(recv_buffer));
WD40andTape 6:f0a18e28a322 315 error_code = comms.clt_sock.recv(recv_buffer, 1024); // Blocks until data is received
WD40andTape 6:f0a18e28a322 316 if( error_code == NSAPI_ERROR_NO_CONNECTION ) { // -3004
WD40andTape 6:f0a18e28a322 317 printf("Client disconnected.\n\r");
WD40andTape 6:f0a18e28a322 318 close_server();
WD40andTape 6:f0a18e28a322 319 return;
WD40andTape 6:f0a18e28a322 320 } else if( error_code < 0 ) {
WD40andTape 6:f0a18e28a322 321 printf("Error %i. Could not send data over the TCP socket. "
WD40andTape 6:f0a18e28a322 322 "Perhaps the server socket is not connected to a remote host? "
WD40andTape 6:f0a18e28a322 323 "Or the socket is set to non-blocking or timed out?\n\r", error_code);
WD40andTape 6:f0a18e28a322 324 close_server();
WD40andTape 6:f0a18e28a322 325 return;
WD40andTape 6:f0a18e28a322 326 }
WD40andTape 6:f0a18e28a322 327 //printf("Message received.\r\n");
WD40andTape 6:f0a18e28a322 328 input = consume_message( recv_buffer );
WD40andTape 6:f0a18e28a322 329 //!! Set global variables to input with mutex
WD40andTape 1:2a43cf183a62 330
WD40andTape 6:f0a18e28a322 331 // Process input
WD40andTape 6:f0a18e28a322 332
WD40andTape 6:f0a18e28a322 333 double dblTargetChambLen_mm[N_CHANNELS]; //the currenly assigned final target position (actuator will reach this at end of path)
WD40andTape 6:f0a18e28a322 334 printf("REPLAN, %f\r\n",input.duration);
dofydoink 0:607bc887b6e0 335 //update front segment
WD40andTape 6:f0a18e28a322 336 dblTargetChambLen_mm[0] = input.psi[0][0]*1000;
WD40andTape 6:f0a18e28a322 337 dblTargetChambLen_mm[1] = input.psi[0][1]*1000;
WD40andTape 6:f0a18e28a322 338 dblTargetChambLen_mm[2] = input.psi[0][2]*1000;
dofydoink 0:607bc887b6e0 339 //update mid segment
WD40andTape 6:f0a18e28a322 340 dblTargetChambLen_mm[6] = input.psi[1][0]*1000;
dofydoink 0:607bc887b6e0 341 dblTargetChambLen_mm[7] = dblTargetChambLen_mm[6]; //same because two pumps are used
dofydoink 0:607bc887b6e0 342 //update rear segment
WD40andTape 6:f0a18e28a322 343 dblTargetChambLen_mm[3] = input.psi[2][0]*1000;
WD40andTape 6:f0a18e28a322 344 dblTargetChambLen_mm[4] = input.psi[2][1]*1000;
WD40andTape 6:f0a18e28a322 345 dblTargetChambLen_mm[5] = input.psi[2][2]*1000;
dofydoink 0:607bc887b6e0 346
WD40andTape 6:f0a18e28a322 347 bool isTimeChanged = 0;
WD40andTape 6:f0a18e28a322 348 double dblMaxRecalculatedTime = input.duration;
WD40andTape 6:f0a18e28a322 349 mutPathIn.lock();//lock variables to avoid race condition
WD40andTape 4:303584310071 350 for (ii = 0; ii< N_CHANNELS; ii++) {
dofydoink 0:607bc887b6e0 351 //check to see if positions are achievable
WD40andTape 6:f0a18e28a322 352 /*if(dblTargetChambLen_mm[ii]>DBL_MAX_CHAMBER_LENGTHS_MM[ii]) {
WD40andTape 4:303584310071 353 dblTargetChambLen_mm[ii] = DBL_MAX_CHAMBER_LENGTHS_MM[ii];
WD40andTape 6:f0a18e28a322 354 isTimeChanged = 1;
dofydoink 0:607bc887b6e0 355 }
WD40andTape 4:303584310071 356 if(dblTargetChambLen_mm[ii]<0.0) {
WD40andTape 6:f0a18e28a322 357 dblTargetChambLen_mm[ii] = 0.0;
WD40andTape 6:f0a18e28a322 358 isTimeChanged = 1;
WD40andTape 6:f0a18e28a322 359 }*/
WD40andTape 6:f0a18e28a322 360 dblTargetActPos_mm[ii] = dblTargetChambLen_mm[ii]*DBL_ACTUATOR_CONVERSION[ii];
WD40andTape 6:f0a18e28a322 361 //!! LIMIT CHAMBER LENGTHS TOO
WD40andTape 6:f0a18e28a322 362 if( dblTargetActPos_mm[ii]<0.0 || dblTargetActPos_mm[ii]>25.0 ) {
WD40andTape 6:f0a18e28a322 363 dblTargetActPos_mm[ii] = min( max( 0.0 , dblTargetActPos_mm[ii] ) , 25.0 );
WD40andTape 6:f0a18e28a322 364 isTimeChanged = 1;
WD40andTape 6:f0a18e28a322 365 }
WD40andTape 6:f0a18e28a322 366 }
WD40andTape 6:f0a18e28a322 367 double dblActPosChange;
WD40andTape 6:f0a18e28a322 368 short sgn;
WD40andTape 6:f0a18e28a322 369 for (ii = 0; ii< N_CHANNELS; ii++) {
WD40andTape 6:f0a18e28a322 370 //work out new velocities
WD40andTape 6:f0a18e28a322 371 dblActPosChange = dblTargetActPos_mm[ii] - dblLinearPathCurrentPos_mm[ii];
WD40andTape 6:f0a18e28a322 372 if( fabs(dblActPosChange) < DBL_PATH_TOLERANCE ) {
WD40andTape 6:f0a18e28a322 373 dblActPosChange = 0.0;
WD40andTape 6:f0a18e28a322 374 isTimeChanged = 1;
dofydoink 0:607bc887b6e0 375 }
WD40andTape 6:f0a18e28a322 376 if( input.duration < 0.000000001 ) {
WD40andTape 6:f0a18e28a322 377 sgn = (dblActPosChange > 0) ? 1 : ((dblActPosChange < 0) ? -1 : 0);
WD40andTape 6:f0a18e28a322 378 dblVelocity_mmps[ii] = sgn * MAX_SPEED_MMPS;
WD40andTape 6:f0a18e28a322 379 isTimeChanged = 1;
WD40andTape 6:f0a18e28a322 380 } else {
WD40andTape 6:f0a18e28a322 381 dblVelocity_mmps[ii] = dblActPosChange / input.duration;
WD40andTape 6:f0a18e28a322 382 }
WD40andTape 6:f0a18e28a322 383 //check to see if velocities are achievable
WD40andTape 6:f0a18e28a322 384 if(abs(dblVelocity_mmps[ii]) > MAX_SPEED_MMPS) {
WD40andTape 6:f0a18e28a322 385 if(dblVelocity_mmps[ii]>0) {
WD40andTape 6:f0a18e28a322 386 dblVelocity_mmps[ii] = MAX_SPEED_MMPS;
WD40andTape 6:f0a18e28a322 387 } else {
WD40andTape 6:f0a18e28a322 388 dblVelocity_mmps[ii] = -1*MAX_SPEED_MMPS;
WD40andTape 6:f0a18e28a322 389 }
WD40andTape 6:f0a18e28a322 390 isTimeChanged = 1;
WD40andTape 6:f0a18e28a322 391 }
WD40andTape 6:f0a18e28a322 392 double dblRecalculatedTime;
WD40andTape 6:f0a18e28a322 393 if( fabs(dblVelocity_mmps[ii]) < 0.000000001 ) {
WD40andTape 6:f0a18e28a322 394 dblRecalculatedTime = 0;
WD40andTape 6:f0a18e28a322 395 } else {
WD40andTape 6:f0a18e28a322 396 dblRecalculatedTime = (dblTargetActPos_mm[ii] - dblLinearPathCurrentPos_mm[ii]) / dblVelocity_mmps[ii];
WD40andTape 6:f0a18e28a322 397 }
WD40andTape 6:f0a18e28a322 398 if( dblRecalculatedTime > dblMaxRecalculatedTime ) {
WD40andTape 6:f0a18e28a322 399 dblMaxRecalculatedTime = dblRecalculatedTime;
WD40andTape 6:f0a18e28a322 400 }
WD40andTape 6:f0a18e28a322 401 }
WD40andTape 6:f0a18e28a322 402 if( isTimeChanged ) {
WD40andTape 6:f0a18e28a322 403 if( dblMaxRecalculatedTime < input.duration ) {
WD40andTape 6:f0a18e28a322 404 dblMaxRecalculatedTime = input.duration;
WD40andTape 6:f0a18e28a322 405 }
WD40andTape 6:f0a18e28a322 406 for (ii = 0; ii< N_CHANNELS; ii++) {
dofydoink 5:712e7634c779 407 //work out new velocities
WD40andTape 6:f0a18e28a322 408 dblVelocity_mmps[ii] = (dblTargetActPos_mm[ii] - dblLinearPathCurrentPos_mm[ii]) / dblMaxRecalculatedTime;
WD40andTape 6:f0a18e28a322 409 }
WD40andTape 6:f0a18e28a322 410 }
dofydoink 0:607bc887b6e0 411
dofydoink 0:607bc887b6e0 412
WD40andTape 6:f0a18e28a322 413 //dblPressure_bar[ii] = 0.5;//read pressure from channel
WD40andTape 6:f0a18e28a322 414 //dblPosition_mtrs[ii] = 0.02; //read position from channel
WD40andTape 4:303584310071 415 //printf("%f\r\n", dblVelocity_mmps[0]);
WD40andTape 6:f0a18e28a322 416 mutPathIn.unlock(); //unlock mutex.
WD40andTape 6:f0a18e28a322 417
WD40andTape 6:f0a18e28a322 418 printf("Sending message...\r\n");
WD40andTape 6:f0a18e28a322 419 // SEND MESSAGE
WD40andTape 6:f0a18e28a322 420 memset(send_buffer, 0, sizeof(send_buffer));
WD40andTape 6:f0a18e28a322 421 _snprintf(send_buffer,64,"%f",dblMaxRecalculatedTime);
WD40andTape 6:f0a18e28a322 422 message_to_send = send_buffer;
WD40andTape 6:f0a18e28a322 423 error_code = comms.clt_sock.send(message_to_send, strlen(message_to_send));
WD40andTape 6:f0a18e28a322 424 if( error_code < 0 ) {
WD40andTape 6:f0a18e28a322 425 printf("Error %i. Could not send data over the TCP socket. "
WD40andTape 6:f0a18e28a322 426 "Perhaps the server socket is not bound or not set to listen for connections? "
WD40andTape 6:f0a18e28a322 427 "Or the socket is set to non-blocking or timed out?\n\r", error_code);
WD40andTape 6:f0a18e28a322 428 close_server();
WD40andTape 6:f0a18e28a322 429 return;
WD40andTape 6:f0a18e28a322 430 }
WD40andTape 6:f0a18e28a322 431 printf("Message sent.\r\n");
WD40andTape 6:f0a18e28a322 432 }
WD40andTape 6:f0a18e28a322 433
dofydoink 0:607bc887b6e0 434 }
dofydoink 0:607bc887b6e0 435
WD40andTape 2:eea12b149dba 436 // lock mutex
WD40andTape 2:eea12b149dba 437 // get variables
WD40andTape 2:eea12b149dba 438 // unlock mutex
WD40andTape 2:eea12b149dba 439 // do calculations
WD40andTape 2:eea12b149dba 440 // lock mutex
WD40andTape 2:eea12b149dba 441 // set variables
WD40andTape 4:303584310071 442 // unlock mutex
WD40andTape 2:eea12b149dba 443
WD40andTape 4:303584310071 444 void CalculateSmoothPath() {
dofydoink 5:712e7634c779 445 int jj;
WD40andTape 1:2a43cf183a62 446 double dblMeasuredSampleTime;
WD40andTape 4:303584310071 447 double dblSmoothPathCurrentPos_mm[N_CHANNELS] = { 0.0 }; //the current position of the smooth path (not sent to actuator)
dofydoink 5:712e7634c779 448 double dblPosition_mtrs[N_CHANNELS]; //the actual chamber lengths in meters given as the change in length relative to neutral (should always be >=0)
dofydoink 5:712e7634c779 449 double dblPressure_bar[N_CHANNELS]; //the pressure in a given chamber in bar (1 bar = 100,000 Pa).
WD40andTape 4:303584310071 450 while(1) {
dofydoink 0:607bc887b6e0 451 semPathPlan.wait();
WD40andTape 1:2a43cf183a62 452
WD40andTape 1:2a43cf183a62 453 // If run time is more than 50 us from expected, calculate from measured time step
WD40andTape 4:303584310071 454 if (fabs(PATH_SAMPLE_TIME_S*1000000 - timer.read_us()) > 50) {
dofydoink 5:712e7634c779 455 dblMeasuredSampleTime = timer.read();
WD40andTape 4:303584310071 456 } else {
WD40andTape 1:2a43cf183a62 457 dblMeasuredSampleTime = PATH_SAMPLE_TIME_S;
WD40andTape 1:2a43cf183a62 458 }
WD40andTape 4:303584310071 459 timer.reset();
WD40andTape 1:2a43cf183a62 460
dofydoink 5:712e7634c779 461 for(jj = 0; jj < N_CHANNELS; jj++) {
dofydoink 5:712e7634c779 462
dofydoink 5:712e7634c779 463 dblPressure_bar[jj] = ReadADCPressure_bar(jj);//read pressure from channel
dofydoink 5:712e7634c779 464 dblPosition_mtrs[jj] = ReadADCPosition_mtrs(jj); //read position from channel
dofydoink 5:712e7634c779 465 //DEBUGGING
dofydoink 5:712e7634c779 466 //if(jj == 0) printf("BEFORE: %f, %f, %f\r\n",dblVelocity_mmps[0],dblPosition_mtrs[0], dblMeasuredSampleTime);
WD40andTape 1:2a43cf183a62 467
dofydoink 5:712e7634c779 468 //calculate next step in linear path
dofydoink 5:712e7634c779 469 mutPathIn.lock();//lock relevant mutex
dofydoink 5:712e7634c779 470 dblLinearPathCurrentPos_mm[jj] = dblLinearPathCurrentPos_mm[jj] + dblVelocity_mmps[jj]*dblMeasuredSampleTime; // PATH_SAMPLE_TIME_S SHOULD BE MEASURED
dofydoink 5:712e7634c779 471 if(dblLinearPathCurrentPos_mm[jj] < 0.0) {
dofydoink 5:712e7634c779 472 dblLinearPathCurrentPos_mm[jj] = 0.00;
dofydoink 5:712e7634c779 473 }
WD40andTape 6:f0a18e28a322 474 /*if(dblLinearPathCurrentPos_mm[jj] > 0.0) {
WD40andTape 6:f0a18e28a322 475 dblLinearPathCurrentPos_mm[jj] = 0.00;
WD40andTape 6:f0a18e28a322 476 }*/
WD40andTape 6:f0a18e28a322 477
dofydoink 5:712e7634c779 478
dofydoink 5:712e7634c779 479 //check tolerance
dofydoink 5:712e7634c779 480 if (fabs(dblLinearPathCurrentPos_mm[jj] - dblTargetActPos_mm[jj]) <= DBL_PATH_TOLERANCE) {
dofydoink 5:712e7634c779 481 dblVelocity_mmps[jj] = 0.0; //stop linear path generation when linear path is within tolerance of target position.
dofydoink 5:712e7634c779 482 }
dofydoink 5:712e7634c779 483 mutPathIn.unlock();//unlock relevant mutex
dofydoink 0:607bc887b6e0 484
dofydoink 0:607bc887b6e0 485 //calculate next step in smooth path
dofydoink 5:712e7634c779 486 dblSmoothPathCurrentPos_mm[jj] = DBL_SMOOTHING_FACTOR*dblLinearPathCurrentPos_mm[jj] + (1.0-DBL_SMOOTHING_FACTOR)*dblSmoothPathCurrentPos_mm[jj];
dofydoink 5:712e7634c779 487
dofydoink 5:712e7634c779 488 mutChannel[jj].lock(); //MUTEX LOCK
dofydoink 5:712e7634c779 489 intDemandPos_Tx[jj] = (int) ((dblSmoothPathCurrentPos_mm[jj]/MAX_ACTUATOR_LENGTH)*8191);//convert to a 13-bit number;
dofydoink 5:712e7634c779 490 intDemandPos_Tx[jj] = intDemandPos_Tx[jj] & 0x1FFF; //ensure number is 13-bit
dofydoink 5:712e7634c779 491 mutChannel[jj].unlock(); //MUTEX UNLOCK
dofydoink 5:712e7634c779 492 //if(jj == 0) printf("AFTER: %f, %f, %f\r\n",dblLinearPathCurrentPos_mm[jj],dblVelocity_mmps[jj],dblMeasuredSampleTime);
dofydoink 0:607bc887b6e0 493
dofydoink 5:712e7634c779 494 isDataReady[jj] = 1;//signal that data ready
dofydoink 0:607bc887b6e0 495
WD40andTape 4:303584310071 496 } // end for
WD40andTape 6:f0a18e28a322 497 //printf("%f, %d\r\n",dblSmoothPathCurrentPos_mm[0], intDemandPos_Tx[0]);
WD40andTape 6:f0a18e28a322 498 /*printf("%f, %f, %f, %f, %f, %f, %f, %f\r\n",dblLinearPathCurrentPos_mm[0],dblLinearPathCurrentPos_mm[1],dblLinearPathCurrentPos_mm[2],
WD40andTape 6:f0a18e28a322 499 dblLinearPathCurrentPos_mm[3],dblLinearPathCurrentPos_mm[4],dblLinearPathCurrentPos_mm[5],dblLinearPathCurrentPos_mm[6],dblLinearPathCurrentPos_mm[7]);*/
WD40andTape 6:f0a18e28a322 500 //printf("%f\r\n",dblLinearPathCurrentPos_mm[0]);
WD40andTape 4:303584310071 501 } // end while
WD40andTape 3:c83291bf9fd2 502 }
dofydoink 0:607bc887b6e0 503
dofydoink 0:607bc887b6e0 504
dofydoink 0:607bc887b6e0 505
dofydoink 0:607bc887b6e0 506 Ticker PathCalculationTicker;
dofydoink 0:607bc887b6e0 507
dofydoink 0:607bc887b6e0 508 int main()
dofydoink 0:607bc887b6e0 509 {
WD40andTape 4:303584310071 510 int ii;
WD40andTape 3:c83291bf9fd2 511
dofydoink 0:607bc887b6e0 512 //initialise relevant variables
dofydoink 0:607bc887b6e0 513 for(ii = 0; ii<N_CHANNELS; ii++)
dofydoink 0:607bc887b6e0 514 {
WD40andTape 3:c83291bf9fd2 515
dofydoink 0:607bc887b6e0 516 //all chip selects in off state
dofydoink 0:607bc887b6e0 517 cs_LL[ii] = 1;
dofydoink 0:607bc887b6e0 518 cs_ADC[ii] = 1;
dofydoink 0:607bc887b6e0 519
dofydoink 0:607bc887b6e0 520 //data ready flags set to not ready
WD40andTape 1:2a43cf183a62 521 isDataReady[ii] = 0;
dofydoink 0:607bc887b6e0 522 }
dofydoink 0:607bc887b6e0 523
dofydoink 0:607bc887b6e0 524 //calculate some control variables
WD40andTape 6:f0a18e28a322 525
dofydoink 0:607bc887b6e0 526
dofydoink 0:607bc887b6e0 527 pinReset = 1; //initialise reset pin to not reset the controllers.
dofydoink 5:712e7634c779 528 wait(0.25);
WD40andTape 3:c83291bf9fd2 529 pinReset=0; //reset controllers to be safe
dofydoink 5:712e7634c779 530 wait(0.25);
WD40andTape 3:c83291bf9fd2 531 pinReset = 1;//ready to go
dofydoink 0:607bc887b6e0 532
dofydoink 0:607bc887b6e0 533 //say something nice to the user.
WD40andTape 6:f0a18e28a322 534 pc.baud(9600); //115200
dofydoink 0:607bc887b6e0 535 printf("Hi, there! I'll be your mid-level controller for today.\r\n");
dofydoink 5:712e7634c779 536 wait(3);
dofydoink 0:607bc887b6e0 537 // Start the event queue
dofydoink 0:607bc887b6e0 538 t.start(callback(&queue, &EventQueue::dispatch_forever));
dofydoink 0:607bc887b6e0 539
dofydoink 0:607bc887b6e0 540 //set up the interrupts
dofydoink 0:607bc887b6e0 541
dofydoink 0:607bc887b6e0 542 //set up rise interrupts MIGHT NOT NEED TO BE POINTERS
WD40andTape 3:c83291bf9fd2 543 //
WD40andTape 3:c83291bf9fd2 544 //pinGate[0].rise(&testRiseFunction);
WD40andTape 3:c83291bf9fd2 545 //testPinGate.rise(&testRiseFunction);//<working
WD40andTape 3:c83291bf9fd2 546 //testPinGate.rise(&rise0);
WD40andTape 3:c83291bf9fd2 547
WD40andTape 3:c83291bf9fd2 548 pinGate0.rise(&rise0);
dofydoink 5:712e7634c779 549
WD40andTape 3:c83291bf9fd2 550 pinGate1.rise(&rise1);
WD40andTape 3:c83291bf9fd2 551 pinGate2.rise(&rise2);
WD40andTape 3:c83291bf9fd2 552 pinGate3.rise(&rise3);
WD40andTape 3:c83291bf9fd2 553 pinGate4.rise(&rise4);
WD40andTape 3:c83291bf9fd2 554 pinGate5.rise(&rise5);
WD40andTape 3:c83291bf9fd2 555 pinGate6.rise(&rise6);
WD40andTape 3:c83291bf9fd2 556 pinGate7.rise(&rise7);
dofydoink 5:712e7634c779 557
dofydoink 0:607bc887b6e0 558
dofydoink 0:607bc887b6e0 559 //set up fall interrupts MIGHT NOT NEED TO BE POINTERS
WD40andTape 3:c83291bf9fd2 560 //
WD40andTape 3:c83291bf9fd2 561 //pinGate[0].fall(&testFallFunction);
WD40andTape 3:c83291bf9fd2 562 //testPinGate.fall(&testFallFunction); <working
WD40andTape 3:c83291bf9fd2 563 //testPinGate.fall(&fall0);
WD40andTape 3:c83291bf9fd2 564
WD40andTape 3:c83291bf9fd2 565 pinGate0.fall(&fall0);
dofydoink 5:712e7634c779 566
WD40andTape 3:c83291bf9fd2 567 pinGate1.fall(&fall1);
WD40andTape 3:c83291bf9fd2 568 pinGate2.fall(&fall2);
WD40andTape 3:c83291bf9fd2 569 pinGate3.fall(&fall3);
WD40andTape 3:c83291bf9fd2 570 pinGate4.fall(&fall4);
WD40andTape 3:c83291bf9fd2 571 pinGate5.fall(&fall5);
WD40andTape 3:c83291bf9fd2 572 pinGate6.fall(&fall6);
WD40andTape 3:c83291bf9fd2 573 pinGate7.fall(&fall7);
dofydoink 5:712e7634c779 574
dofydoink 0:607bc887b6e0 575
dofydoink 0:607bc887b6e0 576 timer.start();
dofydoink 0:607bc887b6e0 577
WD40andTape 4:303584310071 578 //threadSimulateDemand.start(SimulateDemand);
WD40andTape 4:303584310071 579 threadReceiveAndReplan.start(ReceiveAndReplan);//start Replanning thread
WD40andTape 4:303584310071 580 //ReceiveAndReplan();
WD40andTape 4:303584310071 581 threadSmoothPathPlan.start(CalculateSmoothPath); //start planning thread
WD40andTape 1:2a43cf183a62 582
dofydoink 0:607bc887b6e0 583 PathCalculationTicker.attach(&startPathPlan, PATH_SAMPLE_TIME_S); //set up planning thread to recur at fixed intervals
WD40andTape 1:2a43cf183a62 584
dofydoink 0:607bc887b6e0 585 Thread::wait(1);
WD40andTape 3:c83291bf9fd2 586
dofydoink 0:607bc887b6e0 587
WD40andTape 1:2a43cf183a62 588 while(1) {
WD40andTape 1:2a43cf183a62 589 Thread::wait(osWaitForever);
dofydoink 0:607bc887b6e0 590 }
dofydoink 0:607bc887b6e0 591 }
dofydoink 0:607bc887b6e0 592
WD40andTape 6:f0a18e28a322 593
WD40andTape 6:f0a18e28a322 594 int setup_server(void) {
WD40andTape 6:f0a18e28a322 595 int error_code;
WD40andTape 6:f0a18e28a322 596 printf("Starting TCP server...\n\r");
WD40andTape 6:f0a18e28a322 597 if( !IS_DHCP ) {
WD40andTape 6:f0a18e28a322 598 const char* ip = "10.101.79.135"; //"10.101.81.125"; // Get first 3 parts from "ifconfig" on PC
WD40andTape 6:f0a18e28a322 599 const char* mask = "255.255.255.0"; // Get from "ifconfig" on PC
WD40andTape 6:f0a18e28a322 600 const char* gateway = "10.101.79.1"; //"10.101.81.1"; // Get from "route -n" on PC
WD40andTape 6:f0a18e28a322 601 error_code = comms.eth.set_network(ip, mask, gateway); // Dont use DHCP
WD40andTape 6:f0a18e28a322 602 if( error_code < 0 ) {
WD40andTape 6:f0a18e28a322 603 printf("Error %i. Could not network interface to use a static IP address. "
WD40andTape 6:f0a18e28a322 604 "Perhaps the network is already connected?\n\r", error_code);
WD40andTape 6:f0a18e28a322 605 return -1;
WD40andTape 6:f0a18e28a322 606 }
WD40andTape 6:f0a18e28a322 607 }
WD40andTape 6:f0a18e28a322 608 error_code = comms.eth.connect();
WD40andTape 6:f0a18e28a322 609 if( error_code < 0 ) {
WD40andTape 6:f0a18e28a322 610 printf("Error %i. Could not start the Ethernet interface.\n\r", error_code);
WD40andTape 6:f0a18e28a322 611 return -1;
WD40andTape 6:f0a18e28a322 612 }
WD40andTape 6:f0a18e28a322 613 const char* server_ip = comms.eth.get_ip_address();
WD40andTape 6:f0a18e28a322 614 if( server_ip == NULL ) {
WD40andTape 6:f0a18e28a322 615 error_code = -1;
WD40andTape 6:f0a18e28a322 616 printf("Error %i. Ethernet interface is not yet connected.\n\r", error_code);
WD40andTape 6:f0a18e28a322 617 return -1;
WD40andTape 6:f0a18e28a322 618 }
WD40andTape 6:f0a18e28a322 619 printf("The target IP address is '%s'\n\r", server_ip);
WD40andTape 6:f0a18e28a322 620 error_code = comms.srv.open(&comms.eth); // Open the server on ethernet stack
WD40andTape 6:f0a18e28a322 621 if( error_code < 0 ) {
WD40andTape 6:f0a18e28a322 622 printf("Error %i. Could not open server socket.\n\r", error_code);
WD40andTape 6:f0a18e28a322 623 return -1;
WD40andTape 6:f0a18e28a322 624 }
WD40andTape 6:f0a18e28a322 625 error_code = comms.srv.bind(comms.eth.get_ip_address(), PORT); // Bind the HTTP port (TCP 80) to the server
WD40andTape 6:f0a18e28a322 626 if( error_code < 0 ) {
WD40andTape 6:f0a18e28a322 627 printf("Error %i. Could not bind server socket to port '%d'.\n\r", error_code, PORT);
WD40andTape 6:f0a18e28a322 628 return -1;
WD40andTape 6:f0a18e28a322 629 }
WD40andTape 6:f0a18e28a322 630 error_code = comms.srv.listen(1); // Listen for 1 simultaneous connection
WD40andTape 6:f0a18e28a322 631 if( error_code < 0 ) {
WD40andTape 6:f0a18e28a322 632 printf("Error %i. Could not put server socket into listening mode.\n\r", error_code);
WD40andTape 6:f0a18e28a322 633 return -1;
WD40andTape 6:f0a18e28a322 634 }
WD40andTape 6:f0a18e28a322 635 return 0;
WD40andTape 6:f0a18e28a322 636 }
WD40andTape 6:f0a18e28a322 637
WD40andTape 6:f0a18e28a322 638
WD40andTape 6:f0a18e28a322 639 int accept_connection(void) {
WD40andTape 6:f0a18e28a322 640 printf("Waiting to accept a connection on the TCP socket.\n\r");
WD40andTape 6:f0a18e28a322 641 int error_code;
WD40andTape 6:f0a18e28a322 642 error_code = comms.srv.accept(&comms.clt_sock, &comms.clt_addr); // Blocks until data is sent
WD40andTape 6:f0a18e28a322 643 if( error_code < 0 ) {
WD40andTape 6:f0a18e28a322 644 printf("Error %i. Could not create a network socket using the specified socket instance. "
WD40andTape 6:f0a18e28a322 645 "Perhaps the socket is set to non-blocking or timed out?\n\r", error_code);
WD40andTape 6:f0a18e28a322 646 return -1;
WD40andTape 6:f0a18e28a322 647 }
WD40andTape 6:f0a18e28a322 648 printf("Accepted %s:%d\n\r", comms.clt_addr.get_ip_address(), comms.clt_addr.get_port());
WD40andTape 6:f0a18e28a322 649 return 0;
WD40andTape 6:f0a18e28a322 650 }
WD40andTape 6:f0a18e28a322 651
WD40andTape 6:f0a18e28a322 652
WD40andTape 6:f0a18e28a322 653 void close_server(void) {
WD40andTape 6:f0a18e28a322 654 comms.clt_sock.close();
WD40andTape 6:f0a18e28a322 655 comms.srv.close();
WD40andTape 6:f0a18e28a322 656 comms.eth.disconnect();
WD40andTape 6:f0a18e28a322 657 return;
WD40andTape 6:f0a18e28a322 658 }
WD40andTape 6:f0a18e28a322 659
WD40andTape 6:f0a18e28a322 660
WD40andTape 6:f0a18e28a322 661 msg_format consume_message( unsigned char * msg ) {
WD40andTape 6:f0a18e28a322 662 // Break message string into chunks at each comma
WD40andTape 6:f0a18e28a322 663 vector<string> tokens;
WD40andTape 6:f0a18e28a322 664 char * delim = ",";
WD40andTape 6:f0a18e28a322 665 char * token = strtok((char *)msg, delim);
WD40andTape 6:f0a18e28a322 666 while(token != NULL) {
WD40andTape 6:f0a18e28a322 667 tokens.push_back(string(token));
WD40andTape 6:f0a18e28a322 668 //printf("%s\n\r",token);
WD40andTape 6:f0a18e28a322 669 token = strtok(NULL, delim);
WD40andTape 6:f0a18e28a322 670 }
WD40andTape 6:f0a18e28a322 671 // Cast into doubles and assign to variables
WD40andTape 6:f0a18e28a322 672 struct msg_format input;
WD40andTape 6:f0a18e28a322 673 stringstream(tokens[0]) >> input.psi[0][0];
WD40andTape 6:f0a18e28a322 674 stringstream(tokens[1]) >> input.psi[0][1];
WD40andTape 6:f0a18e28a322 675 stringstream(tokens[2]) >> input.psi[0][2];
WD40andTape 6:f0a18e28a322 676 stringstream(tokens[3]) >> input.psi[1][0];
WD40andTape 6:f0a18e28a322 677 stringstream(tokens[4]) >> input.psi[1][1];
WD40andTape 6:f0a18e28a322 678 stringstream(tokens[5]) >> input.psi[1][2];
WD40andTape 6:f0a18e28a322 679 stringstream(tokens[6]) >> input.psi[2][0];
WD40andTape 6:f0a18e28a322 680 stringstream(tokens[7]) >> input.psi[2][1];
WD40andTape 6:f0a18e28a322 681 stringstream(tokens[8]) >> input.psi[2][2];
WD40andTape 6:f0a18e28a322 682 stringstream(tokens[9]) >> input.duration;
WD40andTape 6:f0a18e28a322 683
WD40andTape 6:f0a18e28a322 684 if(input.psi[0][0] < 0.0) input.psi[0][0] = 0.0;
WD40andTape 6:f0a18e28a322 685 if(input.psi[0][1] < 0.0) input.psi[0][1] = 0.0;
WD40andTape 6:f0a18e28a322 686 if(input.psi[0][2] < 0.0) input.psi[0][2] = 0.0;
WD40andTape 6:f0a18e28a322 687 if(input.psi[1][0] < 0.0) input.psi[1][0] = 0.0;
WD40andTape 6:f0a18e28a322 688 if(input.psi[1][1] < 0.0) input.psi[1][1] = 0.0;
WD40andTape 6:f0a18e28a322 689 if(input.psi[1][2] < 0.0) input.psi[1][2] = 0.0;
WD40andTape 6:f0a18e28a322 690 if(input.psi[2][0] < 0.0) input.psi[2][0] = 0.0;
WD40andTape 6:f0a18e28a322 691 if(input.psi[2][1] < 0.0) input.psi[2][1] = 0.0;
WD40andTape 6:f0a18e28a322 692 if(input.psi[2][2] < 0.0) input.psi[2][2] = 0.0;
WD40andTape 6:f0a18e28a322 693 if(input.duration < 0.0) input.duration = 0.0;
WD40andTape 6:f0a18e28a322 694 /*if( input.psi[2][0] > 0.14 ) {
WD40andTape 6:f0a18e28a322 695 printf("Hi\n\r");
WD40andTape 6:f0a18e28a322 696 }*/
WD40andTape 6:f0a18e28a322 697 //throw std::invalid_argument( "received negative value" );
WD40andTape 6:f0a18e28a322 698 //return 0;
WD40andTape 6:f0a18e28a322 699 return input;
WD40andTape 6:f0a18e28a322 700 } // End of consume_message()