-
Understanding the Anatomy
07/18/2016 at 23:32 • 1 commentThe following log is my humble attempt at understanding the bio-mechanics of the foot. The image above is a 3D print of an anatomically correct foot skeleton, consisting of 26 bones. It is also over 25% of your body's total musculo-skeletal anatomy, hitting the ground every time you walk or run! This really demonstrates the complexity and beauty of the system which we use for transport. I find the geometry fascinating, it seems the volume distribution relates directly to function, becoming thinner in the middle and thicker at the extremities.
I stumbled upon this article which I thought was very informative, it describes the foot as a vault, which has three main weight bearing focal points. If we consider a bio-mechanical ideal gait then the pressure distribution is as illustrated below. By averaging these points we can then obtain the gaitline, it is by calculating this line from the 16 sensors that we can diagnose the patient.
Once diagnosed the methodology to create the insole is not so clear and subject to much contraction within the field. I am starting to build my own process but I'll refrain to elaborate until I've done more research and testing.
To end this log I just wanted to share a quick update on the hardware, it most definitely took much longer than it should but it's now working properly. You can see below the insoles inserted in an old pair nike. The target sample rate of 40ms was achieved, I've even managed to get it down to 20ms which could come in useful in certain sports.
Finally, a brief real time replay in the software, even though there is much work to be done on the analytical side I think it's interesting to see the prominence of the three main weight bearing points.
-
Software v1.2
06/27/2016 at 15:18 • 0 commentsIn preparation for a presentation I thought I would spend a little more time visualising the data. It seemed like a nice idea to have the in-sole in 3D with the pressure mapped to the Z height.
I started by modelling a mockup grid in grasshopper and exported the points as csv files which are easy to handle on the processing side. However because not every cell has four sides I had to find a way to 'embed' the tree structure in a csv, you can the number of side concatenated as the first variable in grasshopper circled in red.. Be sure to check the order of the points before exporting, I found that GH had somehow mixed them round.
In the previous log I described a process of interpolation on a pixel basis which turned out to be extremely inefficient, running at 8fps on mac book air. So I decided to split the shape into a grid and calculate the force only at the corners of each cell.
The gradient function stayed the same, by playing with the exponent (y) we can control the fall off. It's just a common remapping formula with an additional force scalar at the end. We also say that for any sensor we won't look beyond a certain distance, this is only for the purpose of visualisation so the exact absorbance 'radius' does not matter too much.
Float zHeight = (lowTo + ((distance^y) - lowFrom) * (highTo - lowTo) / (highFrom^y) - lowFrom) * force
The sketch now runs at smoothly at 45fps which leaves plenty of room for further calculations.
Todo list:
- Distribution through time
- Center of gravity
- Per Sensor time/pressure graph
- Sensor Calibration
- User Software Calibration
-
Software Prototype Development
06/21/2016 at 20:06 • 0 commentsI though it would be worth making a short log on writing the code to visualise the data. Please note that I have not yet linked it with the sensors. The visualisation below was made in Processing using random perlin noise for the development.
The trick here is to interpolate the readings between each sensors. In order to rationalise the problem we must first decide to what level of accuracy we want to be making the calculations. In this example this was done on the scale of one pixel, meaning that for every pixel we calculate the its colour relative to the strongest force. To re-iterate, if the force from the closest sensor for any given pixel is lesser than the second closest sensor then we ignore the latter and register the former.
Now we've covered the basic logic we must create a function that will give us the gradient we're looking for. The following code will only work as expected if you've already carried out the calculations necessary for a linear force/resistance relationship.
// The distances for from every pixel to each sensor is calculated and stored in setup() int [][][] distances = new int [sensor_Num] [mask.width] [mask.height] // We need a temporary matrix to store the forces until we draw then // Must be initialised float [][] temp_matrix; // A function which take the masks and returns the heatmap as a PImage PImage dispHeat(PImage mask) { // Create and load the output image PImage pout = createImage(mask.width, mask.height, HSB); pout.loadPixels(); // Save the max and min for final remap float max =-1 ; float min = 10^4; // Start with an arbitrary high value // Max force for any sensor in gr, obtained in calibration int max_force = 8354; for (int i = 0; i < sensor_csv.length; i++) { // For every sensor for (int x = 0; x < pout.width; x ++ ) { // For every pixel in width for (int y = 0; y < pout.height; y++ ) { // For every pixel in height if (mask.pixels[x+(mask.width*y)] == color(0, 0, 0)) { // If the pixel on the mask is back then proceed // Changing the exponent will change the sharpness of the gradient float pressure = map(pow(distances[i][x][y], 3), 0, pow(max_force, 3), 0.1, 0) * raw_sensor[i] ; if (pressure > temp_matrix[x][y]) { // If new pressure is greater than last then update temp_matrix[x][y] = pressure; } if (pressure > max) max = pressure; // Save max and min if (pressure < min) min = pressure; } } } } heatmap.loadPixels(); for (int i = 0; i < pout.width*pout.height; i++) { int x = i%pout.width; // Find XY coordinate int y = i/pout.width; if (mask.pixels[x+(mask.width*y)] == color(0, 0, 0)) { // If the pixel on the mask is back float col = map(temp_matrix[x][y], min, max, 180, 0); // Then draw the result pout.pixels[i] = color(col, 255, 255); } } pout.updatePixels(); return pout; }
Mask used as the input to the function
On my macbook air 1.6 GHz Intel Core i5, 4 GB DDR3 the program runs at 20fps which isn't surprising considering it's iterating through 40,000 pixels every cycle. However as we won't be visualising the data at the same time as recording it, it won't be a problem for the final sample rate.
There's a lot more to say about the software but I'll keep that for a future log once I've stream lined the process.
-
First Hardware Prototype
06/20/2016 at 12:47 • 0 comments1. Hardware Choice
The choice of hardware was all fairly straight forward except for the sensors. In the image you can see a range of sensor which I've tested, ranging from £22.50 to £0.70. The piezo sensors (metal backing) which were the cheapest performed surprisingly well, however I settled for the FSR 400 series for three reasons. They're flexible, much cheaper than the Flexiforce and has very good documentation on the calculations needed to get a linear relationship between force and resistance. As for the rest of the hardware I don't think it's worth elaborating, I chose the Arduino Micro for it's small form factor and the HC4067 because it read all 16 sensors from one chip, pretty handy right?
2. Insole 3D Modelling
So now we've got the hardware sorted I want to explain the 3D modelling process, which was carried out in Solidworks. There's nothing particularly complicated about it but what needs consideration is the placement of the sensors and cable management.
Prior to starting the project I read a number of papers around Bio-mechanics, Orthopedics and the design process of footwear. This is where I found the picture below (foot anatomical points) which I used to distribute the sensors. However the size of the sensor itself is too large to be placed on every point, therefore it took some interpretation.
In the second version (pictured below) I added a stress relief for the cable. Once printed the part is left to cool down to room temperature, after which it was removed from the bed. We then place it back on the bed and heat up to 60° which allows to bend the tab perpendicular to the sole. NOTES: Once printed it must first be removed from the bed otherwise the part will stretch whilst bending due to it sticking | Temperatures are only valid for PLA
You can find the 3D model (.stl) in the files project named insole_V2.1
3. Assembly
The top side turned out fairly well, I used electrical tape to keep the sensor in place for now, bear in mind this is a temporary prototype so nothing is fixed permanently.
Even after a pedantic cable management planning process the first prototype is rather disastrous. The overlapping cables will probably cause the connections to fail during exercise, so I haven't and won't be testing this prototype during exercise. To solve this I'm looking at etching a PCB for the second prototype, if you're reading this and have a better solution please comment. :)
3. Extra
As a last note for this first update I thought I would also share an experiment which I won't be using but is interesting. The first version of the printed prototype was molded by re-heating it to 65°, placing in the shoe and putting my foot on it until cooled. It produced a very nice result however I decided against it for two reasons. For the data to be as accurate as possible the shoe must be as neutral as possible (flat), additionally the sensors are prone to giving false values when bent.
Furthermore, all the lowest points on this insole (high pressure) have a sensor located more or less in the middle, which confirms they are correctly placed. However, these insole are designed for anyone to wear during diagnosis which makes for another reason not to mold them.
Finally here's a picture of the controller itself, it's not as small as I want it to be but hopefully that can be improved in the second iteration. NOTE: the resistors in the picture below are hidden behind the HC4067Because the wiring of the FSR sensor is very well documented I won't be going into it, however I've made a quick schematic of the wiring of one sensor which can easily be scaled up.