Human Hip Joint Mechanics - An Investigation into the Effects of Femoral Head Endoprosthetic Replacements using In Vivo and In Vitro Pressure Data by Kjirste Lynn Carlson Submitted to the Department of Mechanical Engineering in partial fulfillment of the requirements for the degree of Doctor of Philosophy in Mechanical Engineering at the MASSACHUSETTS INSTITUTE OF TECHNOLOGY May 1993 © Massachusetts Institute of Technology 1993. All rights reserved. Author ................. Department of Mechanical Engineering May 21, 1993 Certified by .. ..................................... Robert W. Mann Professor Emeritus Thesis Supervisor Accepted by....................... Ain A. Sonin Chairman, Departmental Committee on Graduate Students MASSACHULeE7'-NSTrIU'T no' - .n.^. NOV 2 9 1993 Human Hip Joint Mechanics - An Investigation into the Effects of Femoral Head Endoprosthetic Replacements using In Vivo and In Vitro Pressure Data by Kjirste Lynn Carlson Submitted to the Department of Mechanical Engineering on May 21, 1993, in partial fulfillment of the requirements for the degree of Doctor of Philosophy in Mechanical Engineering Abstract The development and implantation of two pressure-instrumented femoral head prostheses and the subsequent posthumous recovery of one of the prostheses provide an unique opportunity for study, both in vivo and in vitro, of the human hip joint. In vivo data, including kinematics and external forces coordinated with the local cartilage pressures were acquired over a period of 5 years beginning in June 1984 from the first prosthesis, and thus far for a year from a second prosthesis, implanted in December 1991. Comparison of the data from the two subjects provide information on the effect of small mismatches (< 1 mm) in prosthesis fit and on the changes cartilage undergoes when in contact with a prosthetic femoral head for extended periods of time in vivo. Data from these two subjects also provides valuable information on the magnitude and location of maximum stresses in the hip joint, the timing of pressure changes, on the presence of muscle co-contraction forces during some movements, and on the effects of rehabilitation exercises. The acetabular location of high pressure regions in general supports Wolff's law on bone response to loading; the highest stresses on the pelvis corresponded to the most dense bone. Location and size differences in the region over which high stresses were measured for the two prostheses can be attributed to the slightly over-sized and slightly under-sized fit of the prostheses; regions of high pressure were more localized for the under-sized prosthesis in analogy to Hertz stresses. Changes in the distribution of high pressures on the acetabulum were found to occur over the implantation period for both subjects. The location and distribution of stresses also varied with the movement performed. Pressure measurements from the two subjects were normalized by body weight over height squared. Maximum normalized pressures were found to change over the implantation period, in a similar manner, for both subjects for the post-operative year. Maximum normalized pressures were usually found to be slightly higher for the slightly under-sized prosthesis, however the maximum pressures and maximum 2 normalized pressures covered a similar range for the two subjects, despite significant differences in their morphology, mobility and coordination. The movements for which the highest normalized pressures were measured were different for the two subjects; rising from a chair resulted in the highest pressure measurements from the first subject while climbing and descending stairs produced higher measurements for the second subject. The highest pressures measured from the second subject were during jumping off a step, a movement not performed by the first subject. The normalized maximum pressures during gait are in the range of 20-25 (MPa/(weight/ht 2 )) for both subjects during the first year post-operative. Thesis Supervisor: Robert W. Mann Title: Professor Emeritus 3 Acknowledgements This thesis has taken longer to complete than many and as a result the number of people who have helped along the way is greater than the number of pages in this document. I wish I could thank each one appropriately here but in the interest of conserving paper and time I can only mention a few people. The work done for this thesis would not have been possible without the support and encouragement of Professor Robert Mann. His vision has guided the work done on this project through a sucession of students over a period of nearly 30 years. I feel extremely fortunate to have been in the Newman lab for Biomechanics and to have worked with Professor Mann on a part of the "hip project". I have a great deal of respect for his work in assembling and motivating students, for his skills as an educator as well as a researcher. I also want to thank the folks in the lab in general, the characters change over the course of years, but it has been a wonderful place to work throughout the time I've spent here. I believe that the Newman lab is possibly the best working environment for graduate students at M.I.T., through a combination of the people in i and the vision and style of the faculty members associated with the lab. Funding for this research has come in part from the National Institute on Disability and Rehabilitation Research, grant REC-H133E80024. Many thanks also to the Whitaker Foundation, which contributed to the support of this research. This thesis might never have been completed with out the help of my wonderful boyfriend, John Morrell, who helped me enormously during the difficult final phases this year. I hope I can be as supportive and helpful in return someday. Finally, I want to thank my parents, Nels and LaVerne Carlson, for believing in me all along. 4 Contents 1 Introduction 1.1 Thesis Goals ................................ 17 1.2 Investigation Procedure .......................... 21 .......................... 22 1.3 2 17 Thesis Organization Background 25 2.1 Instrumented Prosthesis History ................... .. 2.2 Other Research on Joint Forces and Cartilage Pressures ........ 25 26 3 Apparatus 29 3.1 Instrumented Prosthesis 3.1.1 Overview ......................... 29 ............................ . 3.2 Data Acquisition ............................. 3.2.1 36 Kinematic data acquisition ................... . 3.2.2 Pressure data acquisition ................... 3.2.3 4 .. Hip Simulator ........................... 37 41 4.1 Interpretation of Transducer Output Sampling Rate . ................... 4.4 Kinematic Data Processing ........................ 4.5 Transformation to Acetabular Coordinates Change ................. 41 ............................. 4.3 Normalization of Pressure Data . 4.5.1 36 39 Processing 4.2 29 in Coordinate Systems 5 . . 48 . 49 50 . .............. . . . . . . . . . . . . . . . . . 50 50 4.5.2 Timing............................... ..... 4.6 Graphical Displays........... 5 57 . 59 Results 69 5.1 69 Gait .................................... 5.1.1 Free Speed GeSi. Iul. 5.1.2 Free Speed Ga it: Prosthesis 43 I .L QPI\cthc~c QR . . JlJL3 . . 70 .i ..... 75 Ij 5.2 5.3 5.1.3 Paced Gait: P rosthesis 33 ........ 5.1.4 Paced Gait: P rosthesis 43 ........ 6 · · · · I Rising from a Chair ·. . 5.2.1 Prosthesis 33 . 5.2.2 Prosthesis 43 . Stairs ......... . 5.3.1 Prosthesis 33 5.3.2 Prosthesis 43 . . . . . . 5.4.1 Prosthesis 33 5.4.2 Prosthesis 43 Single-Leg Stance . . 33 . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 .. . . 98 . . . . 102 . . . ..........89 . . . .. .. . . . . . . 5.4 Isometric Abduction 5.5 81 . . . . . 109 . 109 . 110 . . . . . 128 . . . . .. . . . . . . . . . . .~~~ . . . . . . . . 128 . . . . . . . . . . . . .. . . . . 128 . . . . . ................. 5.5.1 Prosthesis 5.5.2 Prosthesis 43 ...... . . . . . . . . . . 135 135 . . . 138 145 Discussion 6.1 Endoprosthesis mismatch to acetabulum 6.2 Cartilage adaptation to pressure ..... 6.3 Bone response to pressure loading ... 6.4 Pressure magnitude ............ .. . . . . .. . . . . . . . . . . . 145 146 150 152 155 7 Conclusions A Transdu:er .. . . Locations and Numbering 6 159 B Calibration of Pressure Instrumented Prostheses 163 C Temperature Calibration of Pressure Instrumented Prostheses 201 D Interface circuit between Prosthesis data receiver and the AT&T 6300+ PC 233 237 E Initial Processing of pressure data E.1 Programs for collection of pressure data ................. 240 E.2 Programs for initial processing of data from Prosthesis 43 ....... 259 E.3 Programs for obtaining acetabular locations of pressure measurements 312 For data from prosthesis 43 ................... 312 E.3.2 For data from prosthesis 33 ................... 364 E.3.1 E.3.3 E.4 Programs for data taken after 198(i from prosthesis 33 ..... 407 . . . . . . . . . . .... 417 Programs for acetabular regional information 7 8 List of Figures 18 1-1 Human Hip Joint: Frontal Cross-section [from Tepic [22]] ....... 3-1 Pressure Instrumented Prosthesis: External View [from Carlson [6]] . 31 3-2 Location of central transducer ...................... 32 3-3 Pressure Transducer Mechanical Structure 33 3-4 Equipment setup for Data Acquisition ............... 38 ................. 4-1 Signal from Prosthesis 43 ......................... 43 4-2 Procedure for processing pressure data 44 ................. 4-3 Prosthesis Coordinate Frame ....................... 4-4 Prosthesis and Stem Coordinates 4-5 Stem to Femoral Coordinates 4-6 Definition of clinical joint angles ................... 52 ................... . ................... ... .. 4-7 Relationship between Pelvis and Acetabular coordinates ....... 54 55 56 58 4-8 Pressure vs. Time ............................. 61 4-9 62 Normalized Pressure vs. Time ...................... 4-10 Joint Angles vs. Time 63 .......................... ..... 4-11 Forceplate forces vs. Time ................... 64 4-12 Maximum Local Acetabular Pressures .................. 66 4-13 Maximum Pressures displayed at Transducer Locations ........ 67 5-1 Pressures for subject 1: Free Speed Walking .............. 72 5-2 Forceplate data for subject 1: Free Speed Gait ............. 73 5-3 Joint Angles for Subject 1: Free Speed Gait 74 9 .............. 5-4 Regional Maximums for Subject 1. Free Speed Gait .......... 76 5-5 Pressures in the Hip Joint: Free Speed Walking ............ 77 5-6 Forceplate data for subject 2: Free Speed Gait ............. 78 5-7 Regional Maximums for Subject 2: Free Speed Gait .......... 79 5-8 Joint Angles for Subject 2: Free Speed Gait .............. 80 5-9 Pressures for subject 1: Walking at 120 BPM ............. 82 5-10 Forceplate data for subject 1: Walking at 120 BPM . 5-11 Joint Angles for Subject 1: Walking at 120 BPM 5-12 Pressures for subject 1: Walking at 80 BPM . . ..... . .......... 85 .......... 5-14 Joint Angles for Subject 1: Walking at 80 BPM . . 5-16 Regional Maximums for Subject 1: Walking at 80 BPM . . . . . . 87 .... 88 .... 88 ............ 5-18 Forceplate data for subject 2: Walking at 120 BPM . 5-19 Joint Angles for Subject 2: Walking at 120 BPM 86 ...... 5-15 Regional Maximums for Subject 1: Walking at 120 BPM .. 5-17 Pressures for subject 2: Walking at 120 BPM 84 ............. 5-13 Forceplate data for subject 1: Walking at 80 BPM . 83 90 ..... 91 ...... 92 5-20 Regional Maximums for Subject 2: Walking at 120 BPM ...... 93 5-21 Pressures for subject 2: Walking at 60 BPM .............. 94 5-22 Forceplate data for subject 2: Walking at 60 BPM ........... 95 5-23 Joint Angles for Subject 2: Walking at 60 BPM ............ 96 5-24 Regional Maximums for Subject 2: Walking at 60 BPM ........ 97 5-25 Pressures for subject 1: Rising from a chair ............... 100 5-26 Forceplate data for subject 1: Rising from a chair ........... 101 5-27 Joint Angles for Subject 1: Rising from a chair ............ 103 5-28 Regional Maximums for Subject 1: Rising from a chair ........ 104 5-29 Pressures for subject 2: Rising from a chair ............... 105 5-30 Forceplate data for subject 2: Rising from a chair ........... 106 5-31 Joint Angles for Subject 2: Rising from a chair ............. 107 5-32 Regional Maximums for Subject 2: Rising from a chair ........ 108 5-33 Pressures for subject 1: Ascending Stairs ................ 111 10 5-34 Forceplate data for subject 1: Ascending Stairs 112 5-35 Joint Angles for Subject 1: Ascending Stairs ....... 113 5-36 Regional Maximums for Subject 1: Ascending Stairs . . . 114 ........ 115 5-38 Forceplate data for subject 1: Descending Stairs. 116 5-37 Pressures for subject 1: Descending Stairs ...... 5-39 Joint Angles for Subject 1: Descending Stairs 117 5-40 Regional Maximums for Subject 1: Descending Stairs . . 118 5-41 Pressures for subject 2: Ascending Stairs ......... 120 5-42 Forceplate data for subject 2: Ascending Stairs 121 5-43 Joint Angles for Subject 2: Ascending Stairs ....... 122 5-44 Regional Maximums for Subject 2: Ascending Stairs . . 123 5-45 Pressures for subject 2: Descending Stairs 124 ........ 5-46 Forceplate data for subject 2: Descending Stairs ..... 5-47 Joint Angles for Subject 2: Descending Stairs 125 ...... 126 5-48 Regional Maximums for Subject 2: Descending Stairs 127 5-49 Pressures for subject 1: Isometric Abduction ....... 129 5-50 Joint Angles for Subject 1: Isometric Abduction ..... 130 5-51 Regional Maximums for Subject 1: Isometric Abduction 5-52 Pressures for subject 2: MVIC Abduction ........ 132 5-53 Regional Maximums for Subject 2: MVIC Abduction, pos t-operative 5-54 Regional Maximums for Subject 2: MVIC Abduction 5-55 Pressures for subject 1: Single-Leg Stance 5-56 Forceplate data for subject 1: Single-Leg Stance ..... ...... 5-58 Regional Maximums for Subject 1: Single-Leg Stance . . 5-59 Pressures for subject 2: Single-Leg Stance ........ 5-60 Forceplate data for subject 2: Single-Leg Stance ..... 5-61 Joint Angles for Subject 2: Single-Leg Stance ...... 5-62 Regional Maximums for Subject 2: Single-Leg Stance 11 133 . . . . . . . . . 134 ........ 5-57 Joint Angles for Subject 1: Single-Leg Stance 131 136 137 139 140 141 142 143 144 6-1 Pressures for Subject 1 walking, July 5, 1984 ............ 147 6-2 Ultrasound data on Acetabular Cartilage Thickness for Subject 1 149 6-3 Xray of a left hip ........................... 151 A-1 Transducer locations in Prosthesis 33. 160 A-2 Transducer locations in Prosthesis 43 ................ 162 B-1 Pressure Vessel used for Calibration 165 of Prosthes ;is B-2 Experimental Setup for Pressure Calibration of Prostliesis B-3 Temperature during Pressure calibration tests B-4 Pressure Calibration of Prosthesis 33; Transduc er 1 . B-5 Pressure Calibration of Prosthesis 33; Transducer 2 B-6 Pressure Calibration of Prosthesis 33; Transducer 3 B-7 Pressure Calibration of Prosthesis 33; Transducer 4 B-8 Pressure Calibration of Prosthesis 33; Transducer 5 B-9 Pressure Calibration of Prosthesis 33; Transducer 6 B-10 Pressure Calibration of Prosthesis 33; Transducer 7 B-11 Pressure Calibration of Prosthesis 33; Transducer 8 B-12 Pressure Calibration of Prosthesis 33; Transducer 9 B-13 Pressure Calibration of Prosthesis 33; Transducer 10. B-14 Pressure Calibration of Prosthesis 33; Transducer 11 . B-15 Pressure Calibration of Prosthesis 33; Transducer 12. B-16 Pressure Calibration of Prosthesis 33; Transducer 13. B-17 Pressure Calibration of Prosthesis 33; Transducer 14. B-18 Pressure Calibration of Prosthesis 43; Transducer 1 B-19 Pressure Calibration of Prosthesis 43; Transducer 2 B-20 Pressure Calibration of Prosthesis 43; Transducer 3 B-21 Pressure Calibration of Prosthesis 43; Transducer 4 B-22 Pressure Calibration of Prosthesis 43; Transducer 5 B-23 Pressure Calibration of Prosthesis 43; Transducer 6 B-24 Pressure Calibration of Prosthesis 43; Transducer 7 12 ...... 166 ........ ..171 ........ . 173 ........ . 174 ........ . 176 ........ . 177 ........ . 178 ... ...... ....179 ........ ..180 ........ . 181 ........ . 182 ........ . 183 ........ . 184 ........ . 185 ........ ..186 ........ . 187 ........ ..189 ........ ..190 ........ . 192 175 188 191 .......... . . 193 B-25 Pressure Calibration of Prosthesis 43; Transducer 8 . .. .. . .. 194 B-26 Pressure Calibration of Prosthesis 43; Transducer 9 . . 195 B-27 Pressure Calibration of Prosthesis 43; Transducer 10 .. 196 B-28 Pressure Calibration of Prosthesis 43; Transducer 11 .. 197 B-29 Pressure Calibration of Prosthesis 43; Transducer 12 .. 198 B-30 Pressure Calibration of Prosthesis 43; Transducer 13 .. 199 C-1 Equipment for thermal calibration of Prosthesis 43 202 .......... C-2 Temperature Calibration of Prosthesis 33; Transducer 1 ........ 205 C-3 Temperature Calibration of Prosthesis 33; Transducer 2 ........ 206 C-4 Temperature Calibration of Prosthesis 33; Transducer 3 ........ 207 C-5 Temperature Calibration of Prosthesis 33; Transducer 5 ........ 208 C-6 Temperature Calibration of Prosthesis 33; Transducer 7 ........ 209 C-7 Temperature Calibration of Prosthesis 33; Transducer 9 ........ 210 C-8 Temperature Calibration of Prosthesis 33; Transducer 10 ....... 211 C-9 Temperature Calibration of Prosthesis 33; Transducer 11 ....... 212 C-10 Temperature Calibration of Prosthesis 33; Transducer 12 ....... 213 C-11 Temperature Calibi. tion of Prosthesis 33; Transducer 13 ....... 214 C-12 Thermistor ....... 216 C-13 Temperature Calibration of Prosthesis 43; Transducer 1 ........ 217 C-14 Temperature Calibration of Prosthesis 43; Transducer 2 ........ 218 C-15 Temperature Calibration of Prosthesis 43; Transducer 3 ........ 219 C-16 Temperature Calibration of Prosthesis 43; Transducer 4 . . . . . ... 220 C-17 Temperature Calibration of Prosthesis 43; Transducer 5 ........ 221 C-18 Temperature Calibration of Prosthesis 43; Transducer 6 ........ 222 C-19 Temperature Calibration of Prosthesis 43; Transducer 7 ........ 223 C-20 Temperature Calibration of Prosthesis 43; Transducer 8 ........ 224 C-21 Temperature Calibration of Prosthesis 43; Transducer 9 ........ 225 C-22 Temperature Calibration of Prosthesis 43; Transducer 10 ....... 226 C-23 Temperature Calibration of Prosthesis 43; Transducer 11 ....... 227 calibration . . . . . . . . . . . . . . . . 13 . C-24 Temperature Calibration of Prosthesis 43; Transducer 12 ....... 228 C-25 Temperature Calibration of Prosthesis 43; Transducer 13 ....... 229 C-26 Thermistor response to changes in temperature 230 ............ C-27 Response to changes in temperature ................... 231 D-1 Circuit Diagram for the Interface Box .................. 234 E-1 Equipment Set up for Data Collection .................. 238 E-2 Sample run through pcollect.eze ..................... 239 E-3 Initial Processing Procedure 241 ....................... E-4 Procedure for obtaining acetabular locations of pressure measurements 242 14 List of Tables 4.1 Alarm values ............................... 4.2 Thermal adjustment to transducer offsets for both prostheses ..... 45 4.3 Estimated offset errors for prosthesis 33 in vivo ............ 47 4.4 Sample Duration vs. Effective Sampling Rate for Prosthesis 43 ... 4.5 Maximum time can sample for at a given effective frequency, for Prosthesis 43 .................................. 41 . 48 49 A.1 Transducer Locations in theta and phi ................. 161 B.1 Pressure calibration tests ................... 1...... 167 B.2 Gains of prosthesis 33 pressure transducers ............... 169 B.3 Difference in pressure estimates for different gains ........... 169 B.4 Prosthesis 43 pressure transducer gains ................. 172 C.1 Gains of prosthesis 33 pressure transducers offsets with temperature . 204 C.2 Pressure estimate difference for prosthesis 33 using ex-vivo temperature calibration ................................. 204 C.3 Thermal adjustment to transducer offsets for Prosthesis 43 ...... 15 215 16 Chapter 1 Introduction 1.1 Thesis Goals The human hip joint has been extensively studied both analytically and through experiment. The joint itself is spherical, a ball and socket, and simpler mechanically than many other joints in the human body [Figure 1-1]. Despite its relatively simple geometry and kinematics the lifetime for replacement prostheses is only 5-10 years for a replacement of only the femoral head with an endoprosthesis, or 10-15 years for total joint replacement (THR) at the hip. [14, 24] Every year over 200,000 hip joint replacement operations are performed, of these, 40% are replacement of the femoral head alone. Within 5-10 years these prostheses require revision surgery. This short lifetime suggests that our understanding of the natural history of the joint following surgery is lacking in understanding and that improvements in replacement procedure and hardware are possible. The esearch presented in this thesis has two aims: (1) to better understand the mechanics of the human hip joint and its components; (2) to provide information to improve the success of the endoprosthetic hip joint. Towards these goals, as part of a research investigation of synovial joint biomechanics and osteoarthritis, a pressure-instrumented endoprosthesis was developed in the Newman Laboratory for Biomechanics at MIT. Two of these prostheses were implanted in consenting human subjects, making possible extended studies of the stresses on cartilage, and the pathophysiological response, in the human hip joint. 17 ill I Figure 1-1: Human Hip Joint: Frontal Cross-section [from Tepic [22]] 18 The two implanted prostheses were each very slightly different in size from the natural femoral heads which they were replacing, one being slightly oversized, the other slightly undersized in diameter. This difference was not planned, rather a consequence of the preordained size of the implant and the difficulty, during surgery, of sizing the natural acetabulum, but these circumstances presented the opportunity to evaluate the effect of small misfits in prosthesis size. Investigation into the effects of prosthesis misfit on the stresses in the human hip joint in vivo and on the physiological adaptation process that occurs to the human hip joint followingimplantation of an endoprosthesis is the focus of this thesis. This information may help elucidate how mechanical factors lead to osteoarthritis and identify the contribution of muscular co-contraction forces in producing high joint pressures, as well as explicating reasons for failure of endoprosthetic joints. The measurements, analyses, and comparisons herein were performed in part to investigate the hypothesis that even a small misfit may affect the stress distribution in the human hip joint and the performanceof the prosthetic joint. For the two subjects who have had instrumented femoral head endoprostheses, the prosthesis implanted in the first subject was 0.6 mm over-sized in diameter relative to the natural femoral head, and the prosthesis implanted in the second subject was 0.7 mm under-sized in diameter. Previous in vitro studies by our group, at a time when commercial endoprostheses were produced in 1/8" [3 mm] increments in diameter have shown that mismatches of 1 or 2 mm in femoral head diameter can produce profound differences in the loading distribution of the endoprosthesis on the cartilage in the joint. [20] This information led to the development, testing, and then wide use of sizing gages to determine the proper prosthesis size to implant and to the availability of more closely spaced prosthesis sizes. Femoral head sizes are available now in 1 mm increments, which means that many people are fitted with a prosthesis that is .5 mm too large or too small. No in vivo data on the effect of this small a mismatch had ever been available. Orthopedic surgeons sometimes operate under the premise that if a mismatch is unavoidable, implantation of an oversized prosthesis is preferable to implantation of an undersized prosthesis. This rule appeals to common sense, the area of con19 tact between the femoral head and cartilage will be larger and therefore the stresses should be more evenly distributed, however there has been no experimental proof or disproof. The chance occurrences which led to the implantation of two instrumented prostheses, each slightly mismatched to the particular subject in opposing directions, have produced a unique opportunity to investigate this hypothesis. Data obtained from the implanted instrumented prostheses over long periods of time provide information on the adaptation process of the natural cartilage of the acetabulum to the rigid metal endoprosthesis ball. Initially the cartilage presumably adapts to the different size of the replacement femoral head. More global remodelling may take place as the prosthesis performs as a part of the joint for longer periods of time; this frequently culminates in the protrusion of the prosthetic femoral head through the acetabular cartilage and the underlying bone. A common failure mode of femoral head replacement prostheses, the reasons for this occurance are not well understood. While this type of failure has not occurred with either subject, the acetabular cartilage of the first subject, who succumbed to an unrelated pathology, did show a substantial difference between the time of implantation and after 5 years of contact with the endoprosthesis. This study will shed light both on what changes occurred to the cartilage and on why those changes took place. Of general concern to all endoprosthetic procedures, the difference in long-term success of slightly oversized versus undersized prostheses is not known at all. Although the second prosthesis has been implanted for a only year thus far, some indication of what may occur in the future is evident in the data obtained thus far. What is clear is that over the long term the cartilage in constant contact with a prosthetic femoral head experiences degradation of a different type than that found in a natural joint. The initial thrust of this thesis was the comparison of joint forces in vivo to estimates of joint forces made from measurements of external forces to assess the importance of muscle co-contraction forces. In both subjects the maximum pressures recorded during activities such as rising from a chair or ascending stairs was considerably higher than would be expected from the dynamics alone. Concurrent recording of electromyographic signals from agonist and antagonist muscle pairs about the hip 20 joint confirmed that muscular co-contraction was augmenting the dynamic and inertial forces at the hip. Attempts to estimate the hip force vector from the pressure data were unsatisfactory due to the paucity of reporting transducers, leading to the decision to design a new prosthesis which measures force directly. This research will be reported in future efforts of our group. As part of this thesis much effort was directed at assessing the effect of impact forces at the foot on the loading in the hip joint. Howeverit proved difficult to obtain consistent data for impact loading tests, with synchronization of external kinematic and dynamic variables and the internally measured pressures. This will also be addressed in the future with the new prosthesis design. 1.2 Investigation Procedure Pressure data from two subjects are compared in this thesis, primarily the comparison of maximum pressures measured in each acetabular region. Since the pressure transducers are in the metal femoral head, while of interest is where they are on acetabular cartilage, kinematic variables in the relationship between femur and pelvis are employed throughout to make this transition. Comparison of data between the two subjects is done through normalization of the pressures using subject weight and height and representation of data as in a right hip orientation. (One prosthesis was implanted in a right hip, the other in a left hip.) The change in pressures over the implantation period for a standardized test protocol provides information on the effect of joint adaptation to the prosthesis. The first pressure-instrumented prosthesis was implanted in June 1984, in a 73year-old woman, who was 1.68 m tall and weighed 663 N. The data reported herein was acquired during testing every 3 to 6 months for the next 5 years. In late 1989 she died of an unrelated cause. Arrangements had been for donation of the prosthesis and the matching hemipelvis. The second prosthesis was implanted in December 1991 when a suitable subject was found, in this case an 82-year-old man, who was 1.6 m tall and weighed 529 N. Data has been acquired from this subject for a year as 21 reported herein, and data continues to be taken every few months. During the immediate post-operative phase of patient management primarily pressure data is gathered, supplemented at times with external measurements of leg angle or force exerted by the leg against a force transducer. From 10 days post-surgical the subject is capable of coming to the Biomotion Laboratory at Massachusestts General Hospital (MGH); where kinematic and forceplate data can be synchronized with the pressure data. Sets of synchronized pressure, kinematic, and forceplate data exist for 5 years of test sessions with the first subject, and now for three test sessions with the second subject. In addition to investigating the changes that occurred over time and the differences between the two prostheses, pressures were also compared for changes in activity level, for instance, walking at 60 beats per minute (BPM), walking at 120 BPM, unpaced walking, and walking in place. Forceplate information is used on data comparison, primarily the timing of pressure changes vs. that of rise of external force. Additionally, pressures measured in vitro on the excised hemipelvis and retrieved prosthesis in the MIT hip simulator were compared to those previously obtained in vivo for similar kinematic and loading configurations. Ultrasound measurements of the acetabular cartilage region of the explant were made by another researcher [26] and these data were used to compare acetabular thickness to regional maximum pressures. 1.3 Thesis Organization Chapter 2 presents relevant aspects of the history of the development of the pressure instrumented prostheses and discusses the results of other researchers in this field. Chapter 3 describes the equipment used to take data, while Chapter 4 discusses the processing of data. Chapter 5 presents results for selected tests organized by movement and by subject. A discussion of the trends observed in these results and their implications is presented in Chapter 6. Detailed information on transducer calibration and on the location of transducers in the prostheses are presented in the appendices, as is information on the computer programs for data acquisition programs 22 and test equipment circuitry. 23 24 Chapter 2 Background 2.1 Instrumented Prosthesis History Experimental and analytical study of the human hip joint has been underway at MIT in the Newman Laboratory since 1966. At that time C.E. C'arlson began design of a pressure instrumented femoral head prosthesis for measurement of the loading in the human hip joint. [6, 17] The currently implanted instrumented prostheses are very similar to his prototype, although several aspects were altered in response to results obtained from in vitro testing of the original prostheses. Information about the pressure-instrumented prosthesis structure and data output essential to this thesis are in Chapters 3 and 4 and in Appendices A, B and C. More information on the design and on the telemetry electronics can be found in [6, 7, 5]. Human implantation of a pressure-instrumented prosthesis was a goal of the project from the outset. This intention dictated some of the initial design parameters and necessitated some of the redesign process. Extensive in vitro testing, using the sme pressure instrumentation, but with hard-wired output, preceded implantation. But no degree of in vitro results can substitute for in vivo data. Among other considerations in vivo data was a priority in light of the fact that the muscle forces acting across a joint in life are not known. Design specifications for the prosthesis included: subject safety; performance characteristics identical or superior to standard prostheses of this type; high data accuracy; adequate high frequency response 25 to faithfully record effects of human motion; minimum patient encumberence during data acquisition; as many pressure transducers as possible given the joint geometry; data acquisition ability for more than 2 years post-implantation. The prosthesis itself is similar to a Moore endoprosthesis, however at 14 locations on the femoral ball the spherical wall thickness is reduced to a thin diaphragm. Deflection of these diaphragms due to a localized pressure between the ball and acetabular cartilage is measured and output via radio-telemetry. Power is supplied to the electronics in the femoral ball externally through a magnetic power induction link. Calibration of the assembled prostheses (covered in detail in Appendices B and C ) indicated that transducer output could be interpreted accurately from 10 transducers in the first implanted prosthesis and from 12 transducers in the more recently implanted prosthesis. Although the number of transducers is as large as possible for the available space, unfortunately they do not report enough data to accurately interpolate pressure contours over the entire surface at any given instant in a test. [9] Thus, in vivo data on the force vector during movements has not been possible with this prosthesis design. 2.2 Other Research on Joint Forces and Cartilage Pressures The most common approach to the problem of estimating joint forces has been analytical, based on experimental kinematic, kinetic, body morphological, and electromyographic data. Some such studies have considered the results of in vitro tests. The analytical approach allows consideration of the normal joint; however much information on relevant parameters is lacking and many simplifying assumptions must be made to reduce the problem to a manageable one. The basic technique is inverse Newtonian analysis; foot-floor forces and moments can be measured with satisfactory accuracy and precision. The foot is then assumed to be a solid object with kinematic variables, positions and rotations measured by some stereographic movement analysis system. Most of these read position data from 26 markers on the body segment. Calibration issues, recording fidelity, 3-D reconstruction algorithms, system noise (enhanced by differentiation to determine velocities and then accelerations), all contaminate the kinematic data to various degrees. Then the mass, center of mass, and several inertias of the limb segment must be estimated by methods ranging from anthromorphic scaling of cadaver experiments to use of computer-tomographic data. With acceleration and mass-inertial estimates, the causative forces and moments can be estimated, for the example here, at the ankle. This analytical procedure is repeated treating the shank as an isolated body, to get estimates of the knee forces and moments, followed by similar treatment of the thigh to arrive at estimates of hip forces and moments. Given the range of fidelity of inertial and kinematic data and the processing involved it is perhaps not surprising that estimates of hip forces in normal level walking range in the literature by almost a factor of 10. [21, 12, 19] Beyond these uncertainties the analytical procedure cannot include those forces across the joint which result from co-contraction of agonist-antagonist muscle pairs. Motion analyses can only reflect muscle pair imbalances which produce mlotion, ie. the difference between opposing muscle forces, whereas the joint experiences the force due to the sum of co-contracting muscles. That co-contraction is commonplace in virtually all movement is becoming increasingly clear both from the hip joint research reported in this thesis as well as from studies that show the movement control areas of the brain and spinal cord control the impedance as well as the motion of anatomical joints. [15] In vivo results for the force at the human hip joint were obtained by Rydell. [21] This study used a strain-gaged instrumented, modified Austin-Moore endoprosthesis with an over-long neck implanted in two subjects. The only data was taken at one test session 6 months post-operative, at which time the subjects may not have been fully recovered. The brevity of testing was dictated by the means of transmitting data; wires from the strain gages passed directly through an incision in the skin. The maximum joint force recorded was 4.3 times body weight for running. During walking the highest force measured was 3.3 times body weight. 27 Recently Bergmann et. al. have implanted 3 force instrumented total hip replacements: two in one subject and one in another. [3] These are total hip replacements, the entire natural joint has been replaced by a new metal ball and plastic socket, thus they intrinsically change the natural joint geometry, compared to endoprostheses where only the femoral head is replaced. In most technical respects the prostheses implanted by Bergmann et al [3] are similar to the ones from which results are reported here. They also inductively power the prostheses and use telemetered output. However, their prostheses are total hip replacements and they measure forces acting at the joint. No kinematic data concurrent with the internal force data is available, except for video of the subject during tests. Their results which are of interest here are that the resultant load direction is always close to the femoral-neck axis and that the load direction is nearly invariable at higher loading and longer time post-op.[2] The peak forces reported during walking were 300% BW. [2] Although they possess a forceplatform and are in a position to concurrently measure external forces and internal force at the joint, no information of this type has been published by this group of researchers. A number of in vitro studies have also been done on the human hip joint. Estimation or measurement of the surface pressure distribution has been more common in these investigations. Prior to 1980 researchers doing these studies estimated pressure at only a few locations using indirect methods and then inferred a uniform or axisymmetric sinusiodal pressure distribution. The first direct in vitro pressure measurements were made early in this project by Rushfeldt using an instrumented prosthesis similar to the ones discussed in this thesis in the hip simulator. [20] Results from his in vitro studies indicated that local pressures were much higher than previously assumed, and that non-uniform, steep pressure gradients can exist in hip joint articular cartilage. Similar pressure distributions were then found by Brown in experiments in which recesses were machined into the cartilage surface layer on the femoral head and accept small piezoresistive pressure transducers. [4] 28 Chapter 3 Apparatus The equipment used to collect the data reported in this thesis includes two pressure instrumented endoprostheses, the kinematic data acquisition system in the Biomotion Laboratory at Massachusetts General hospital (MGH), a pressure data acquisition system, and the hip simulator at MIT. Information describing each of these subsystems is presented here; other sources can be consulted for further information on the prostheses, the kinematic data acquisition system, and the hip simulator. Additional new equipment was designed and fabricated to allow calibration of the pressure instrumented prostheses; this equipment is discussed in Appendix B. 3.1 Instrumented Prosthesis 3.1.1 Overview The pressure instrumented prosthesis is essentially a Moore-type femoral head replacement; it takes the place of the natural femoral head and neck and is attached to a shaft which extends into the femoral canal. Figure 3-1 shows the external form of the prosthesis. This type of prosthesis is typically implanted in an individual who has sustained a fracture of the femoral neck and has no degradation of the acetabular cartilage. As a result the joint better replicates the natural human hip joint than does a total hip replacement prosthesis, in which both the ball (femoral head) and 29 the socket (acetabulum) are replaced. Since the acetabulum is natural, the ball location is predetermined. Provided the geometry between the natural femur and the natural femoral head is reproduced, an endoprosthesis maintains the anatomy of the natural joint. By contrast with total hip replacements, the removal of bone stock for the artificial components; and deliberate choices by the surgeon to reduce loading in the artificial joint usually changes the natural geometry of the joint. The implanted prostheses material is a cobalt chromium alloy (Stellite 21) a biocompatible alloy commonly used in endoprostheses. The stem and integral lower half of the femoral head was cast by Howmedica; the upper hemisphere containing the transducers was hot isostatically pressed from a sintered version of this same material and donated by Zimmer. The pressure transducers consist of 3 mm wells formed in the inner surface of this hemisphere by electron discharge machining. These wells are arranged with one central transducer surrounded by a ring of six, and an outer ring of six or seven transducers (differs in the two prostheses). The arrangement of the transducer wells for each prosthesis is shown in Appendix A. Figure 3-2 indicates the relationship of transducer 1 (the central transducer) to the prosthesis stem. The mechanical structure of the pressure transducers is shown in Figure 3-3. The thinner hemisphere diaphragm (0.46 mm) of the well is connected by a pin (restrained by a Teflon sleeve) to a strain-gaged, silicon-crystal cantilever beam. Deflection of the diaphragm (0.00028 mm per MPa) is proportional to the difference in pressure between the external and internal sides of the hemisphere wall and is transmitted via the sliding pin to the free end of the cantilever beam. The actual deflection of the much thicker (3 mm) shell is negligible and does not unduly influence the pressure measurement. The natural frequency of the transducer is 12 kHz. The second implanted prosthesis also contains a thermistor in another well in the inner surface of the hemisphere, location shown on the diagram of prosthesis 43 in Appendix A. The well in which the thermistor is placed is similar to the other wells but was not counter-bored. The transducers are powered and read through a radio-telemetry system contained in the prosthesis. External to the subject and the prosthesis are the power supply and 30 Figure 3-1: Pressure Instrumented Prosthesis: External View [from Carlson [6]] 31 I Figure 3-2: Location of central transducer 32 _ , d:f.831) PM -- J.a. 3 1 AN-6c I - imlm~mmmm~, _ la Diaphragm I .... l - /.2-7 IMa - Wall of IsN Hemisphere N1. Is Is Is I Is . 9 Imm I I , .~~_ _ Pin XStrain Gages Beam Figure 3-3: Pressure Transducer Mechanical Structure 33 signal receiver. Electronic circuitry in the ball sequentially powers the transducers and multiplexes the output signal from all transducers. A pair of insulated silver leads run down the stem of the prosthesis to the antenna inside a Teflon cap at the end of the stem. The prostheses are externally powered at 100 kHz. Data are output from the prostheses via radio-telemetry. The transducers are each operated at 250 or 500 Hz (500 Hz in the case of the newer prosthesis), and a single analog output carries information from all transducers serially. In addition this signal carries samples of a known voltage (1 V or 2.5 V) and of 0 V at the start of each sampling sequence. These signals are used for scaling of transducer output magnitude. Chapter 4 contains information on the signal format and interpretation of this signal. The telemetry device itself is more thoroughly described in [6, 7]. The electronic circuitry of the device isolates each transducer output and amplifies the pulse-amplitude-modulated (PAM) signal in an operational amplifier stage. The amplified signal is used to frequency modulate a 100 MHz oscillator. The resulting FM signal is transmitted to the external receiver through the antenna coil wound on a ferrite core at the end of the prosthesis stem. The signal collection and transmission system of the prosthesis is powered externally through a magnetic power induction link, which eliminates the lifetime restrictions (and biologically incompatible materials) of internal batteries. There are three components active in power transmission: 1) a 100 kHz power oscillator (HP Model 20SAH); 2) a primary coil contained either in a teflon sleeve which fits over the pros- thesis stem prior to implantation or a garter that fits over the subject's thigh; 3) a secondary coil inside the Teflon tip of the prosthesis stem, the same coil which acts as the PAM/FM transmitting antenna. Approximately 700mW are delivered to the telemetry system through the power system for the first implanted prosthesis, the newer prosthesis only requires approximately 30 mW. The hermetically sealed single-unit stucture of the prosthesis ensures protection of the subject from electronic materials. The equator between the stem part and the instrumented hemisphere is welded, after which the interior is sterilized by a baking and nitrous oxide gas process, after which the access hole is plugged and welded. The 34 leads from the ball interior to the stem pass through a glass to metal feed through. The integrity of the prosthesis structure also protects the electronic instrumentation and assures the extended lifetime and accuracy of the transducers. To the subject the prosthesis is indistinguishable from a normal Austin-Moore prosthesis whether powered or not, and it is only powered during data acquisition sessions in the lab. The risk of infection has proven non-existent. Interpretation and accuracy of the data transmitted from the prosthesis is ad- dressed in Chapter 4 and in appendices B and C. The relationship between transducer output and applied pressure is linear for most of the transducers and the gain of that relationship was found to be invariant with time and temperature. With no applied pressure the transducer output value was found to change over time and to depend on temperature as well. Appendices B and C contains information on how the transducers were calibrated and the results of that calibration process. The essential facts are that the transducers from which results are reported here behaved in a linear fashion and that recalibration in vivo of the transducer offset was accomplished by taking data with the subject relaxed and lying down. Previous work indicated that relaxed lying produced transducer outputs as low or lower than those obtained with traction applied to the leg. [8] There are 14 pressure transducers in the first implanted prosthesis, serial 33, and 13 pressure transducers in the second implanted prosthesis (serial 43). Of these, 4 were found to have non-linear behavior in serial 33 and 1 was found to be non-linear in serial 43. Results from non-linear transducers have not been reported. Estimation of the misfit of the two instrumented prostheses to their respective recipients was made from measurement of X-ray images of the femoral head. The femoral heads were also passed through a set of sizing gauges during the implantation process to ensure that the correct size prosthesis was implanted. The diameter of each prosthesis was measured with a micrometer. 35 3.2 Data Acquisition The data used in this thesis was collected over the period from 1984 to 1993. During this time computer systems were changing rapidly and as a result the data acquisition systems used changed too. One system was used throughout the implantation period for the first prosthesis and another set of systems has been used with the more recently implanted prosthesis. The earlier in vivo pressure, kinematic, and forceplate data were all collected by the same computer, a PDP 11/60 running the RSX-11M operating system. Now pressure data is collected on a PC while kinematic and forceplate data is collected on another computer (at first the same PDP 11/60 and now a 486 PC). The information that will be presented in this chapter can be supplimented with [8] for the data acquisition and processing from the first implanted prosthesis and information on the kinematic data acquisition system can be found in [1]. 3.2.1 Kinematic data acquisition All the kinematic data that will be reported in this thesis was collected at the MGH Biomotion Laboratory. This lab uses a version of a data acquisition system, called TRACK, developed in the Newman Laboratory for Biomechanics at MIT by Tetewsky, Conati, Ottenheimer, Antonsson, Mansfield and Lord. [22, 11, 1, 18, 16] Bilateral kinematic data are acquired by two sets of opto-electronic Selspot cameras. Each set of cameras can sense the locations of up to 32 infra-red light emitting diodes in the laboratory reference frame. These LEDs are mounted on rigid arrays of known dimensions attached to the subject's body segments. for now - put back in later The location and rotation of each body segment is computed by the TRACK software system. Kinematic data is stored in processed form as the 3-D location and orientation of coordinate systems fixed to each body segment. Forceplate data is acquired from two Kistler forceplates. The three components of forceplate data are saved from each forceplate. Forceplate and kinematic data are acquired simultaneously at the same rate, which has typically been 153 Hz. 36 3.2.2 Pressure data acquisition Data from the first implanted prosthesis was acquired by the same computer as the kinematic and forceplate data at a rate of 250 Hz per transducer. Many aspects of the data and the processing have not changed between the two prostheses, thus this section will deal explicitly with the newer prosthesis and note differences between the two. For an explanation of the data and processing from the older prosthesis only, refer to [8]. Pressure data are currently acquired on an AT&T 6300+ personal computer, this computer has a 80286 microprocessor but with an XT bus, using an Analog Devices RTI-815F multifunction card for the A/D. Data acquisition uses 2 or 3 A/D channels at 8 kHz for prosthesis 43, 4 kHz for prosthesis 33. This card stores data on the computer via DMA (direct memory access). Figure 3-4 shows the system as set up for data acquisition of 3 channels of data. The interface box between the receiver and the computer performs two additional functions; it buffers the computer from the signal which is used to trigger data sampling when data collection has not yet started and it contains a circuit which allowsthe computer to collect data at a lower rate. Data collection at a lower frequency was necessary because the DMA controller can only access a 32K block of memory locations and there is insufficient time while running the data acquisition program to transfer data from memory to a file. Appendix E covers the manner in which the interface circuit performs. Of the three channels of analog data, one is the actual transducer outputs, a second contains information required for processing and interpretation of the data, and the third contains auxiliary input (goniometer, force instrumented cane, foot switches, forceplates, TRACK synch signal) which are multiplexed onto a single channel by the auxiliary-multiplexer box. Data processing and analysis has been carried out on another personal computer, a 486 in the Newman Lab. This computer is also equipped to take data concurrently from a prosthesis and from the hip simulator and to control the hip simulator. 37 TRACK Synch data - output voltages - alarms - pulse 3 A/D channels Figure 3-4: Equipment setup for Data Acquisition 38 nation 3.2.3 Hip Simulator The hip simulator is a multi-axis electro-hydraulic machine in which a cadaver hip joint can be loaded in anatomical positions. Flexion angle, rotation, and load can be controlled (only two at a time). Measurements of those angles, the load, torque applied, and deflection can be obtained. This machine and the controller for it were developed by Carlson, Rushfeldt and Palmer. [20] 39 40 Chapter 4 Processing 4.1 Interpretation of Transducer Output Data from all transducers are multiplexed onto a single analog signal which is input to an A/D channel on the computer used for data acquisition. Data processing includes correctly demultiplexing and interpreting this data; information on this aspect of processing for prosthesis 33 can also be found in [8]. The procedure determines frame boundaries, identifies the scaling channels, demultiplexes the data, uses the thermal information, and applies transducer calibrations to determine the pressure corresponding to the transducer output signal. Figure 4-1 shows an example of the data signal collected from prosthesis 43. Also shown is the signal on a second A/D channel used to interpret the data channel. This second channel, referred to as the alarm channel, indicates any conditions which may indicate that the data is bad. The alarm channel also determines the start of each Table 4.1: Alarm values Alarms None Tuned AGC Tuned AGC Lock AGC Field 1 (V) -4.95 -4.3 -3.7 -3.05 -1.05 Field 2 (V) +0.31 +0.95 +1.6 +2.3 +4.2 41 Comments AV between fields - 5.3 V Signal from prosthesis not tuned Auto-gain for signal not set Not tuned and gain not set Phase-lock loop not synchronized franie of data. Table 4.1 contains the possible alarm values and their interpretation. A third A/D signal is also shown in Figure 4-1; this channel primarily contains data not required for pressure data processing; this channel however, has a signal which indicates when kinematic data is being acquired. In summary, three channels of A/D are required whenever kinematic data is acquired in order to determine the temporal relationship of the pressure and kinematic data. The data and alarm signal from prosthesis 43 is transmitted in two "fields". Each field includes 16 output values on the data channel. Both fields have the output from all pressure transducers and from the thermistor, field A also contains two constant voltage signals used to scale the transducer outputs and field B carries information defining the threshold above which data is compressed. The determination of which field is active is established by inspecting the alarm channel; the transition from one field to the other is used to find the frame start. Appendices B and C discuss calibration of the prostheses and Appendix E contains the programs used for initial processing of pressure data. Figure 4-2 shows a block diagram of the procedure. Factors that need to be considered are: thermal effects; decompression of data; scaling of the output; alarm conditions; offset of transducer output at zero pressure; and gain of transducer output with pressure. The thermal measurements for the test are averaged and interpreted via equation 4.1, where T is in degrees Fahrenheit and y is the thermistor output. This relationship was determined during the transducer calibration as detailed in Appendix C. The temperature at which measurements are made influences the offset in each transducer's pressure relation (equation 4.2). In this equation b represents the offset of transducer i, ai and c are the thermal adjustment factors for that transducer, and T is the mean temperature for that test. The thermal adjustment for each transducer offset is shown in Table 4.2. The programs that process data from prosthesis 33 define temperature in degrees C, while the processing programs for prosthesis 43 calculate temperature in degrees F. T= 2861.0)/0.339 /(y42 (4.1) Analog , 1tJ § ,ro,,,,,,, g_2f I I I I: Data I I I I I II@ I A , I T: P: L, 1 2, 3 4 5 6, '13, T C Z 1 2, 3 4 5, 6, 7, 8 9 ,10:11:12,1l3, II I II Sync/ I AlarmsA l Input Strobe: Sample Trigger I I I I I III I I I I I I IJ I I I I I I I I I ''\'FIELD gI I IJ I e IV I |a I II I I~ I I i2ti I I~3 I I I I I I I I I I I a I I a I I I I I I II FIELD2 I 1 t 2' 3 4 5 6 7' 89 '1011F1F2F3F4G 9 1011F1F2'F3F4G I I 1 2' . . . . . . . . . Sample~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' . .' . I. Ij. i . ' . . . . .' . . . .' . . . .' . C: Scaling signal 2.5 V Z.Scaling signal 0 V P: Power level L: Compression Level F1, F2, F3, F4: Foot Switches G: Goniomrneter t: Thermistor output Figure 4-1: Signal from Prosthesis 43 43 .' .' . . Data File i Find Frame-Synch - I iI I ! I I I I I I I e - / I I l II I Scale using constant V sigs. I I I I I - Adjust for Use temperature, inform ation I temperature i channels, calibration dat I Find in vivo zero offsets t I r I Decompress Find mean temperature from thermistor data q ~~~ - I I L Use gains from pressure calib. Restina data M- Adjust for Ik I offsets Pressure Data File Figure 4-2: Procedure for processing pressure data 44 I Table 4.2: Thermal adjustment to transducer offsets for both prostheses Prosthesis Transducer ai, C 33 1 2 3 5 7 9 10 11 12 13 -2.67 -8.45 -20.15 2.52 0.48 -32.95 -96.2 16.13 3.925 -37.3 0 0 0 0 0 0 0 0 0 0 43 1 2 3 5 6 7 8 9 10 11 12 13 -0.0308 -0.275 -0.412 -0.150 0.201 -0.113 -0.0564 -0.2899 -0.4408 -0.177 -0.0815 -0.0722 -153 1009 22 555 359 150 251 314 695 -159 1068 -175 45 bi = b - aT - c( (4.2) One of the signals transmitted in field B is the compression level. Any data in that frame above the threshold must be decompressed. Equation 4.3 indicates how this is done; L is the compression threshold and zi is the output of transducer i. The data is divided into the part belowthe compressionthreshold and the part above the threshold. The second part is multiplied by 4 and added to the compression threshold to obtain the actual value. Compression above a certain voltage was introduced in order to avoid saturating the A/D converter. In prosthesis 33 the compression threshold wasn't transmitted but was fixed at 3 V. Data above that value was also compressed 4:1. 4(2 - L) + L if 2 > L if = :ri X (43 (4.3) otherwise Two constant voltage signals are transmitted with the transducer outputs. The difference between these signals is used to appropriately scale the transducer output, as shown in equation 4.4 where Z represents a 0 V. signal and C represents a higher constant voltage. The 0 V signal is subtracted from both the data and the higher voltage signal (1 V for prosthesis 33 or 2.5 V for prosthesis 43). In this equation the result is the scaled transducer output in units of "corrected millivolts" (cmv). = 1000.0 C-Z) (4.4) The relationship between transducer output in cmv and pressure is linear for most of the transducers and can be described by a gain and an offset (data from the nonlinear transducers have not been used in results). As described above the offset at zero pressure changes with temperature; it also varies over time on the order of months for transducers in both prostheses. This variation necessitates some means of determining the offset after the prosthesis is implanted and a known calibrating pressure cannot be applied. After implantation the zero-pressure offset is estimated by 46 Table 4.3: Estimated offset errors for prosthesis 33 in vivo Est. ex-vivo offsets August 1989 (temp. corrected to 38.60 C in vivo offsets -1457 939 785 589 1673 -1051 375 935 25 -638 -1507 905 835 639 1657 -1041 425 871 -51.7 -662 Est. correction to in vivo pressure estimates (MPa) -0.7 -0.3 0.55 0.5 -0.2 0.1 0.44 -0.46 -0.58 -0.2 averaging data taken while the subject lies relaxed. These "zeros" are almost certainly not all at 0 MPa. The error introduced in pressure measurements is estimated in table 4.3. These were obtained by comparing prosthesis 33 post-vivo zeroes with the preceding in vivo data from prosthesis 33, after correction for temperature. The temperature correction was made using post-vivo temperature calibration data; in vivo the temperature in the hip was estimated at 38.6° C (101.50 F), using temperature data from the integra; thermistor implanted in prosthesis 43 in the second subject. A positive value indicates that the pressure in vivo was probably under-estimated by that amount, while a negative sign indicates that the in vivo estimates were probably over-estimated by the amount shown. The estimated error is relatively small for all transducers compared to the noise in the signal from this prosthesis which was +/0.3 MPa for some of the transducers. Prior to implantation the transducers were calibrated in a hydrostatic pressure chamber, and, in the case of prosthesis 33, post-vivo. The calibration procedure and equipment is detailed in Appendix B. The gain in the relationship between transducer output and pressure was found to be invariant with both temperature and over time. Pressures at each transducer are obtained through equation 4.5, in which zi is the 47 Table 4.4: Sample Duration vs. Effective Sampling Rate for Prosthesis 43 Time [sec] A/D Channels Eff. Freq. [Hz] 1 2 3 5 7 9 125 83.3 62.5 41.67 31.25 25 3 3 3 3 3 3 scaled transducer output in cmv, bi is the transducer offset adjusted for temperature, Gi is the transducer gain with pressure, yz, is the mean zero pressure reading for that day, and yi is the estimated pressure measured at transducer i. zi - bl xi-b 4.2 Yzi (4.5) Sampling Rate Some frames of data must be skipped in order to acquire data for long periods of time (1-10 seconds) and not exceed the DMA limitations. The data acquisition program is in Appendix E and in part consists of clock programming which enables the system to skip a number of frames between each pair of frames collected. A pair of frames of data are required for the interpretation of the pressure data. The number of frames skipped is therefore a multiple of two and varies with the length of time for which data is to be collected, in the trade-off to collect data at as high a frequency as possible. Tables 4.4 and 4.5 show the tradeoff between the length of time of data collection and the frequency of data acquisition. Of the two frames collected together, one set of transducer outputs is discarded to maintain a single sampling frequency. 48 Table 4.5: Maximum time can sample for at a given effective frequency, for Prosthesis 43 Effective Frequency 4.3 [Hz] Time [sec], 500 125 83.3 62.5 50 0.9 1.8 2.7 3.6 4.5 41.67 35.7 5.4 6.3 31.25 27.78 25 7.25 8.1 9.0 Normalization of Pressure Data The two subjects participating in this study were both implanted with the same size prosthesis, but were otherwise quite different in bodily dimensions. Therefore comparison of pressures between subjects requires some consideration of the physique of the respective subjects. Of a number of normalization factors considered, the dimensions which seem most relevant are body weight, height, acetabular area, and perhaps leg length or some indicator of the location of the center of mass. Since the two subjects have essentially the same size acetabulum, the normalization chosen was body weight over height-squared. This provides a non-dimensional number for comparison of data. A scaling factor of 1000 was applied to reduce the range of data values to 0 - 100. (The maximum value thus far is 82.3, from the second subject.) Equation 4.6 normalizes pressure data where yni is the normalized pressure, BW is body weight, and H is height. The first subject (implanted with prosthesis 33) weighed 665 N and was 1.68 m tall. The second subject (implanted with prosthesis 43) weighed between 530 and 578 N and was 1.6 m tall. yni 1000.0[ 49 W] (4.6) 4.4 Kinematic Data Processing The kinematic data was collected and processed at MGH using the version of the TRACK system installed at the Biomotion Laboratory. Kinematic data was processed according to the current methods used at that facility at the time of data collection, thus not all of the kinematic data has been processed identically. Functionally, the only critical difference has been the filtering applied to kinematic data. The filter cutoff frequency and filter type affect the estimates of joint angles made from processed kinematic data. All of the kinematic data used in this thesis has been low-pass filtered. Early data from prosthesis 33 was low-pass filtered using a Butterworth filter with a relatively high cut-off frequency (different depending on the day). Kinematic data taken for prosthesis 43 has all been filtered at 6 Hz using an FIR filter. The kinematic data low-pass filtered with a high cutoff frequency produced noisier estimates of joint angles; when used to calculate acetabular locations of transducers those kinematic data produced pressures applied over more extended areas of the acetabulum. In order to compare with data from prosthesis 43, the joint angle information from prosthesis 33 (first subject) was smoothed for data acquired in Dec. 1984, May 1985, and Oct. 1986. Kinematic data from prosthesis 33 from later dates had already been filtered with a sufficiently low cut-off frequency for use in comparisons. The smoothing routine used a generalized, cross-validatory spline smoothing algorithm. This routine was made available by Professor W. Durfee; the version used was written in January 4.5 4.5.1 1993. Transformation to Acetabular Coordinates Change in Coordinate Systems The stresses seen by the natural cartilage side of the joint are of primary interest since only that side experiences remodelling, adaptation and degradation. The kinematic data is crucial to the determination of where on the acetabulum measurements are made, since the kinematic data gives the relationship of the femur to the pelvis as 50 the subject moves. The process of transforming data from the prosthesis coordinate frame to one fixed in the acetabulum is thus a critical aspect of the processing. These coordinate transformations will be outlined here and are also explained in [8] and in Appendix E which contains the program that performs coordinate transformations. The process used assumes that only rotations matter, that no translations of the pelvis relative to the femoral head occur, an eminently reasonable assumption. For both the right and left hip axes X is anterior and Y superior, thus Z is lateral for a right hip and medial for a left hip. The transformation from the prosthesis coordinate frame to the acetabular coordinate frame requires three steps; one from the prosthesis to the reference frame fixed to the femur, one from the femur to the pelvis which is calculated from kinematic data, and one from the pelvis to the acetabular coordinate frame. The first and the last of these do not change; they are calculated once and used for the whole data set. Only the relationship between the femur and the pelvis requires kinematic data. To make the programs more easily understood, the transformation from prosthesis to femoral coordinates is described in several steps corresponding to information relating the coordinate systems. The first step is the specification of transducer locations in the prosthesis coordinate frame. The prosthesis coordinate frame is shown in figure 4-3 and is defined with the prosthesis z coordinate along the axis from the center of the femoral head to the center of transducer 1 (the central transducer). The prosthesis y direction is towards transducer 8. Prosthesis axis x is defined to point in an anterior direction, thus the prosthesis z coordinate is in opposite directions for a left and a right hip. Transducer locations in the prosthesis are shown in Appendix A which also contains the transducer locations in the prosthesis coordinate frame. The first transformation is to Ustem" coordinates, i, which only involves a rotation of as degrees from prosthesis coordinates, , as shown in Figure 4-4; a0o is 25° for both of the prostheses implanted thus far. The rotation matrix for this procedure is shown in equation 4.7. This rotation requires information on prosthesis design and on the subject's side in which it is implanted, R. R is 1.0 for a right hip and -1.0 for a left hip. 51 I Figure 4-3: Prosthesis Coordinate Frame 52 1 0 0 0 sin Cao -7jcosao O Rcos ao The next rotation is from U (4.7) sin a0 stem" to "femoral" coordinates. This rotation uses a set of angles which describe the placement of the prosthesis in the femur. The angles used are indicated in Figure 4-5. Angle al is the angle in the frontal plane between the stem y direction and the femoral y direction. Angle a 2 is defined inthe transverse plane and is the angle between the "stem" and "femoral" z directions. Angle a 3 is the angle between the stem and femoral z directions in the saggital plane. The values of these three angles were determined by the surgeon who performed the operation on both subjects and from x-rays. The rotation matrix which uses these angles to relate stem, 8, to femoral, 7, coordinates is shown in Equation 4.8. The array elements c[i][0] are calculated from the cross product of the c[i][1] and c[i][2] columns. R is 1.0 for a right hip and -1.0 for a left hip. Transducer locations are defined in femoral coordinates once, then stored for use through the whole data set. c[0][] =c[1][] c[2][0] -tanacr /1.O+(tan a )2 +(tan as) 2 *)2 70S+(a 1.0+(tana1)2+(tan R tan. a / loO-t-(t~nfal)2+( Rt tan 2 1/.0+(tno ) +(tan a2) +na 2 )2 (4.8) 1.0 taa )2 ,/1.0+(tana1)2+(tan02)2 The rotation from femoral to pelvis coordinates uses the kinematic data. The clinical joint angles; hip flexion, abduction, and external rotation are found using the Tupling and Pierrynowski formulation [23] as is also done at the MGH Biomotion lab. The method for calculating these angles is presented in the subroutine mghang.c in appendix E. Figure 4-6 shows the physical meaning of these angles. Equation 4.9 shows the rotation matrix used to relate femoral,7, and pelvis,h, coordinates using the clinical joint angles. Hip flexion is denoted by Y, external rotation by E, and abduction by A. X is 1.0 for a right hip and -1.0 for a left hip. 53 I / Figure 4-4: Prosthesis and Stem Coordinates 54 I I I S Figure 45: Stem to Femora Coordinates Figure 4-5: Stem to Femoral Coordinates 55 Q Z 2 0 b, C. I" .J 0 N ad .a 4 2 U I" n I \ N4 2 e Ii m .0.~~~L - -ft- J- 04 IW .la .CI oa - w J am Figure 4-6: Definition of clinical joint angles 56 coaccosa: = -cosAsinY -RainEcoasF cosCainY + aingainA cosAcosY 7&sinEcosA -&jinAco -Rain.FainC + ? cos8£JinA cosEcosA (4.9) The final transformation is from the pelvis coordinates to acetabular coordinates. The orthogonal acetabular coordinate system is shown in figure 4-7, in which the x direction is defined by the medial direction and z is defined by the acetabular outward normal. Two angles are used to describe the relationship of the pelvis, h, and acetabular, a, coordinate systems; angle a 4 is the angle in the transverse plane between the medial-lateral direction (global Z) and the acetabular outward normal, angle as is in the frontal plane between the medial-lateral direction and the acetabular outward normal. These angles are used to determine the rotation matrix shown in equation 4.10. The rotation matrix elements c[ll][i]are calculated by taking the cross product of the other two rows of the rotation matrix. COsa 4 = c[1][0] stan a l.O+(tan 4. )2+(tn a,)2 0.0 c[1][1] -7tan a 2 +(tn.,) 2 /.O+(ta.) -7.in a4 c[1][2] X (4.10) 1.0 /.0+(tana)2+(tana,)J The acetabular coordinates for each transducer are subsequently stored as a longitude and latitude (two numbers are sufficient as the radius of the sphere is constant). The Cartesian coordinates are recalculated from these numbers by the programs that require displays in orthogonal coordinates. 4.5.2 Timing Another issue in processing important to establishing acetabular pressure locations is the timing relationship between kinematic and pressure data. Since the two sets of data are collected by different computers, at different frequencies, and over different 57 Zk - -1.i0 -- r-7 <y oC- Figure 4-7: Relationship between Pelvis and Acetabular coordinates 58 lengths of time, a method for relating the two is needed in order to combine them. To achieve this a signal was output by the kinematic data acquisition system to the pressure data acquisition system via the auxiliary inputs. This synch signal goes low when kinematic data is being acquired thus it records the start and end of the kinematic data in the pressure data file. When pressure and kinematic data are being used together the one acquired at a lower frequency is used as is and the time for each frame of that data is calculated. The corresponding closest frame of the other type of data is calculated from the time and the known frequency of data acquisition. 4.6 Graphical Displays Several types of data were collected in conjunction with the in vivo pressure data, and there are a multitude of ways in which these data can be combined and presented. Some require little explanation, such as plots of pressure vs. time for each transducer, but when kinematic and pressure data is combined some thought must be given as to how to present information effectively. The results presented here will use: 1. Discrete measured values: Maximum values reported by pressure transducers, both normalized and not, for a test, a movement, or a day. 2. Time displays: Plots of pressure vs. time, forceplate forces vs. time, and clinical joint angles vs. time. 3. Global summary displays: Plots of maximum, minimum, or mean pressure measured in each region of the acetabulum over the course of a test or a set of tests. Figure 4-8 shows an example of plots of pressure measured at each transducer vs. time. This multi-plot type of display has been used a great deal for initial evaluation of each test session. In this particular format the data is from prosthesis 43 and the thermistor data is in the upper left-hand corner, followed by the two scaling channels, the compression level and the power level, then plots for the active transducers (all except number 4 for prosthesis 43). Additionally, plots of auxiliary data, such as goniometer or foot switch can be presented on the same page. Figure 4-9 is another 59 example of pressure vs. time plots, in this case the pressure at each transducer is normalized and all transducers are plotted on the same graph. This format is used in the Results section of this thesis. In Chapter 5, graphs of pressure data acquired from the first subject (prosthesis 33) present smoothed pressure data. The smoothing algorithm used was the same as that used to smooth joint angle data and uses a generalized cross-validatory spline smoothing algorithm. An example of a plot of clinical joint angles vs. time is shown in figure 4-10; in these plots the left-hand y axis is used for flexion and abduction, the right-hand y axis is used for external rotation. Kinematic data is not necessarily valid for the entire test session, as the subject may move out of view of one of the Selspot cameras. For the current subject a factor indicating whether the subject is in view or not is stored in the kinematic data files, thus only kinematic data acquired when the subject is in view of the cameras are used in processing and in displays. Kinematic data from earlier in this study did not have the same indicator, but clinical joint angles became +/- 90° when the subject was not in view. The data sets were clipped so that data when the subject was not in view were not used in smoothing or in subsequent processing. For this reason the time index in graphs does not always start at 0. Forceplate vertical force vs. time is shown in figure 4-11, the forceplate forces are normalized by body weight. In current procedure a weight estimate for the subject is included in the kinematic data files, stored from the early post-operative phase. Static stance data was examined to determine the weight of subject 2 on the test dates from which data is presented; these estimates were used in normalizing the pressure and forceplate data for subject 2. An attempt was made to apply the same process for subject 1. No similar static stance data was available, however, weight estimates from other sets of data indicated that the original estimate of her weight was nearly correct for all the days on which data is presented in this thesis. Calculation of the acetabular location of each pressure measurement frame enables the compilation of a set of basic statistics for each acetabular region over a given data set or a set of data sets. The values tabulated have been: regional maximum, regional minimum, regional mean, number of points measured in the region and RMS value for 60 -------- .i a ;A . W f f . II li 0 I 8ilil a X i !fj A I 0 1 .1 II I aI , El E~ a 0 Emd 0o I -1 II I 0 - i II A " am" . I I a 4........ I I i I44 ..444444.. .._....... ,.........: :....... .e .--· ·- t j i ......... t. . · .. .--.'""~ .---.---- ·o 0l '- ft Iq t t A I3 0 9 ii . __0 . .. I I i I I I i st 00 I .i....... , ... .. i 'a - .::, ::::. v.::...... 11............. 'V - f- 0 1 1 a it el .I I . 11 a : 0 I I I * 1r 11 . L 0 ?il I --i. ,i I i 0 . i " I I I ql t ql' _ * ",&v a O 0 . lodN ""= HIW Figure 4-8: Pressure vs. Time 61 I (r& SOMo 2 e I I 0 e v j ia .. . ..I ... :::::::;w O 1 i ., I · .. ... ... E O t I ......... I .IS i (· .-.... .... I .f . 3 I om Gamma _ Is i Ia : e w O IB II I~r ... .'. a 0 |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ §I I I I E~ r I I r. .1 8§ : (I b. I 9= - W . tod")o Dec. 14, 1992; Waliking in Place 120 BPM Normalized Presst ire: MPa/(wtht' * 1000.'* .0068948) caC MAN_ *VV9 = t a IN I Rm Ju Transi ?rL Trans3 Trans4 TransS Trans6 Trans7 20 Trans8 Trans9 Trans 0 Trans i Trans 12 10 Transl 3 0 0.0 I1.0 2.0 40 Figure 4-9: Normalized Pressure vs. Time 62 T3.0 Time (seconds) Prosthesis 43; Dec. 14, 1992; Test 10; Walking in Place 120 BPM 0 0) 20 20 '0 C 0 Or l 0) 0 1 ' C C 10 10 0 I .0 0 x0 E 0 0 E0 V hi 0 C C co C -10 *10 O1 0.0 .S 1.0 1.S 2.0 2.5 3.0 3.5 Figure 4-10: Joint Angles vs. Time 63 4.0 '¶le, . .5 seconds Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; Dec. 14, 1992; Test 10; Walking in Place 120 BPM fot A 100 i ,8 ' i ' I i' I i 9 I , - 3.1 -9 CE iI 'i II 'i I II'i i i 50 - I .9 i "r i r i 1 99 ,.I ! ! ,.9 i !,' !l !l 11 .9 0.0 I i I I i !g , ,1 I, I r~~~~~~~~ (I.9I \~~~~~~~~~~ III I I~~~~~~~~~~ I I ~~~~~~~~i ' iI 9, 99 99 l l~~~~~~ rI' ! ! i i 9*"'-:.9 ~-·-L 1.0 .1% I i..~., I li I i I 9 9 ,9 . .9 . - - - - 2.0 I .i .9? '- i i. I i I5I ~~~~~~~i 1 ., 3.0 Time (seconds) Figure 4-11: Forceplate forces vs. Time 64 Wii' I, I J I ! ii ;\ i i~, iiI I i Ii !l I i' ., I i' i 99 l i !I II i' i! h U I 9 .9.9 III !! 95 _.i! 99 95 I995 9 ..9~~~~ 9 9 9~~~~~~~ 9 9 ! I.. .9~~~ 9 5 9 0 Ii I i 9_Va 99 !k.9 I I I 95 ili I 25 i I i II II I il Ii 'i! I I II i/ '!9 i i; I i 9 i " i,, I I 9 i 75 ii ., 9 I ' fP2, I\ , , 4.0 the pressure. These tabulations permit the display of sets of data in a concise manner for comparison with other data and to determine whether high pressures were always measured in the same region. A display of maximum normalized regional pressures on the acetabular cartilage surface is shown in figure 4-12. This type of plot uses kinematic and pressure data, but does not explicitly present temporal information. The acetabular surface is sectioned into bins and the maximum, minimum, and mean pressure and the number of measurements made in each bin are recorded. Regions in which no measurements were made are left blank. The view of figure 4-12 is looking into the socket, with all data oriented for a right hip, and anterior toward the right side of the plot. In the presentation of similar results for movements such as rising from a chair and stair climbing, the acetabular surface has been rotated to show the regions of high pressure more clearly. Similar to figure 4-12, but without the kinematic information, is the plot shown in figure 4-13. In this case the maximum pressure measured at each transducer is displayed by a symbol at that tranducer's location in the prosthesis. The view is looking into the inner surface of the femoral ball hemisphere, with data again displayed as for a right hip. Since evaluation of the effect of prosthesis sizing on acetabular cartilage response is global in scope, displays of regional maximum pressures or normalized pressures have been used extensively in this thesis. The data sets presented in the Results section are accompanied by plots of the joint angles, forceplate forces, and normalized pressures vs. time, to convey a sense of the temporal course of the movement and to evaluate the similarity of the movement between trials and between subjects. 65 Suerior nAnterior Prosthesis 43 Dec. 14, 1992; Test 10; Walking in Place 120 BPM pmax 25 23.5 22 20.5 19 17.5 16 14.5 13 11.5 10 8.5 7 5.5 4 2.5 1 BW= 5E ialized Pressure: 30. Figure 4-12: Maximum Local Acetabular Pressures 66 MVIC Abduction Normalized Maximum pressures at each transducer pmax Is 29 25 21 17 13 9 5 Prosthesis 43: Dec. 10, 1991 Tests 2 and 3 1 Data displayed in Right hip orientation Maximum normalized pressure: 11.6 BW= 529 N Ht = 1.6 m Figure 4-13: Maximum Pressures displayed at Transducer Locaticns 67 68 Chapter 5 Results Of the huge volume collected, data from several types of movements will be presented in this chapter. These movements were chosen for different reasons: some reported the same activity over a number of different days, some resulted in especially high pressures, and others are activities frequently considered by other researchers. Data will be presented separately for each movement and each subject. The protocol for some movements been different for the two subjects, and in many cases the protocol changed over the years the first prosthesis was implanted. In general the results will be presented in a number of different formats; pressure vs. time, forceplate forces vs. time, joint angles vs. time, and regional statistics. Evaluation of the similarity of a movement performed on different days or by a different subject may be made in part by considering the joint angle plots and the forces recorded by the forceplates. The first subject received prosthesis number 33, the second received prosthesis 43. The prosthesis fitted to the first subject was 0.6 mm greater in diameter than her natural femoral head. The prosthesis implanted in the second subject was 0.7 mm smaller in diameter than his natural femoral head. 5.1 Gait The movement inspected at the greatest depth is walking. In virtually every test session with each subject (after the first post-operative week or so) data were taken 69 with the subject walking normally across the lab. There were minimal differences in the way these tests were performed over the course of time and between subjects, it is an activity performed routinely during the daily life of each subject, and it is an activity the results of which can be compared to those of other researchers. In all "unconstrained" tests the subject was instructed to walk as he or she normally would and to look ahead (rather than down at the ground). This gait data is labeled "free-speed" walking. Among the other types of gait data collected were walking tests with the pace set to some number of steps per minute using a metronome. These tests are labeled 60 beats per minute (BPM) walking, or 120 BPM, or 80 BPM, and are otherwise similar to the free-speed tests. 5.1.1 Free Speed Gait: Prosthesis 33 Figure 5-1 shows the magnitude of the local pressures at the joint during walking for the first subject for 6 months to 5 years post-operative. Data from all working transducers is shown, though not all record significant pressures. The pressures in this figure are normalized and smoothed. Figure 5-2 shows the corresponding forceplate forces during the same set of tests; the vertical force at the forceplate is shown and it is normalized by body weight. Usually the force on the instrumented leg is measured at forceplate 1 for this subject; however in the December 1984 data forceplate 2 was on the right. The joint angles for thz tests shown are presented in figure 5-3. Figure 5-4 presents the regional statistics for the same time period and the same tests, though when more than one test was available they were both used to compile regional statistics. Significant among this accumulated data are: the highest pressure during gait was measured 6 months post-operative, pressure at 11 months post-operative was nearly as high, then pressures decreased for the next 4 years; a change in the regions in which the maxiumum pressure was measured occurred between 6 months and 11 months post-op, and again between 2 years and 5 years post-operative. At 6 months post- up there are three regions in which relatively high pressures were measured, with the outer two of the three regions bearing higher stresses. Although no kinematic 70 data is available for the pressure data tlen in the early post-operative period, 4 transducers were measuring pressures on the order of 3 MPa at approximately the same times during the gait cycle, which would suggest that there were also 4 regions of relatively high pressure during gait in the first two weeks after implantation. In the 11 month post-operative data the same general region was more highly stressed than other areas, however higher pressures were measured in the more central area. This pattern is substantiated in the data from Oct. 1986, though the highest pressures have decreased in magnitude. By March 1989, however, the loading pattern has become even more diffuse, with pressures nearly as high as those measured centrally also being found in the outer regions of the acetabular surface. The acetabular cartilage had thinned by this time and the prosthesis was in the initial stages of protrusion, as is evidenced by load distribution. The subject was feeling discomfort during extended activity at this time. 71 Dc. ,. 1964; Ts ;2.FeeS eedO6I _ WIM3N _ ml Lr 2 1il-*,. 1, Nomme i Pmr 1 : MV1 , ' -v OllS Au. . .... was M$ Em.t Wme out w~a MI· "aMI) woo Vale MlO mlo Emil EMI =0- Mml$ EMIS Emis My 2.165:; Te 1l. FreeSped GM Mar. 17.19; Tos 16;FoIsSpeed Gm eASMM63N VW 63 N -_ IWN Im wai@ inll _ll Im Ol. 23. I; Tel 16;FreeSpeed lO NOma WI P5 MP*~wWI· 1 000.- m1 (lam) NNd3 6D 48) H iA .. - Mm ow ml11 mm -Immlwom) Figure 5-1: Pressures for subject 1: Free Speed Walking 72 m),, eisW Frowe Vml Fore N/ motd dbed WItOe Pm Mefd 33 Dec . I4, Ute 22.FIr Sed O( V_~ TNm o Oo b-bS I MVIWI F*I_ 33 De 22,1m. tOO1I.FPNSped tOI t :::- ._. -- -- , ,,I 'a II i ' I, ·I , la' II I I I I II I ,LI I t I i , r -- U a I ........ ON Fompe Pr/MlW ... I . . Is . ......... t0 Th (mnd) Veq~I Fes NNedd Paoee 33. cch 17, i .°_' , . . Io os FeqeS Vlm Fo.e Nwmbed by lo WuOgl 3 May 2.1 NI. Tel t, Ffr elSPd GM I' . *o on OO Tim (iema) lI byS'* WeaN t.trSaIt kF SoedOS I. ._.0 I ~ ~ ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ___ B 7S 1% I IAR III II dl - I I I go ::,',' ,, . NI at ' - o q m M "I " .':3"-. - o , ° . · ''-'' "- U a 0 0 oo 0 e Th" ({~) oJ F eol V3teW Feas NoM PF 33:Oct 22.1_. T t J othw Imo oI) I_}nb b 8o* WSVM - Iat la IS.Fre SpedO , 'S I os 2o A - - 'U' ,,, , __ I I 7t II I 4·~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1 I s I~~~~~~~~~~~~~~~~~~~ ~ I a ~ I ~ I I~~~~~~ I~~~~~~~~~~~~~~~~ a . --- . OJ -------- to0 i rThu pen - 20 --- 2. Figure 5-2: Forceplate data for subject 1: Free Speed Gait 73 Io .J P ov -s33 Dc (I 'OM *912. F Sw P owe 33. Dec 22. I. Tet 1. FteeSoeaGe Got m m 1 "I j' ,~~~~~· · · .:1 1 a a I 'i I St i 0A A 5 i m I i I It Ii 9 I I Ii f If ii I I aw :___ m. PMooWe433 May2 1tU Tlo 19.Ft"SedGOM 33. MIcn PeOs 17. 1: Teo Il. Fee Se GM Jg tel J I a a 0 I I I I ii S a %, ..... -~ ,'"''°-"o . ,.. o"° - .. i- ......... ". ........ .i id. ''°° J. I I Il Il OO I II I III ' ! I u * m.. TVn. aCn li I ---- t. I Z I l . el _ 'O1 .S _ - rue Ti Figure 5-3: Joint Angles for Subject 1: Free Speed Gait 74 iI J cco 5.1.2 Free Speed Gait: Prosthesis 43 Figure 5-5 shows the magnitude of the local pressures at the joint during walking for the second subject for 4 months to 1 year post-operative. Data from all working transducers are shown, though not all record significant pressures. The pressures in this figure are normalized. Figure 5-6 shows the corresponding forceplate forces during the same set of tests; the vertical force at the forceplate is shown and it is normalized by body weight. In general forceplate 2 corresponds to the instrumented leg for this subject. Figure 5-7 presents the regional statistics for the same time period and the same tests, though when more than one test was available they were both used to compile regional statistics. The joint angles for the tests shown are presented in figure 5-8. The maximum normalized pressures measured in the second subject during free speed walking rose between 4 months and 1 year post-operative. The regional maximums cover a similar range to that found in the first subject, with the normalized maximum pressures very similar for free-speed walking during the first year postoperative. In contrast to the first subject, however, in the second subject the regions in which higher pressures are measured have become more diffuse between 4 months and 1 year post-operative. No kinematic data is available coincident with the pres- sure data taken during the initial post-operative period, but the pressures for one set of gait data from December 1991, shown in fig 5-5, indicate that at that time only one transducer was registering significant pressures. In later data, the location of the higher pressure regions was very similar to that found in the first subject. 75 Prosthesis33 Dec. 6, 1984;FreeSpeedGait Tests22and 24 Prostheis 33 Dec.22, 1986;FreeSpeedGait Test 11 _ ml 16 IS 2 :1 as 5 13 2, t 21 III S I, Il ,. 10 IS 7 6S ,~ 4 ., 25 II BW=66 IIICAIIII1 .li"r 1 lil.. Pressre. !V||6U I. BW=66 2 "'"^"""" IMI.U.· &v/, flitrlI Preuclre 1 1 U" lC' lW"w """'W w 'WV Prosthesis33 March17,1989;FreeSpeedGait Test 16 Prosthesis33 May 2, 1985;FreeSpeedGait Test19 rU5 n 5 105 11 1·. 2S tS 1. I0 IS .1 4SS 2 7 1 11I(Dncrra ? BW=61 BW=6E CAIIIIU III IlU I FII I-alLI~u,U. . .," 7.I "" " " ~liTH " ' PrpcJrm' _. w Figure 5-4: Regional Maximums for Subject 1: Free Speed Gait 76 ".. .' z 15; 7 Prosthesis33 Dec. 22, 1986; FreeSpeedGait Tet 11 Prosthesis33 Dec.6, 1984; FreeSpeedGait Tests22 and24 P- 11 11 17J "I I" 141 la 10 U U P MiUallmum --IlormLIUU 9sr^0$Cr.L ,s~Dr ruruuru. IIYI- nllll 1 . -~Y~ I~ Prosthesis33 March17,1989;FreeSpeedGait Test 16 Prosthesis33 May 2, 1985;FreeSpeedGait Test 19 0- Ir a 11j 111 141 10 Is Is 111 SI aNJ DU Us no7-Dazlr-O SW-st dFnlUm IUmIIlMU lN r lRI:rU. co.( Imum IrIUFkIMdU rrur. Figure 5-4: Regional Maximums for Subject 1; Free Speed Gait 76A I.1 76B Dec. 13, 1991; Galt early post-op Normalized Pressure: MPa/(wht 2I 1000. * .0068948) BW. 529 N Ht. 1 A m Trnal Trns2 Trnn*3 Trmns4 Trans5 Trmns6 Tnns? 1is Trns Tran9 10 Trans10 Trans 1 Transl2 Trans13 00 2. 0so April 14, 1992; Free Speed Gait; Test 22 Time (seconds) BW- 578 N Tnns1 Normal Trn2 Trsns3 Trns4 20 Tnns5 Trans8 Tn7 10 Trans8 rrans9 rrans10 Trans1 Trans12 rmns13 10 Dec. 14, 1992; Free Speed Gait Test 8 Normalized Pressure: MPa/(wt/ht2 BW= 565 N 1000. ' .0068948) Trinsl Trns2 Trns3 Ht= 1.6 m Trans4 Trane5 20 Trns Tnns7 Is Trans TranO Tnra10 Trnsl 1 Tnrns12 Tmns13 10 5 0 rime (seconds) Figure 5-5: Pressures in the Hip Joint: Free Speed Walking 77 Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; April 14, 1992; Test 22; Free speed Gait yPlt t I' /, I I I 75 I I , I I I I I ,I I I I I I I I i: .Z@e ~D I 50 I I I I Ir \ r r ; 25 II I II I I / · - , /I I / l '~~~~~~~~~~~~~~~~~~ 0 2.0 2.5 Time (seconds) Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; Dec. 14, 1992; Test 8; Free Speed Gait I \ - / I / / 100 /' - - ....... - yp2 yPl Y4~. %. I i 75 I J: 50 / / I II I I ;.* 25 ~~~~Ii I'..." T--'.'·. 0 -- 1.0 - - 1.5 Time (seconds) 2.0 Figure 5-6: Forceplate data for subject 2: Free Speed Gait 78 Prosthesis 43 April 14, 1992: Free Speed Gait Tests 22 and 23 pmu 25 235 22 205 175 Is 1t45 115 10 Is 55 4 25 BW= 5, alized Pressure. 22.8 Prosthesis 43 Dec. 14, 1992; Free Speed Gait Tests 7 and 8 pmax 25 235 22 205 19 175 16 145 13 10 85 7 55 4 25 BW= 51 alized Pressure: 24.5 Figure 5-7: Regional Maximums for Subject 2: Free Speed Gait 79 Prosthesis 43; April 14, 1992; Test 22; Free Speed Gait -- 0 eA 50 Du flex 4) D ------ abd ........... extr0 aC 0 c0 'O 25 0 25 _ ) .0 o 0r- - -- - -- - - - - 0) CO C tO - 0 .' 0) a Ct c ._o -25 ~I I _ ! I I I i iJ 2.0 2.5 -25 Time, seconds Prosthesis 43; Dec. 14, 1992; Test 8; Free Speed Gait en 50 25 0 0) Cu a) 'O C 0 0) C c 0 o 25 25 .0 O 0 aC O o- ) 0 bi C 0 .0 O -3 co -25 -25 1.0 1.5 2 Time, seconds Figure 5-8: Joint Angles for Subject 2: Free Speed Gait 80 Prosthesis43 Dec.14,1992;FreeSpeedGait Tests 7and 8 Prosthesis 43 April 14,1992;FreeSpeedGait Tests22 and 23 P- Wr a I" 18 "Is 14 11 16 1t Is 10 10 st Zi SW- 5 alizedPressure:22.8 Pressure: 4alized SW- 5 24.5 nalized Pressure:24.5 Figure 5-7 Regional Maximums for Subject 2; Free Speed Gait Prosthesis 33 March17, 1989;PacedGait120 BPM Test 17 P- a 2U a "1 17. 11 lii 10 a 1o saiarel 4 - r 1S U asw m~Aii-lll I-lIlLU r-Iou I . Figure 5-12; Regional Maximums for Subject 1; Walking at 120 BPM 80A 80B 5.1.3 Paced Gait: Prosthesis 33 Very few gait tests were done at specified paces for prosthesis 33. The data reported here is all from late in the implantation period. Figure 5-9 shows the local pressure magnitude in the joint during walking at 120 beats per minute (BPM). The pressures in this figure are normalized and smoothed. Figure 5-10 shows the corresponding forceplate forces during the same test ; the vertical force at the forceplate is shown and it is normalized by body weight. The force on the instrumented leg is measured at forceplate 1 for this subject. The joint angles for the test shown are presented in figure 5-11. Figure 5-15 presents the regional statistics for the same test. The magnitude of the maximum normalized pressure for this activity was very similar to free speed walking. The only data for this movement was taken late in the implantation period, by which time the regions of high pressure had become more diffuse. Figure 5-12 shows the local pressure magnitude in the joint during walking at 80 beats per minute (BPM). The pressures in this figure are normalized and smoothed. Figure 5-13 shows the corresponding forceplate forces during the same test; the vertical force at the forceplate is shown and it is normalized by body weight. The force on the instrumented leg is measured at forceplate 1 for this subject. The joint angles for the test shown are presented in figure 5-14. Figure 5-16 presents the regional statistics for the same test. The results from this test are very similar to both free speed walking and 120 BPM gait for the day on which 80 BPM gait was taken. However, this data was taken late in the implantation period. 81 Mar. 17, 1989; Test 17; 120 BPM Gait Normalized Pressure: MPa(wtht· *1 BW= 663 N Wt- ~q m 1000. .0068948) I - .- ... trallr 25 tnm~ 20 _ Utn7 buns -- IIS I I I10 r\ \ \ I, ii I II Z IrolO1 \ h\ \ \i \\ 5 r-, CI \ ,i, Z, /I,Zr \ .t _---- r 2\ t 'ir I 5· Ibww3 C *' -·-·IY L. · I\ I I V I\ I 0 P\ \? 0.00 b11 \ \ r \ 025 · L 050 '*. 0.75 1.00 \ r , \ \ .·S'I r I Ir.· 125 1.50 1.75 -Time (seconds) Figure 5-9: Pressures for su .ect 1: Walking at 120 BPM 82 - Forceplate Vertical Force Normalized by Body Weight Prosthesis 33; Mar. 17, 1989; Test 17; Walking at 120 BPM - , 100 - I- - - y lI ........ yp2 I ~I~~ 75 v M ji~~~~~~~ 10 50 I. I r 25 0 ._L _ 0.5 __ __ .I. C 1.0 1.5 . I 2.0 Time (seconds) Figure 5-10: Forceplate data for subject 1: Walking at 120 BPM 83 Prosthesis 33; March 17, 1989; Test 17 Po II I 50 C C 50 iaK o E C 31 C e i 2 . cNED { 0 C i afo ffi II ,.,~ a -5_ 05 1.0 1.5 Time, seconds Figure 5-11: Joint Angles for Subject 1: Walking at 120 BPM 84 Mar. 17, 1989; Test 20; Paced Gait 00 BPM Normalized Pressure: MPa/(wt/ht 2 BW= 663 N 1000. .0068948) t W1 Ht= 1.68 m - r,,24 25 20 5 ,-- .- 0 / ~ ,-... 5 '-....' ii _. , - . I ~.~ .. 0.0 I ;d.... .,___// 0 - ---- - - bI4 arslO0 mrl ---- b"l2 %' ~'~, '~?,~ /" i'/ ' I .. /', ID - - '-"~~~~~~~~~~~ I¢ 1.0 15 l " ? ~- '~,-----2.0 2 _. - Time (seconds) Figure 5-12: Pressures for subject 1: Walking at 80 BPM 85 Forceplate Vertical Force Normalized by Body Weight Prosthesis 33; March 17, 1989; Test 20; Walking at 80 BPM I I I I I I I I I 100 75 '. j II I II .0 co I2 y pl - \ I--1 . .... y 50 I I I I /\ 25 . ~~~~~~~~I; r r 1~~~~~~~ I.I -, i I 0 _- - -- 0.5 - - - - . 1.0 1.5 Time (seconds) 2.0 2.5 Figure 5-13: Forceplate data for subject 1: Walking at 80 BPM 86 Prosthesis 33; Mar. 17, 1989; Test 20 . 50 SC c( E Ca 0 I C 25 Co 0 .2 25 0c0Ca .5 -25 .25 0.5 1.0 1.5 2.0 2S Time, seconds Time, seconds Figure 5-14: Joint Angles for Subject 1: Walking at 80 BPM 87 Prosthesis 33 March 17,1989; Paced Gait 120 BPM Test 17 pmax 25 235 22 20 5 19 175 16 145 13 115 10 85 7 55 4 25 1 BW=6 IVIGXll UIII ali irl 7 'IVIIIIC El lllU I rn I1I K J.r racl IUII Figure 5-15: Regional Maximums for Subject 1: Walking at 120 BPM Prosthesis 33 March 17, 1989; Test 20 Paced Gait 60 BPM pmax 25 235 22 205 19 175 16 145 13 115 10 85 7 55 4 25 t BW=66 IVlaAll I IUI I I IUII -l1;-~1 IICIICU r,-e-l, ;3 Ul. r I 1I. J -1 I Figure 5-16: Regional Maximums for Subject 1: Walking at 80 BPM 88 Prosthesis 43 Dec.14, 1992;Gait Pacedat 120BPM Test g Prosthesis 43 April14,1992;GaitPacedat 120BPM Tests24 and25 rm a n 1I3 t r1S .l 'rd 'ItJl 'Is '0 U Sr U Pressre:21.2 Jaled BW-i BW-S nalizedPressure: 21.2 lizedPressure: 29.9 Figure 5-20: Regional Maximums for Subject 2; Walking at 120 BPM Prosthesis33 March17.1989:PacedGait80 BPM Test 20 a a B1 'S Is 14 I'Ii 'S is I IlIIU u III ll rnli~as Illfll FI PDllrs IrWIIA ul:., 1. I.I* 1 Figure 5-16: Regional Maximums for Subject 1; Walking at 80 BPM 884 88B 5.1.4 Paced Gait: Prosthesis 43 In contrast to the data from prosthesis 33, a metronome has been used frequently during data acquisition sessions with the second subject. However, the data is much earlier post-operative than is the paced gait data from the first subject and only reports the first year post-implantation. Figure 5-17 shows the local pressure mag- nitude in the joint during walking at 120 beats per minute (BPM). The pressures in this figure are normalized. Figure 5-18 shows the corresponding forceplate forces during the same set of tests; the vertical force at the forceplate is shown and it is normalized by body weight. The force on the instrumented leg is measured at forceplate 2 for this subject. The joint ai. les for the tests shown are presented in figure 5-19. Figure 5-20 presents the regional statistics for the same tests, when more than one test was available they were all used to compile regional statistics. Higher pressures were measured during 120 BPM gait than during free speed gait for this subject, at a year post-operative. (At 4 months they were essentially the same.) The regions in which the highest pressures were measured are slightly different in that they are more localized for 120 BPM gait than for free speed gait. Figure 5-21 shows the local pressure magnitude in the joint during walking at 60 beats per minute (BPM). The pressures in this figure are normalized. Figure 5-22 shows the corresponding forceplate forces during the same tests; the vertical force at the forceplate is shown and it is normalized by body weight. The force on the instrumented leg is measured at forceplate 2 for this subject. The joint angles for the tests shown are presented in figure 5-23. Figure 5-24 presents the regional statistics for the same tests. Higher pressures were measured during 60 BPM gait than during free speed gait for both days presented here. Pressures were also higher than those measured for 120 BPM gait on the same days. Although not presented here, the same trends in pressure were observed in data taken at 15 months post-operative. Data from a year post-operative is striking in how well-defined the area over which high pressures were measured. 89 April 14, 1992; Gait at 120 BPM; Test 25 Normalized Pressure: MPa/(wt/ht BW= 578 N 1000. * .0068948) Transl Trans2 Trans3 Trans4 Trans5 Trans6 Trans7 Trans8 Trans9 TranslO Trans11 Trans12 Trans13 It- I Am 20 15 10 5 0 1.50 1.75 2.25 2.00 2.50 3.00 2.75 Dec. 14, 1992; Gait Paced at 120 BPM; Test 9 i 5e (seconds) Tife (seconds) BW= 565 N Normalized Pressure: MPa/(wt/ht2 * 1000. * .0068948) - -- LW- I A m 25 .. .. . . 20 ... . .. 15 10 Transl Trmns2 Trans3 Trans4 Trans5 Trans6 Trans7 Trans8 Trans9 TranslO Trans1 Trans12 Trans13 5 0 0.75 1.00 125 .50 1.5 2e (econds) Figure 5-17: Pressures for subject 2: Walking at 12i BPM 90 Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; April 14, 1992; Test 25; Gait 120 BPM .11% 100 I '. , I . II \ I I 75 E I .LM -...... i i i I i i i i i i i i i i I I I co mO 50 yp2 II i I 25 I % _ 0 -- lr .·_-- ---- --P· -- -L- 1.5 · , I ._(_· ·-· I·- · C-·- ' 2.5 2,0 -·-·- 3.0 Time (seconds) Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; Dec. 14, 1992; Test 9; Gait 120 BPM 100 . YP - _.---- - yp2 i I I I- I i 75 I Z .0 I , I,1 / 50 / t3~ I 3= I I I il I II i i / I I k k I i I i /I 25 I , ,I,~~~~ i I 0 i' · -· 1.0 I -- I 1-- 1.5 Time (seconds) ;1211 C -- · -I--- -·--- 2.0 Figure 5-18: Forceplate data for subject 2: Walking at 120 BPM 91 Prosthesis 43; April 14, 1992; Test 25; Gait Paced 120 BPM co 50 _ tZ *U a, a) a0 cm a, 0) C C C C .O a) 'a 0 CO {3 25 25 co 'a c. I.-.- " 0 o a, C-D 0) c -25 -3 -25 -25 1.5 2.0 2.5 3.0 Time, seconds Prosthesis 43; Dec. 14, 1992; Test 9; Gait Paced at 120 BPM 50 50 a, 0) a, cO a3 O 0 25 25 .C C .O O .0 o E a, 0 0 0 oO O .5 -3 o~ -3 0 -25 -25 1.5 1.0 ime, seconds Figure 5-19: Joint Angles for Subject 2: Walking at 120 BPM 92 Prosthesis 43 April 14, 1992; Gait Paced at 120 BPM Tests 24 and 25 pmax 25 23.5 22 20 5 19 175 16 14.5 13 115 10 85 7 5.5 4 2.5 1 BW= 57 lalized Pressure: 21.2 Prosthesis 43 Dec. 14, 1992; Gait Paced at 120 BPM Test 9 pmax 25 23 5 22 205 19 17.5 16 145 13 115 10 8.5 7 55 4 25 1 BW= 565 lized Pressure: 29.9 Figure 5-20: Regional Maximums for Subject 2: Walking at 120 BPM 93 April 14, 1992; Gait Paced at 60 BPM; Test 27 BW= 578 N Trans3 Trans4 Trans5 20 Trans6 Trans7 ~~~~15~~ Trans8 · ----- Tra ns11 Dec. 14, 1992; Test 11;MPa/(w Gait Paced at 60 BPMBW Pressure: -Normalized1000..008948) 2.50 2.75 Trans9 Trans10 ' j ;~X o_|-- 3.00 ~ NTrans1 325 35 ime (seconds) Dec. 14, 1992; Test 11; Gait Paced at 60 BPM Normalized Pressure: MPa/(wt/ht= 1000. .0068948) Ht= I R m .-.Trans2 . ......... Trans3 Trans4 Trans5 Trans6 30 25 .---.. 20 --- - Trans9 Trans7 Trans8 ------ TranslO Trans 1 15 ---- Trans12 Trans13 10 5 0 2.5 3.5 3.0 4.0 Time (seconds) Figure 5-21: Pressures for subject 2: Walking at 60 BPM 94 Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; April 14, 1992; Test 27; Gait Paced at 60 BPM --- . ,. / I 75 02 0 \ ' . yp2 , . / I . i ,1 50 m 25 - i i iI I , ,/ = , I, _ _ _ _ L. , _ . _ -- ------ 0 2.5 3.0 Time (seconds) 3.5 Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; Dec. 14, 1992; Test 11; Gait Paced at 60 BPM 100 _ /.' I ' ~-.' .... I 75 0) I V 0 I 50 0- t I I\ \ i I I I I I I I I I I 25 , -,·l·=-'·l·;P.,,/)-tr\s·' '-'2.5 i i I i/I I I 0 ii \ ; I ,, ' --- -~-'-L'·--'-·~- 3.0 . 3.5 Time (seconds) \ I . . ·. . . . .· 4.0 Figure 5-22: Forceplate data for subject 2: Walking at 60 BPM 95 Prosthesis 43; April 14, 1992; Gait Paced at 60 BPM; Test 27 so a) cm ...... - flex abd .----- extro 50so u) a) a) (3 0 25 25 a, .0 C eCo C E o-- x 0 a) _4 0 a -25 -25 25 3.0 3.5Time, seconds Prosthesis 43; Dec. 14, 1992; Gait Paced at 60 BPM; Test 11 0U) ', so 50 .,C a (0 Cn 0a) a, aO 25 25 0 2 aa .Q a _o _) 0 0 03 a 0 CE -25 -25 2.5 3.5 3.0 4.0 Time, seconds Figure 5-23: Joint Angles for Subject 2: Walking at 60 BPM 96 Prosthesis 43 April 14, 1992; Gait Paced at 60 BPM Test 27 pmax 25 23.5 22 20.5 19 175 16 14.5 13 115 10 85 7 55 4 25 1 BW= 578 N lized Pressure: 23.6 Prosthesis 43 Dec. 14, 1992; Gait Paced at60 BPM Test 11 pmax '5 23 5 22 205 19 175 16 145 13 115 10 85 7 55 4 25 1 BW= 565 h lized Pressure: 34.2 Figure 5-24: Regional Maximums for Subject 2: Walking at 60 BPM 97 5.2 Rising from a Chair The motion of rising from a chair produced the highest pressure measurement recorded from the first subject, at 11 months post-operative. Following that measurement more attention was paid to this movement, and numerous tests were done, including a series with different height chairs. [9] Accordingly a number of tests have been done with the second subject rising from a seated position, however for this subject the maximum pressures recorded during this movement are much lower. 5.2.1 Prosthesis 33 The manner in which this movement was carried out by the first subject varied over the implantation period. Early on data was taken with the subject rising from an actual chair - sometimes a different chair than the one used the previous time data was taken. Eventually a set of blocks was built which could be arranged into different height seats or into a set of stairs, to standardize these test conditions. In general the instruction to the subject was to cross her arms in front of her body during the movement. Figure 5-25 shows the local pressure magnitude in the joint during rising from a chair. The pressures in this figure are normalized and smoothed. Figure 5-26 shows the corresponding forceplate forces during the same tests; the vertical force at the forceplate is shown and it is normalized by body weight. In general the force on the instrumented leg is measured at forceplate 1 for this subject. The positioning of the chair or blocks relative to the forceplate evolved, so that during some tests only one foot was on a forceplate while during other tests one foot was on each forceplate. Also, the subject's feet may not have been entirely on the forceplates during some tests, this appears to be the case in Oct. 1986. The joint angles for the tests shown are presented in figure 5-27. These plots indicate differences in chair height, as the hip flexion angle ranged from 65 to 80 degrees for the tests shown. Figure 5-28 presents the regional statistics for the same tests. Whatever the possible effect of chair height variation on the pressures, the maxi98 Prosthesis43 April 14,1992;Gait Pacedat60 6PM Test 27 Prosthesis43 Dec.14,1992;GaitPacedat 60 BPM Test 11 pmlx 2.. 23 20 2S 17 14. 13 11 10 18 13 11l 225 z55~W-S ized Pressure: 23.6 ized Pressure: 23.6 Pressure:34.2 Figure 5-24: Regional Maximums for Subject 2; Walking at 60 BPM Prosthesis 43 Dec.14,1992;Risingfroma Chair Tests18 and19 25 2t 22 20 19 142 lI 10 lalized Pressure:22.7 Figure 5-32: Regional Maximums for Subject 2; Rising from a Chair 98A 98B mum pressures measured in May 1985 were more than double those measured during this movement in 1986. Although not all of the data has been presented here, pressure measurements during rising from a chair in August 1985 were nearly as high as those made in May 1985. In all tests it is clear that this subject initiated the movement by bringing her upper body forward (the flexion angle increases significantly) prior to rising. The time at which the maximum pressure occurred varies relative to the timing of the movement. For instance, in Dec. 1984 the maximum pressure was measured after the maximum flexion angle, while in May 1985 and Oct. and Dec. 1986 the maximum pressure was nearly coincident with the maximum flexion angle. The regions of highest pressure were located posterior on the acetabulum in all cases. 99 Dc 13.191. Toa 13. RaN tm a Cr SW. 663 N Oc 23. 196 Wm Ta 2. RGa Im 1nm a Char MUg1w' S N&oWAtmP' BW. 663 N HI IR m 1000 ' 00M4) . .. I.·I I I _,O -11 -12 .- I I =111( =111) 7 -- ------ --- --- --- May2 1 Nomfnaiz S. ToT Z3. PAmgfr Pmur C MP&nAI ' 0oo ' .00e) w.663N . m - - Dec 2. 1. Tl mnalmd Pimia. 27: Png a MP#4,M mre (S6ola) 63 N · I0. -r .II *.6648) Fk1 . m Tmt 1mm Tw --- ." _1 .mm --- mml., -_mm --- m-m rm Tm -/ mm r.n T,1 .-- - tlC .TS T ( to - m 1i .is mIs1 an ) Si ii * J 1.5 Figure 5-25: Pressures for subject 1: Rising from a chair 100 ?eft i T* w cTna a 3 -* Forplte Prhosli ForaepiaeVwcl ForteNomtbed byBodyWeight Prodr. so 33, Doc. 6194, Tet13.R Fsgtnmacha ---- Vmt-l Foet Nomuizetd by Body Weiht 33. Oct. 23. tg, Tt 22: PqaFwtm a char ----- I .... 1e 0~ ! 40 I , L- 30 s5 I CY-, -20 :1 i 10 : I·II' I' 0 aSfie rlwb 0.5 0.0 Focrg t PodF. 1b re ) nv C i^-r---S· 1.5 2.0 2.5 Vtcl Force Noimfle d by Body Wet t,, 33. Mry 2. 1985. Tet 23, Rng tmon cslr --- -- i.. . 1.5 2.0 i .... 0.5 1.o Tkh (mcond) 25 Foacepte Vetorl Force Noar tedby Body Wgt Proldis 33, Dec 22. 186, Tot 27, RFPsgfrom Chair - .I' 75 50 40 so I~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I , I I 30 25 :1. 10 0 '----------____..S - , , _~~~~~~~~~~~ .. _ - ........ 0.0 0.5 10 15 Tow (seconds) _ ....... 2.0 a 2.5 0.0 ..... 0. I 1.0 . 15 TnM ( ' , l I I 2.0 Iconds) Figure 5-26: Forceplate data for subject 1: Rising from a chair 101 2.5 Data was taken for rising from different height chairs, this is presented and discussed in [9]. The results essentially are that higher local pressures are measured the lower the chair height. 5.2.2 Prosthesis 43 For this subject greater uniformity has been imposed in the manner in which this rising from a chair test has been conducted, although there are fewer days for which kinematic data is available. The standard test is rising from a seated position without pacing, with the seat at 100% of knee height. Tests have also been done in which the seat height was changed to 150% of knee heightLand 80% of knee height. The subject puts his hands on his thighs at the start of the test. Figure 5-29 shows the local pressure magnitude in the joint during rising from a seat at 100% knee height without pacing. The pressures in this figure are normalized. Figure 5-30 shows the corresponding forceplate forces during the same tests; the vertical force at the forceplate is shown and it is normalized by body weight. The force on the instrumented leg is measured at forceplate 2 for this subject. The joint angles for the tests shown are presented in figure 5-31. Figure 5-32 presents the regional statistics for the same tests. In a number of respects this data is similar to that from the first subject; the chair height is similar as shown by a starting flexion angle of about 74 degrees, the subject also initiates this movement by bringing his upper body forward, and the point in the movement at which the maximum pressure is measured is similar to the results for the first subject at 6 months post-operative. However, the maximum pressures measured were much lower for the second subject and positioned more anterior than the high stresses measured for the first subject. 102 Prosthess 33. Dec 6, 1984,Teat 13, Rising from a Chair Prostiss 33: Oct 23, 1986. Te 22 I I I I 5 G 3 i a a lb i B { Proaitea 33. Dec.22. 1986,Test27, Rung froma Chair Prosthesis 33. May2, 1985, Test 23. Rising form a Char I S [ i .{ 9 I f, I i I Il ~I m I I lb A. Time.seconds Figure 5-27: Joint Angles for Subject 1: Rising from a chair 103 I rme.3a6xl Superior ¥ Prosthesis 33 Oct.23, 1986;Risingfroma Chair Tests21 and22 Prosthesis33 Dec.6,1984; Risingfroma Chair Test13 Anterior p 27 25 29 23 23 17 21 IS II 11 ei S 3 1 r5 1P alized Pressure: 32.6 BW--663 N HI= 1 68 m 34.1 MaxirrhumNormalizedPressure: Prosthesis 33 Dec.22,1986;Risingfroma Chair Tests26 and27 Prosthesis 33 May2, 1985;Risingfroma Chair Tests22 and23 27 29 21 a1 12 I? i1 17 II 1S 13 11 I ,111· I wV n,-li,,r *Ill-fIV Pre,cre* ' v-_ G. 76V.L 0 |UIII nli- IVII**all^GV Pr-E.l-rC * *G~UIG. Figure 5-28: Regional Maximums for Subject 1: Rising from a chair 104 34 V·.V Prosthesis33 Oct.23, 19886; Risingfroma Chair Test 22 Prosthesis33 Dec.6, 1984;Risingfroma Chair Test 13 plu P.t 2M a 2? 27 22 21 1D 11t I: 11 1 a 1 I·IM wlU III l mli;,-A (~ILv II I Praeurne Q) R rl.WI MaxlmumNorrrltzeo rressure; 4.I JL.u.ul Prosthesis33 Dec.22, 19886; Risingfroma Chair Tests26 and27 Prosthesis33 May2, 1985;Risingfroma Chair Tests22 and23 s 27 17 n 21 15 15 13 11 11 1 II MIICIIIIUmf IurlU UU rrRUre Ia ," I. ICII~UIIII IIUIIl1CIU -- im,,D I pa ,l.r · QA -lIU0IIW .o Figure 5-28: Regional Maximums for Subject 1; Rising from a Chair 1 04A 104B Dec. 14. 1992; Test 18; Rising from a Chair Normalized Pressure: MPa(wVht2 ' 1000. .0068948) BW= 565 N It- t m Trans -,..,-,-, .-- --- Trans3 Trans4 TransS 20 ---- Tronv .- -- Trans? ----- Trmns TransS --- Trans Trans1l Trsns13 5 oo os 00 o 0 II1~0 1.5 ~5 s 20 20 2.5 2Z ~Time (seconds) Figure 5-29: Pressures for subject 2: Rising from a chair 105 Forceplate Vertical Force Normalized by Body Weight Prosthesis43; Dec. 14, 1992; Test 18; Rising from a chair - YR1 ... yp2 I / I I 60 - -- , \ I - II i li I , k\ ! \. Io 50 3'" >, I I II III I .0 Z \ ,, '!'!'! 40 o8 , ' . \ \ a i I , I I! 30 I 20 II \, -\ , 10 .. 0.0 . . . I 0.5 . I. -.- :,,,.. . .... - 1.0 - 1.5 Time (seconds) I 2.0 2.5 Figure 5-30: Forceplate data for subject 2: Rising from a chair 106 Prosthesis43;Dec.14, 1992;Test 18;Risingfroma Chair 5 ._ 2o C 0 s co ES QR 4M -me, seconds Figure 5-31: Joint Angles for Subject 2: Rising from a chair 107 Superior Prosthesis 43 Dec. 14, 1992; Rising from a Chair Tests 18 and 19 Anterior pmax 25 23.5 22 205 19 175 16 145 13 11.5 10 8.5 7 55 4 25 1 lalized Pressure: 22.7 BW= 565 1 Figure 5-32: Regional Maximums for Subject 2: Rising from a chair 108 5.3 Stairs Climbing and descending stairs are also movements performed frequently in daily life which were found to generate locally high pressures for the first subject. Thus far these tests have resulted in higher local pressures for the second subject than for the first, both with and without normalization. The pressures measured in the second subject during stair climbing and descending have also been higher than those found in rising from a chair for this subject. The second subject has expressed difficulty in maintaining his balance, this may contribute to the higher pressure measurements during stair climbing and descending, as the subject may be co-contracting massively. For the second subject descending stairs resulted in higher pressure measurements than did ascending stairs. 5.3.1 Prosthesis 33 The protocol for this movement varied over the implantation period, early on there was only one step, 9" high, later a set of blocks that could be arranged into a set of stairs with 3 steps was built. No armrails were provided during any test. Results for both ascending and descending stairs are presented. Figure 5-33 shows the local pressure magnitude in the joint during ascending stairs. The pressures in this figure are normalized and smoothed. Figure 5-34 shows the corresponding forceplate forces during the same tests; the vertical force at the forceplate is shown and it is normalized by body weight. However, the steps used were not always the same and were not always placed on the forceplates in the same manner. For instance in May 1985 the only step was on forceplate 1. By Dec. 1986 a set of stairs had been constructed and the two forceplate measurements were independant. The joint angles for the tests shown are presented in figure 5-35. Figure 5-36 presents the regional statistics for the same tests. The pressure vs. time data for climbing stairs is quite complex and confusing, for both this subject and the second subject. The maximum pressure was generally measured during the initial loading of the foot during each step for this subject. The 109 regions in which the highest pressures were measured were more anterior than for rising from a chair, but more posterior than in normal gait. Figure 5-37 shows the local pressure magnitude in the joint during descending stairs. The pressures in this figure are normalized and smoothed. Figure 5-38 shows the corresponding forceplate forces during the same tests; the vertical force at the forceplate is shown and it is normalized by body weight. The force on the instrumented leg is measured at forceplate 2 for this subject on this date. The joint angles for the tests shown are presented in figure 5-39. Figure 5-40 presents the regional statistics for the same tests. The pressures measured during this movement were not as high as in climbing stairs for this subject and, despite occuring during a period of high hip flexion, were more anterior on the acetabulum than for climbing stairs, suggesting that muscle action influences area of acetabular loading. 5.3.2 Prosthesis 43 This subject has always used the same set of stairs - three steps each 9" high. The stairs have been turned around for descending stairs, so that forceplate 2 always registers force from the instrumented leg. Data has been taken for both paced (at 80 BPM) and unpaced stair-climbing. No hand rails are used. Figure 5-41 shows the local pressure magnitude in the joint during stair climbing with and without pacing. The pressures in this figure are normalized. Figure 5-42 shows the corresponding forceplate forces during the same tests; the vertical force at the forceplate is shown and it is normalized by body weight. The joint angles for the tests shown are presented in figure 5-43. Figure 5-44 presents the regional statistics for the same tests. Climbing and descending stairs have resulted in the highest recorded pressures from this subject, except for tests in which he jumps off a step. High pressures have been recorded at just about all points in the gait cycle during stair climbing, though the highest pressures appear just as the leg is being raised for the next step. Regions of high stress are located both posterior and superior in the acetabulum. This 110 Dec.6, 984. Tro 1s. OamngStm NormazedPru: MPm(wt 1000 o. 0oe948) p1 Iv," a -. , i 1 I ' ,'I BW- 3 N Ht 1.68 m _ Dec.22. 196;:Tea13:CMng Sits RW. - . ', ".,W _ . --- T.W _.m 'rll "m'm ,rlo IIM0 -I 9"12 ."13 I [ Ta12 'sXl ,·r)1 ··... 2 '.'" · r' 00 01 ··I O r( 10 IfflS iy 2. 196S.TM 21:Cmbisg Stan NomnaizaO Pwww. UPI(*W'' 100.* .00946) Co ____,. as 5o *a a iUwUJ W-663N H t. m - -Is I*- I ms ." W. i ~ S .__ ml tW 1113 .8"., < · `· L-- , Sr,-; t.' A, ,"''' * L _,,w~~s,_ r __ 00 a 05 , , . , L Tm (saolns) Figure 5-33: Pressures for subject 1: Ascending Stairs 111 2 s T eo nds ForceplateVertcalForceNormalized byBodyWeight Prosthes s 33;Dec.6, 1984;Teot15;ClImbing Stairs --- - ypel _ ,,'' I r 75 s I II 50 __ I I · _, I 25 II, I - /I '.11-.:, 0 00 I , 11 - ...... 10 0.5 . 15 I'I.-~~, I I 25 2.0 Time(seconds) ForceplateVerbcalForceNormalized byBodyWeight Prosthess33;May2, 1985;Test21; ClimbrngStairs I 100 " I I - - - -- -__ yIPI P2 - ,- . I 75 I t i 25 0 00 ....... - 05 '.- ·....... 10 ' 15 - 'r I 20 rime (seconds) -, i. 25 Forceplate Veribcat ForceNormalized by BodyWeight Prostheeis 33:Dec. 22,1966;Test13;ClimbingStairs D 100 75 , _\ -- ,t, ,,... it itI 5 I.at - s £C' . 0 00 05 .1, ' " . 10 I ,; ? , t ~~~~~I ,)~t{ ' ' 15 t i I SI > i,8;hfk'' ,, .' :I , rime (seconds) 20 25 Figure 5-34: Forceplate data for subject 1: Ascending Stairs 112 Prosthesis33 Dc 22. 1986,Test13 Cmbin Stairs Prosthesis33, Dec 6. 1984,Test 15.ClmbingStairs Ii d 2 i x* II d 91 n 5 -R i Ii S i i I ------------- ie E o __ __ I 05 __ · S 2o r- B 5s 20 Thrt.1 I: Prosthesis33. May2. 1985.Test21.,ClrmbngStain Ii I 'a iII i I I m. J C lime. usconos Figure 5-35: Joint Angles for Subject 1: Ascending Stairs 113 Bnm ¥ Prosthesis33 Dec. 6, 1984:Test 15;ClimbingStairs Prosthesis33 Dec.22, 1986;Test 13;ClimbingStairs pox 29 27 25 20 21 11 t? 15 13 11 :11 II 9 I I 5 3 n-liTa- III-ICI-ll v IlIAIlll/l Pr0-rz~ rI IgOQU. 3 J.U R II-IA IIIII -li-fd . I I- I.IIIICIII.U Prosthesis33 May 2, 1985;Test 21; ClimbingStairs 2. 21 ,I 1I 3 IVIC.IJ I Il:JllC IIII IIJIIl, AlilnH Dr F ctlrq- - Rq oU .. R Figure 5-36: Regional Maximums for Subject 1: Ascending Stairs 114 Pri VII. - 'Jcl On 5 AR ·- . Prosthesis 33 Dec. 22,1988;Test 13; ClimbingStairs Prosthesis 33 Dec.6,1984; Test 15;ClimbingStairs Wa a 2 Is 27 21 II 1: IIIs II a qr Mn=AIIllUIl IrUrIIZIIIu I IIII Ui IrIUI*UIU. L . MIUIIIuII ,U. rIIUIIIlll Iu ri WUIll. Prosthesis33 May2, 1985; Test 21;ClimbingStairs pmal 29 n 27 2S 1 II I sBW IVllUtlllIIllM Ulllllll -11--A rUI. 120 L 12'~ L~ k.l Figure 5-36: Regional Maximums for Subiect 1; Ascendinq Stairs Prosthesis33 Dec.6, 1984;Test17;DescendingStairs m i 2S 27 is 21 12 II MaIIIllIII I fl1..A FIMDIIO UIIII.LJU U IrIIWUIl . .r In R I D.U Figure 5-40: Regional Maximums for Subject 1; Descending Stairs 114A O.U 114B Dec. 6, 1984; Test 17; Descending Stairs Normalized Pressure: MPa/(wht 2 * 1000. BW= 663 N .0068948) Ht= I AR m - - - -- - tran1l trans2 trans3 ........ 15 .. .. .. 10 trans4 trans trans6 trans7 trans8 trans9 transl O transl1 transl2 5 transl 3 0 0.0 0.5 1.0 1.5 2.0 Time tseconds) Figure 5-37: Pressures for subject 1: Descending Stairs 115 r Forceplate Vertical Force Normalized by Body Weight Prosthesis 33; Dec. 6, 1984; Test 17; Descending Stairs 150 125 - - - 4~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~F -* - -. ygp1 yp2 /% 100 tI 1 I T!I , % t t I I 75 I II I-I \ iI t i' t 50 % II I I i II I , 25 I I I''i - I 0 0.0 _ I . 0.5 . . % I I I . I. . 1.0 . i . 1.5 Time (seconds) . __ %__ 2.0 I 2.5 Figure 5-38: Forceplate data for subject 1: Descending Stairs 116 Prosthesis 33; Dec. 6, 1984; Test 17; Descending Stairs ~A 50 )U Q) .e C (D O I) 0) 'O 'O 25 25 C C O .- E X a) c- ..0 x C 0 C OO aO .5 44- CU 25--_ -25, 0.0 0.5 1.0 1.5 2.0 2.5 Time, seconds Figure 5-39: Joint Angles for Subject 1: Descending Stairs 117 y Prosthesis33 Dec. 6, 1984; Descending Stairs X Test 17 pmax 25 23.5 22 20.5 19 17.5 16 14.5 13 11.5 10 8.5 7 5.5 4 2.5 1 BW=( i-rl P cl -r . 1 0 .U IVICall lUul IuIIII l liIISU I r0OUIU Figure 5-40: Regional Maximums for Subject 1: Descending Stairs 118 subject has complained of balance difficulty; it appears that this is being manifested in massive co-contraction during this movement and during descending stairs. Visually, the subject ascends and descends stairs with difficulty, particularly during descent. Very high pressures have been measured in the second subject as he descends a set of stairs. Only data from paced descending is available, pacing was done at 80 BPM, however due to the difficulty with which he performed this movement the actual pace may be different. Figure 5-45 shows the local pressure magnitude in the joint during descending stairs. The pressures in this figure are normalized. Figure 546 shows the corresponding forceplate forces during the same tests; the vertical force at the forceplate is shown and it is normalized by body weight. The force on the instrumented leg is measured at forceplate 2 for this subject. The joint angles for the tests shown are presented in figure 5-47. Figure 5-48 presents the regional statistics for the same tests. While the kinematics for this subject while ascending stairs are similar to those from the first subject, the kinematics during descent are quite different and complex. 119 Dec. 14, 1992; Test 14; Climbing Stairs · Ik -AId I I,,,I.... 2 .I... *· nin BW= 565 N · nftanlflAl-. Transi Trans2 "' '"' " Tmrana3 "' 50 "' "' 25 '"""' TransS Tmns4 Trmnh6 Trans8 Trans9 Trans109 TranslO Tranal Trans12 Transl3 0 1.00 125 1.50 1.75 2.00 225 Dec. 14, 1992; Test 15; Climbing Stairs at 80 BPM 2.50 T2 e (second ime (secondi S) BW= 565 N 2 Normalized Pressure: MPa/(wht * 1000. *.0068948) - Ht= 1.6 m -"'""' 40 "' 30 "'""' "' 20 "' --- Transl Trans2 Trans3 Tmns4 Trans5 Trans6 Trans7 Trans8 Trans9 TranslO Transl 1 Trans12 Transl3 10 0 0.75 1.00 1.25 1.50 1.75 2.00 2.25 2.50 e (seconds) Figure 5-41: Pressures for subject 2: Ascending Stairs 120 Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; Dec. 14, 1992; Climbing Stairs - ', , I 100 --- 101, . - - - p2, I I i ', 'I , I 1 I II I , I I ! / I I I I I I I I ~~~~~I I II ! I I I , %t IIiI . 1 75 a I I I I I I I I I I I I I I 25 I i1., lt I I ,. I 0 --- Y·-·- -- c·-i------ · .I- 1.0 -. u- 1.5 -- - L .· .· · 2.0 Time (seconds) 2.5 Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; Dec. 14, 1992; Climbing stairs at 80 BPM 150 I I'~~~~~ jI. ~ 125 i 100 _ *1 ~ ~ r I - .m - Ip2, -.-.- - II i 75 I !i I~~ I~~ '. pr 50 I j i1' I II t I I 25 I *-I-.-·~Z=_.r.,*= 'i I 0 -'- 1.0 1.5 2.0 Time (seconds) -- 2.5 Figure 5-42: Forceplate data for subject 2: Ascending Stairs 121 Prosthesis 43; Dec. 14, 1992; Test 14; Climbing Stairs U) ¢D 0 75 0 0 o- C 0 50 0 I la E ._ o0 .10 25 C C 10 0 -3 0 0 1.0 1.5 2.0 2.5 Time, seconds Prosthesis 43; Dec. 14, 1992; Test 15; Climbing Stairs at 80 BPM 0 0) 0 (A 0) () 75 C C O .0 'ac 50 .2 iCD n CF a 0 0 .10 C c a 0 25 ..0aO cm C cO -3 -20 c -30 -3 O 0 1.0 1.5 2.0 Time, seconds Figure 5-43: Joint Angles for Subject 2: Ascending Stairs 122 Prosthesis43 Dec 14, 1992;Test 14; ClimbingStairs,unpaced Prosthesis43 Dec. 14.,1992;Test 15;ClimbingStairsat 80 BPM 11 11 I II :11 '3 11 11 11 I·lC4Al "l!11rr1u1I· ilrrlllll. · V w w And I IlLflll I wYIY Y . ofw_._ .- 2 . BW= IVI4,~I,/ 1 1- I*V · mali',d 1 wwI~ Figure 5-44: Regional Maximums for Subject 2: Ascending Stairs 123 PrAcllr' vl& * i l . 421 I! _. Dec. 14, 1992; Test 16; DescendingStairs at 80 BPM BW= 565 N Normalized Pressure: MPa/(wt/ht 2 * 1000. * .0068948) - - - -- Ht= 1.6 m 50 40 - - -' 30 ... .. 20 Transi Trans2 Trans3 Trans4 Trans5 Trans6 Trans7 Trans8 Trans9 Trans10 Transl 1 Trans12 Trans13 10 0 0.0 0.5 1.0 1.5 20 Dec. 14, 1992; Test 17; Descending Stairs at 80 BPM Normalized Pressure: MPa/(wt/ht 2 * 1000. * 2.5 Time (seconds) BW= RfiR N .0068948) Ht= . - Trans2 Trans3 Trans4 Trans4 Trans5 Trans6 Trans8 Trans8 TranslO Trans1i Transl 1 Trans13 Trans13 50 25 0.0 Trans1 -m- 0.5 1.0 1.5 2.0 Time (seconds) Figure 5-45: Pressures for subject 2: Descending Stairs 124 Prosthesis 43 Dec14, 1992;Test14;ClimbingStairsunpaced Prosthesis43 Dec.14, 1992; Test 15;ClimbingStairsat 80 BPM 21 a 21 27 6to 111 17 15 11 111 I 11 IB 1 f IMAlU I l IIII Drsorea rWIL rmnil^^aU rrUSur.; MIAII IIII 0".0 Drn IUlIWltU IIlloFU rlUI mfri- A~ 1 iu. '.4. 1 Figure 5-44: Regional Maximums for Subject 2: Ascending Stairs Prosthesis43 Dec.14, 1992;Tests 16and 17; DescendingStairsat60 BPM P... I 43 40 37 a 1i 11 13 I 1 alizedPressure:70.3 Figure 5-48: Regional Maximums for Subject 2: Descending Stairs 124A 124B Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; Dec. 14, 1992; Descending Stairs at 80 BPM; Test 16 , . III - - fpl, p2, I 125 9 I ~ 9 100 ~~~~~~~ 1 I' iii G) ., 9 75 I I 9 I m el 9 91 I I .9 \, .', so 9 9 I 9 I 9 9 9 9 9 , I I ?\ 9~~~~~ 25 .I19II. ." 0 0.0 ! -- 0.5 1.0 1.5 Time (seconds) 2.0 ._.t '.. ., 2.5 Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; Dec. 14, 1992; Descending Stairs at 80 BPM; Test 17 125 - I9 100 I c. 75 '' /I 9 9 I I co I I II 9t/I I 50 ! - - ii 4i ii ii' !' i i ;/ I t , t I I I 25 'IP, - - I iI' I I I I 0 0.0 -- -1. 0.5 -:.- 1.0 - - - - 1.5 Time (seconds) I- - - 2.0 -/ 2.5 Figure 5-46: Forceplate data for subject 2: Descending Stairs 125 II Prosthesis 43; Dec. 14, 1992; Test 16; Descending Stairs at 80 BPM 30 Un Q) 0' C C O 20 0) C C 50 10 0 ._ x 25 C -20 ,0 tO C _ C) .£ 0 -30 0.0 0.5 1.0 1.5 2.0 Time, seconds Prosthesis 43; Dec. 14, 1992; Test 17; Descending Stairs at 30 BPM 30 (D 50 C 0 20 c._ o -r .o C .0 .2 v -o V 25 3C0 o C .C 0Cr *8 0 01:. 0 C 0.0 0.5 1.0 1.5 2.0 25 Time, seconds Figure 5-47: Joint Angles for Subject ?: Descending Stairs 126 Prosthesis 43 Dec. 14, 1992; Tests 16 and 17; Descending Stairs at 80 BPM pmax 46 43 40 37 34 31 28 25 22 19 16 13 10 7 4 1 ialized Pressure: 70.3 Figure 5-48: Regional Maximums for Subject 2: Descending Stairs 127 5.4 Isometric Abduction Isometric abduction has been performed each time data is acquired from the second subject and was performed several times with the first subject. The protocol with the second subject has been that he lies on a physical therapy table and pushes outward against restraint; he is instructed to push as hard as he can. Data acquisition starts just as he starts to push, so that a ramp increase in pressure is seen. No kinematic data has been acquired during this activity. Abduction tests with the first subject were performed in a different manner, and were not consistent. A description of the conditions accompanies each test for prosthesis 33. 5.4.1 Prosthesis 33 Isometric abduction data at 6 months and 2 1/2 years post-operative were taken with the subject lying on a couch and pushing out against a restraining force. This subject was not instructed to push as hard as she could, and data was taken starting after she had been performing the activity for a short time. Kinematic data were acquired at the same time. Figure 5-49 shows the local pressure magnitude in the joint during isometric abduction. The pressures in this figure are normalized and smoothed. The joint angles for the tests shown are presented in figure 5-50. Figure 5-51 presents the regional statistics for the same tests. 5.4.2 Prosthesis 43 Testing of maximum voluntary isometric (MVIC) abduction has been done at almost every test session for the second subject. Figure 5-52 shows the pressures vs. time for some of these tests. The pressures in this figure are normalized. Figures 5-53 and 5-54 present the regional statistics for the same tests, however since no kinematic data is available statistics are only displayed for each transducer in the prosthesis. 128 Dec. 6, 1984; Test 52; Isometric Abduction Normalized Pressure: MPa/(wt/ht 2 BW- 663 N .0068948) 1000. transl 20 tns2 ------ Ht= 1.68 m i. . i. . tnas3 tan4 15 tranS - trius6 bns7 10 -- - --. transl trins1 5 trans13 -- 0 .- ..--. - . .................... . - -- . . . - - - - - - - - - - - - - ................................... ............................ .5 .. 1 .. .. .10 0.00 . r I . . . I - . I 0.40 0.30 020 0.10 Dec. 22, 1986; Test 14; Isometric Abduction Normalized Pressure: MPa/(wht 2 . 0.50 .. . 0.e0 Time (seconds) BW= 663 N .0068948) * 1000. - - 2 Ht= 1.68 m - - - - - Transl Trans2 Trn3 Tran4 TranS 15 Trns6 'II 10 TrnaW7 Trawu Trans9 Trmn10 Tranwl __________ I.- Tnrl12 Trn13 5 0 .5 o.C0 _I _. ---------- --- ----_ , 25 _ I, 0.50 - - - _ - 0.75 _ Time (seconds) Figure 5-49: Pressures for subject 1: Isometric Abduction 129 Prosthesis 33; Dec. 6, 1984; Test 52; IsometrIc Abduction 25 fie: ........ _a, 20 Isa 1s 5 o O10 i a (u I ------------------------ 61 5 _._1 0 ; 0.03 ,.1 0.10 . 020 i 040 0.30- ... I 0 f 0 secnds - Prosthesis 33; Dec. 22, 1986; Test 14; Isometric Abduction 30 6.; .. 25 20 20 15 1s S I11! to 10 ,I ., ........ -, ., ,,, I . . ' ,, W,,,' ', I!0 5 S A II _s 0.00 0 _'- . .-·_s . . J .1 ·.- . '---1··- 0.2 k -_ , -o · · 0O . L--- .l . , . .. 0.75 .v_ . _ . \: .. a Time, seconds . .. . Figure 5-50: Joint Angles for Subject 1: Isometric Abduction 130 Prosthesis 33 Dec. 6, 1984; Test 52; Isometric Abduction pmax 10 9 7 6 5 4 3 2 1 BW=66 >ll*lllIlII II IJ |- lii7d PrCS !. ,ir' . -k· 11 · I. Prosthesis 33 Dec. 22, 1986; Test 14; Isometric Abduction prnax 10 9 8 7 6 5 4 3 2 BW=66 IVItAll I WII I VW.IL~ I *u II i .I 1~ J1" CPrPC~llrP. l:i'7,-,I . V I. Figure 5-51: Regional Maximums for Subject 1: Isometric Abduction 131 MM;h I i I Ii J Ij I i iv 10 A i! l i ' " il l jJ!!JII}L J a I I ..I .. I I I i h.e i Sj _ _ 9 I Figure 5-52: Pressures for subject 2: MVIC Abduction 132 Prosthesis 33 Dec. 6, 1984; Test 52; Isometric Abduction prm Si 6 U- BW-e3 Maimum NormaIZeU .- . need-. -A;_ rrewssure; I I Prosthesis 33 Dec. 22, 1986; Test 14; Isometric Abduction p 3 BW-63 · rna1;7^SA DrotoraAII~nna~iiiiuiiii,4uiiikuiz-tiur Tti.2outi. FIGURE 5-51 ].32A li.303 Q 132s MVIC Abduction Normalized Maximum pressures at each transducer pMa 29 Prosthesis 43: Dec. 10, 1991 25 Tests 2 and 3 13 Data displayed in Data displayed in Right hip orientation Maximum normalized pressure: 11.6 BW= 529 N -t - I m MVIC Abduction Normalized Maximum pressures at each transducer pmAx Prosthesis 43: 25 Dec. 16, 1991 17 Test3 13 9 *5 Data displayed in Right hip orientation Maximum normalized pressure: 27.8 BW= 529 N m I-lt- Figure 5-53: Regional Maximums for Subject 2: MVIC Abduction, post-operative 133 MVIC Abduction Normalized Maximum pressures at each transducer pmax 29 25 21 17 Prosthesis 43: April 14, 1992 Tests 2 and 41 13 I 5 Data displayed in Right hip orientation Maximum normalized pressure: 31.8 BW= 578 N Ht = 1.6 m MVIC Abduction Normalized Maximum pressures at each transducer pmax 29 25 21 17 I Prosthesis 43: Dec. 14, 1992 Test 2 13 9 5 1 Data displayed in Right hip orientation Maximum normalized pressure: 58.3 BW= 565 N Ht = 1.6 m Figure 5-54: Regional Maximums for Subject 2: MVIC Abduction 134 MVIC Abduction Normalized Maximum pressures at each transducer Prosthesis 43: Dec. 10, 1991 Tests 2 and 3 7 i5 Data displayed In Right hip orientation Maximum normalized pressure: 11.6 BW- 529 N IH- i am MVIC Abduction Normalized Maximum pressures at each transducer F"M Prosthesis 43: I2: Dec. 16, 1991 17 Test 3 Data displayed in Right hip orientation Maximum normalized pressure: 27.8 BW- 529 N i - 1 Am FIGURE 5-53 I34A 134B MVIC Abduction Normalized Maximum pressures at each transducer PMX 29 43: Prosthesis April 14, 1992 Tests 2 and 41 17 13 1: Data displayed in Right hip orientation Maximum normalized pressure: 31.8 BW= 578 N W- = I A m MVIC Abduction Normalized Maximum pressures at each transducer Prosthesis 43: Dec. 14, 1992 Test2 17 13 Data displayed in Right hip orientation Maximum normalized pressure: 58.3 BW= 565 N Wt=1 Am I II - FIGURE 5-54 134c I . III 1311D 5.5 Single-Leg Stance Another activity during which little movement takes place is single-leg stance, always on the leg in which the instrumented prosthesis is implanted. Instructions to both subjects were essentially the same for this test and neither subject was assisted with support. The second subject had greater difficulty performing this test, due to his balance difficulty, thus he was not always able to stand on a single leg for the duration of the test. The forceplate data and the joint angle data indicate what movement was taking place during each test. 5.5.1 Prosthesis 33 Figure 5-55 shows the local pressure magnitude in the joint during single-leg stance on the instrumented leg. The pressures in this figure are normalized and smoothed. Figure 5-56 shows the corresponding forceplate forces during the test from December 1984 (the subject was not standing on either forceplate in Dec. 1986); the vertical force at the forceplate is shown and it is normalized by body weight. The force on the instrumented leg is measured at forceplate 2 for this test. The joint angles for the tests shown are presented in figure 5-57. Figure 5-58 presents the regional statistics for the same tests. 135 Dec. 6, 1984; Test 6; Single-Leg Stance Normalized Pressure: MPa/(wt/ht 1. 8W- 663 N ' 1000.' .0068948) I 30 Ik 25 _.. _ 15 V3 v ,, ...... ~~~~~~~~~~~~~~~~~----. . - - _.._._...._ _' . , _.~ fi I 'a..~~~~~. 10 1ram2 ._,., · --._. - --- ,I ---.... 20 b"1 Htl 1.68 m ,. ' .:_ ' ...~' .. Mul I Imnl3 1l3 i mgz~ _./~Vi . _ . 5 .~' ,V , _ _ ~ _ _ 0 -5 _ = 0.00 025 __ 50 I.. 0.75 . . .00 _ __ _ .... . _ .. _ _ ! . 1.75Time (seconds) 150 125 Time (seconds) 663 N Dec. 22, 1986; Test 21; Single-Leg Stance Normalized Pressure: MPa/(wt/ht _ .0068948) 1000. Hf 1.68 35 m ------ Trul Trmw2 Trt3 Trui4 30 Trt5 Trtn6 25 Trtl7 Trms8 Trans TrnO10 Trlil 1 Tranu12 20 15 'L 5·'-·-·-4' 10 f: \r I/ S t -A - .5 0.00 I / "" I -- - . I 025 c`·r"· l/ r I `·-·-·- ,,, \ . IN C -\t -! v, , 1 ,,! \II\\ - - - I 0.50 Trr13 -- ' 0.75 / - - i/ - Time (seconds) Figure 5-55: Pressures for subject 1: Single-Leg Stance 136 Forceplate Vertical Force Normalized by Body Weight Prosthesis 33; Dec. 6, 1984; Test 6; Single-Leg Stance '' 100 -\ s_. yp2 "' \- % 75 , % I ta . . . . . . . . . . . . . s .~~~~~~~~~~~~~~~~~~~~~ 25 _ 0.0 0.5 1.0 Time (seconds) 1.5 Figure 5-56: Forceplate data for subject 1: Single-Leg Stance 137 5.5.2 Prosthesis 43 Single-leg stance results are shown in figure 5-59 for standing on the instrumented leg. The pressures in this figure are normalized. Figure 5-60 shows the corresponding forceplate forces during the same test; the vertical force at the foiceplate is shown and it is normalized by body weight. The force on the instrumented leg is measured at forceplate 2 for this subject, and shows that the subject was not always standing on only the instrumented leg. The joint angles for the tests shown are presented in figure 5-61. Figure 5-62 presents the regional statistics for the same tests. The pressure data from this test for this subject, indicate how large a role cocontra tion forces can play in determining the loading at a joint. This subject is clearly having difficulty stabilizing himself on one foot, and must as a result be contracting the muscles about his hip joint since the pressures measured in the joint are more than double those measured during gait, even though the kinematics indicate little dynamic contribution to pressure. 138 Prosthesis33; Dec. 6, 1984;Test 6; Single-Leg Stance slOm ior 0o IS 10 c 2 - - - - I , - , I ' ' II c S I i ,I 0 I -S 9 10 ,I , , I I · -- I ... A 0 . .. 10 Os : · C · .s . _ *,0 Time,seconds Prosthesis33; Dec. 22, 1986;Test 21; Single-Leg Stance 0 20 25 0 20 ~'~ cc o o 0 .o x ,.,.,' Jt 11. L I II ~ ~I~ I 15 .5 0S 5i S 0 IlI~. 10 S5 1%1 - ' ~. , eS,' / I· % ' ~:';a'''^ '~ ' ^f?,X I ---a^'f^ s rI F- 0 ·10 c0 c -S .m I 00 0 -15 - L - - f 050 025 . ors . . C a -20 Time,seconds Figure 5-57: Joint Angles for Subject 1: Single-Leg Stance 139 C C Prosthesis 33 Dec. 6, 1984; Test 6; Single-Leg Stance (instrumented leg) pul 29 27 25 23 21 19 17 Is 13 11 9 7 3 I BW=663 il-.F3 - I;. U . fA UlL.rac.,ra' IVI Iu.iIII IV ICflt-ljne Prosthesis 33 Dec. 22, 1986; Test 21; Single-Leg Stance (instrumented leg) p=ax 29 27 25 23 21 19 17 15 13 11 7 3 3 1 BW=663 IVI¢AIIIIU l IIV ,l;-,rl IIIIIllCu Dr-,-. r 0UI ,V. I 1a 7.t Figure 5-58: Regional Maximums for Subject 1: Single-Leg Stance 140 Proethes 33 Dec. 22, 1986; Teet21; Sngle-eg Stance Protheel 33 Dec.6, 1984; Test 6; Singleeg Stance eU MU 11 11e 1: II I: BWEdt mJ AIIIIIII 11--A :Prov -- dlllrullslu kierluU '/ I M t A L, BW. M IIs mIIIIUull I1UIImIIIUI/ fml.t. lu^I. rl 1li l, A Figure 5-58: Regional Maximums for Subject 1; Single-Leg Stance Prosthis 43 Dec. 14, 1992; Test 6; Single-Leg Stance 11 I?Ial ls BW-M alzedPressure: 64.5 Figure 5-62: Regional Maximums for Subject 2: Single-Leg Stance 140A ].40B Dec. 14. 1992: Test 6: Sinale-Lea Stance ""' ""' ---' Normalize 50 ""' "" ---' 25 ""'-"' Trans1 Trans2 Trans3 Trans4 Trans5 Trans6 Trans7 Trans8 Trans9 Trans1 ( Transl' Trans1; Trans1' 0 0.0 2.5 5.0 Time (seconds) Figure 5-59: Pressures for subject 2: Single-Leg Stance 141 Forceplate Vertical Force Normalized by Body Weight Prosthesis 43; Dec. 14, 1992; Test 6, Single-Leg Stance I - I 100 II ' f i i ,5 ! ."*."s * / I I I . ' iii i!i J !I i I 'I i I ! I I I 0 ·i I I i - yp2 ii I -.<. ii I MM 75 i - v I i1 'i 'ij I I1 i ! I % !. I I 50 I II I i tI I I 25 . i I! I 0.0 L 1.0 1\ II i III I I II tI ' 0 I' iiII I I . -·- ~ . .- , % .' : ·- 2.0 · - , I NS~ -{Df- 3.0 4.0 5.0 % I" I 11 6.0 Time (seconds) Figure 5-60: Forceplate data for subject 2: Single-Leg Stance 142 , sSSXl Prosthesis 43; Dec. 14, 1992; Test 6; Single-Leg Stance 0 CD 50 50 U) a) 0) O) '0 0 ._ rC 0C 25 25 o 0._ tp 25 c ._ X C .. O) Ca 0 0 '" .0.0 1.0 2.0 3.0 4.0 5.0 6 'Qime, seconds Figure 5-61: Joint Angles for Subject 2: Single-Leg Stance 143 Prosthesis 43 Dec. 14, 1992; Test 6; Single-Leg Stance (instrumented leg) pmax 29 27 25 23 m BW= 565 21 19 17 15 13 11 9 7 5 3 1 ialized Pressure: 64.5 Figure 5-62: Regional Maximums for Subject 2: Single-Leg Stance 144 Chapter 6 Discussion This chapter will present a discussion on several aspects of the results, the acetabular location of pressures with implications on bone and cartilage response and endoprosthesis misfit, and the magnitudes of the pressures measured. Many other aspects of the data warrant the extraction of important information, but those chosen here are the most obvious areas to first investigate. 6.1 Endoprosthesis mismatch to acetabulum The mismatch in sizing of the prostheses was expected to produce an effect in the distribution of pressures on the acetabulum, though it was not known if the effect of such small mismatches would be discernible. The prosthesis implanted in the first subject was 0.6 mm over-sized in diameter relative to the natural femoral head, while the prosthesis implanted in the second subject was 0.7 mm undersized in diameter relative to that subject's natural femoral head. Differencesin the distribution of pressures were apparent shortly after implantation even in the absence of kinematic data during the first two weeks post-operative. Only one transducer reported significant pressures from the second subject during the early post-operative period, while four transducers had reported pressures at a similar level for the first subject at the same time post-operative. Figure 6-1 shows the pressure data for the two subjects during gait data taken two weeks after implantation. All of the transducers reporting rela145 tively high pressures for the first subject were active at the same time, indicating that several regions of the acetabulum were experiencing relatively high pressures, while only one transducer was recording similar pressures in the second subject, indicating that a much smaller region of the acetabulum was being loaded. Later data from the two subjects continues to show this effect, though changes occuring during the first 4-6 months post-operative tended to produce more similarity between the two subjects. These differences in pressure distribution correspond to the Hertz stresses analytically predicted when two different diameter spherical surfaces are in contact, For rigid materials a ball smaller than the socket in which it sits will contact the socket in one location at any one time. Although the femoral head replacement is rigid, the cartilage is not and so the contact is not solely point contact, but occurs over a smaller area than it would were the ball to fit exactly. Given the consolidation of cartilage in the case of the slightly oversized prosthesis, contact occurs over a large area. Results from in vitro tests with instrumented prostheses and cadaver acetabula indicated the effect of prosthesis fit on pressure distribution in the acetabulum for undersized misfits of 1-3 mm in diameter. [20] The pressure data from these two sub- jects support the in vitro results, and extend them to smaller misfits and oversized prostheses. 6.2 Cartilage adaptation to pressure Changes occurred in the pressure distribution over the implantation period for both of the two subjects. Since data is available for 5 years from the first subject and only for a year from the second subject, the data from the first subject has greater utility in discussing the adaptation process. There appear to be two phases during which the pressure distribution changes, an initial adaptation phase during the first year to 18 months post-operative and a degenerative phase late in the implantation period. The adaptation phase was manifested differently in the two subjects, due to the different directions of prosthesis misfit. In the first subject the prosthesis was initially 146 ?asioleei q'ui iioA vs'E Z. t VP a -. --" sro 117 - 2.8 -- a 3 - 7- II -'U AhoD, gp A2ftw .u Lk I.= ;.. .w 1.S L M #W=I 'a 20O.S -- 0 , I , l. i 2 ?MQW TIMM 9 3 Ax,. ,,,asca~wrR~c~r R L LU L2. T MW 0 3 Im , ! -T - C.t D - 'U 3 -. 7 -IY-TLC/~~~~~~C~~ -__L;-~~~~~--C?~ -11 -'m I I I & U L * ThM.WW0 UM, Ia _ - M P5Lj ... A I : l TUMD91V3 CA I 1.3 M T.J1. 1 IfP0 Rtvro - I -. n L25 LI l IUI i WALK III I I - "1'1,*" LC/1·"IL*W\WJhyyyyy I -om ...... ._ a L L Il--A·lrwuE I 1. I 1.5 L . ",, . I L7 L7 L L L . L mre Sm T9sl12 Figure 6-1: Pressures for Subject 1 walking, July 5, 1984 147 too large and significant pressures (3 MPa) were measured concurrently at several transducers during gait. The region over which high pressures were measured was more localized in the data taken at 11 months and 2 1/2 years post-operative than in the data taken at 6 months (figure 5-4). In the second subject the changes that occurred during the first year after undersized implantation were in the opposite direction, from data that approaches point contact at 2 weeks post-operative, to a high pressure region at 1 year which is similar in extent to that seen in the first subject at the same post-operative time (see figure 5-7). Following the first year and up to 2 1/2 years post-operative, little change appears to take place in the location or area over which high pressures are distributed. However, data taken nearly 5 years after implantation indicate a substantial change in the extent of the acetabulum over which relatively high pressures are measured. The distribution of pressures had become much more diffuse as is evident in figure 5-4 in the data from March 1989. Relatively high pressure measurements are found at that time in the outer regions of the acetabulum. This indicates that the prosthesis has thinned the cartilage to the point whereit has begun to protrude into the acetabulum. Following the death of the first subject the prosthesis and matching hemi-pelvis were donated to the lab. The thickness of the acetabular cartilage was subsequently measured using ultrasound by M.C. Clayton [10]. A representation of his results is shown in figure 6-2. This figure presents his data in the same reference frame that the regional maximum pressure data has been presented in this thesis. Essentially he found that the acetabular cartilage was very thin, with the thickest regions anterior in the socket. The ultrasound measurement system used could not accurately measure cartilage thicknesses of less than 0.5 mm. Much of the acetabular cartilage was too thin to be measure, leading to very sparse data. Visual inspection of the ac- etabular surface supports the ultrasound measurement data, as the cartilage is nearly non-existent over much of the acetabulum and is also "burnished", a condition that generally occurs after prolonged contact with a metallic femoral head relacement. Measurement of normal acetabular cartilage thickness by Rushfeldt from two cadavers using the same technique indicated that the thickest cartilage was more posterior 148 Acetabular Cartilage Thickness Measured post-mortem using ultrasound Prosthesis 33 implanted in joint for 5 years previous thick 2.5 1.75 1 148A 148B Cartilage thickness in millimeters post-vivo thick 3 2.25 1.5 0.75 0 I Figure 6-2: Ultrasound data on Acetabular Cartilage Thickness for Subject 1 on the acetabular surface, in much the same region that in which high pressures have been measured. [21] That the cartilage was thin in this region of the acetabulum from the first subject supports the hypothesis that the femoral head had begun to protrude. 149 6.3 Bone response to pressure loading The display of regional maximum pressures on the acetabulum provides an argument in the support of Wolff's law. This hypothesis states that bone grows in response to stress so as to support the loads applied to it with a minimum of material; Wolff's observation was that the spicules in cancellous bone in the hip joint appear to form arcades that line up with the assumed principle directions of stress in the tissue. [26] The regional maximum pressure data indicates that the highest stresses are in the superior/posterior region of the acetabulum as had previously been conjectured. Figure 6-3 shows the Xray image of a right hip from and the regional maximum pressures for gait from subject 1, in approximately the same orientation. Since Xrays are absorbed by the material through which they pass, and an Xray is a negative image, the densest bone will produce the whitest image. As can be seen in this figure the greatest bone mass is in the region in which high pressures were measured during gait. While gait pressures were not the highest measured, walking and standing are much more common activities than are rising from a chair or stair climbing. Bone response to the integrated effect of load and duration seems likely. A conceptual difficulty arises in that, if the data support Wolff's law, as they do appear to, then how does protrusion of the femoral head into the pelvic cavity occur? Shouldn't the presence of higher stresses in that region mean that bone mass in that region remains strong? So, why is this prosthesis thinning the cartilage to the point that much of the femoral head is loaded during data taken at 5 years post-operative? One possible explanation lies in the fact that the prosthesis is slightly over-sized. Perhaps the distribution of stresses over a larger area results in an abnormal loading such that the stresses are lower than normal in the high stress region. This may result in the bone mass in that region decreasing as more is formed in a less central area. This could eventually lead to the gradual inward migration of the socket area. 150 Figure 6-3: Xray of a left hip 151 6.4 Pressure magnitude In addition to changes that occured in the location and distribution of pressures, there were also changes in the magnitude of pressures and normalized pressures for both subjects. The magnitude of the pressures is influenced by the rehabilitation of the subject following surgery as well as by changes in the structure and mechanics of the joint. Both subjects show some similar trends in the changes in pressure magnitude during the first year post-operative. In the first subject the trend appeared to be that pressures increased for a particular activity until some time between 6 and 18 months, then leveled off. Maximum pressures began to gradually decrease between 2 years and 5 years post-operative for all activities. For the first subject the maximum normalized pressure during free speed gait was reached at 6 months post-operative. At 2 1/2 years post-operative this maximum pressure was 25% lower than at 6 months. At 5 years post-operative it was nearly 40% lower than the value at 6 months post-operative. Some of this decrease can be attributed to better muscle control and coordination. In general it appears that the maximum pressures attained during an activity increased during rehabilitation as the subject became stronger, then leveled off as the subject became more skilled at doing that activity. Decreases in pressure accompany the degradation of the acetabulum. Results from Hall et al [14] appear to indicate that cartilage synthesis increases when subjected to pressures between 5 and 15 MPa in a cyclical manner, though not for pressures between 20 and 50 MPa. As all the pressures measured were below 20 MPa it would appear that the actual magnitude of the pressures in the joint was not responsible for the cartilage degradation that took place in the acetabulum of the first subject. For the second subject the maximum normalized pressure continued to rise for the first year post-operative, in addition to the increase in the area of the acetabulum over which those pressures were measured. During gait the maximum normalized pressures were very similar to those measured in the first subject, between 20 and 152 25 (MPa/(BW/Ht 2 )). Although not included in this thesis, data was taken from the second subject at 15 months post-operative. The maximum normalized pressures during free speed gait at that time were slightly lower than at a year post-operative, suggesting that a leveling-off trend similar to that which was found in the first subject was beginning to take place. The maximum normalized pressures during other types of gait had also decreased slightly. While differences between data from the two subjects are notable, the ways in which the data are similar are also important. The pressures achieved, normalized or not, achieved were very similar for both subjects. The overall pressures found for the first subject were up to 18 MPa (2600 psi), or 76 (MPa/(BW/Ht 2 )) in normalized units. The highest pressure measurement made thus far from the second subject, in Sepember 1992, was 18.2 MPa, or 82.3 (MPa/(BW/Ht 2 )) during descending stairs at 80 BPM. This test was not presented in this thesis because the kinematic and pressure data was not synchronized on that day. The maximum pressure measured from the second subject during the data acquisition sessions presented here was 16.2 MPa, 73.4 in normalized units, during jumping off a 7" step. During free speed gait the maximum normalized pressures measured during the first year post-operative were between 22 and 26 for both subjects. The actual maximum pressures measured were between 5 and 6 MPa for both subjects. These similarities exist in spite of gender, morphological, and neuromuscular control differences between the subjects and differences in the way tests were performed. The measurement of such similar pressures, in similar regions of the acetabular surface, from two very different subjects, substantiates the validity of the results obtained. In addition, the in vitro calibration performed on the first implanted prosthesis post-vivo establishes that the measurements made with that prosthesis in vivo were accurate. Reviewing the changes that occured over time for both subjects in both the pressure distribution and pressure magnitude, the presence of three stages during the implantation period appears. The first 6-11 months are an initial rehabilitation time, during which the cartilage adapts to the replacement femoral head. A more advanced 153 rehabilitation period follows, with some overlap, taking place between 6 months and 18 months, during which the patient reaches a steady-state strength and coordination level when performing different activities at different times. Following this period there is a gradual decline in the pressure measurements due to cartilage degeneration. 154 Chapter 7 Conclusions Nearly 100,000 femoral head endoprostheses are implanted in the U.S alone each year. A better understanding of how these prostheses perform and how they fail will have an impact on the lives of an enormous number of people. A number of conclusions can be drawn directly from the data obtained from these two instrumented prostheses. Additionally, these results can be used to support or challenge theories on joint lubrication and wear. Finally, since these results provide unique information on the actual in vivo loading in a human joint the data presented here are expected to be of value to other researchers investigating cartilage, synovial joints, bone, and musculo-skeletal analysis and experiments. While there have been only two subjects thus far, the similarites between the subjects' data are reassuring, while the existence of data from more than one person nonetheless provides the opportunity to separate subject-specific results from those which are more global. Recalibration of the first prosthesis post-vivo established the accuracy of data previously obtained in vivo, and validated the entire instrumented prosthesis design and data acquisition and processing system. The major conclusions of this thesis are that: a misfit of less than 1 mm in prosthesis diameter can significantly influence the pressure distribution in the human hip; the location of high pressures on the acetabulum supports Wolff's law; significant changes in pressure distribution and magnitude occur over the implantation time of a prosthesis; the normalized pressures measured in both subjects were similar; and 155 muscle co-contraction during routine maneuvers strongly influences the loading, and thereby pressures, in the human hip. The collaborating surgical team took great care was taken in fitting both of these subjects with their prostheses. Even so, the prosthesis implanted in the first subject was 0.6 mm over-sized for that person, while the second subject was implanted an 0.7 mm under-sized prosthesis. Considering the care taken to match prosthesis and subject and noting that standard femoral head replacement prostheses are only available in 1 mm increments in diameter, it is likely that a very large per cent of individuals are fitted with a prosthesis that does not quite match their natural femoral head. The evidence from this research is that even such small mismatches can and do affect the distribution of load in the human hip joint. The high pressures measured in the two subjects in this study were concentrated in specific regions of the acetabulum for each movement studied, and were generally located in the superior-posterior region. Wolff's "law", essentially contends that bone grows so as to optimally support the applied stresses with a minimum of tissue. He based his finding on observation of the structure of cancellous bone in the hip and on assumptions of the stress distribution in the joint. The data of this study support Wolff in that the location of high pressures in the joint during gait corresponds well with the most dense region of bone in the pelvis. The distribution of pressures on acetabular cartilage changed over the implantation period for both subjects. High interior and central pressures became less localized during the first year post-operative for the (second) subject fitted with a under-sized (0.7 mm) prosthesis. The pressure distribution for the first subject fitted with an over-sized prosthesis also changed during the first post-operative year. Here the higher pressures initially were distributed over a relatively large area, with the highest pressures in the outer part of that region. Later in the year the highest pressures were measured more centrally. Adaptation of the cartilage in the acetabulum to the rigid replacement femoral ball clearly accounts for the changes seen during the first year post-operative; different geometrical adaptations are a direct consequence of the fit of the two prostheses to the joint. Late in the implantation period of the 156 first subject the distribution of relatively high pressures became diffuse and there was no distinct region of high pressures. Degradation of the acetabular cartilage had probably occurred by this time and is believed to be the reason for the change in the distribution of high pressures. Changes also occured in the magnitude of the pressures measured during the time the prostheses were implanted. The maximum pressures reported increase during the first year to 18 months post-operative, then level off and decrease later in the implantation period. The asymptote of maximum pressure was found to occur at different times post-operative for different movements. This trend follows the regimen of the rehabilitation process, the more strenuous the movement the longer the post-operative period before pressure measurements reached steady-state. Trends observed in these changes during the first year post-operative are similar for both subjects. Later in the implantation period the maximum pressures measured decreased significantly; accompanied by the more diffuse loading pattern mentioned above. The pressure measurements from both subjects were similar in many ways. Data from the second subject substantiates the results previously found from the first sub- ject. [8]Irregular pressure distributions are routine in both subjects. The magnitude range of pressures measured was similar for the two subjects, in both cases the highest pressure recorded was about 18 MPa. Maximum pressures during free speed gait are between 5 and 6 MPa for both subjects during the first year post-operative. Normalizing by body weight and height, the maximum values were between 23 and 25 for free speed gait during the first year post-operative for both subjects. The maximum pressures during other movements were not as similar due to subject-specific factors, but the range of measurements was almost the same. The locations on the acetabulum on which high pressures were measured were also similar for the two subjects in all movements. Muscular co-contraction has been established as a major determinant of the resultant load at the hip joint. Early observation of high pressures while rising from a chair, prior to the measurement of large forces on the forceplate, indicated the importance of muscle forces on the loading experienced by the joint. That informa157 tion is now supported by results from a number of movements during tests with the second subject, from stair-climbing, stair-descent, and single-leg stance in particular. The pressures measured during single-leg stance were more than twice as large as the pressures measured in stance phase of normal gait. No research is ever actually complete; this project is no different. There are several ways in which this research should be continued: future data from the second subject should be acquired and analyzed; data from future instrumented prostheses should be compared to the results from these subjects; results from this work should be used in considering lubrication and wear phenomena in synovial joints. I hope that someone will continue to investigate the data acquired in vivo from these instrumented prostheses, and that the results presented in this thesis will be useful to other researchers in determining parameters to use in studies of articular cartilage and synovial joints. 158 Appendix A Transducer Locations and Numbering Figure A shows the transducer numbering and locations for prosthesis 33. The view shown is looking into the inner surface of the femoral ball hemisphere. Figure A shows a similar view for prosthesis 43. Table A.1 presents the transducer locations in prosthesis latitude and longitude, where transducer 1 is at one "pole", or 0° longitude (a). 900 latitude () is in the same direction as the positive y axis in prosthesis coordinates, toward transducer 8 for prosthesis 33, and 0° latitude is clockwise from that direction. 159 Location of pressure transducers in prosthesis 33, looking at inside surface of open hemisphere <--- anterior for L hip * anterior for R hip ---> transducer not working or non-linear response to pressure Figure A-1: Transducer locations in Prosthesis 33 160 Table A.1: Transducer Locations in theta and phi Prosthesis Transducer 33 TOI 1 0 0 2 90 30 330 270 210 150 90 38.6 347.2 295.75 244.3 192.9 141.4 0 90 30 330 270 210 150 60 17 343 197 163 120 120 31 31 31 3 4 5 6 7 8 9 10 11 12 13 14 __- 43 eO 1 2 3 4 5 6 7 8 9 10 11 12 13 Temp 161 31 31 31 62 62 62 62 62 62 62 0 31 31 31 31 31 31 53 60 60 60 60 53 20 Location of pressure transducers in prosthesis 43, looking at inside surface of open hemisphere anterior for R hip ---> <--- anterior for L hip * transducer not working or non-linear response to pressure Figure A-2: Transducer locations in Prosthesis 43 162 Appendix B Calibration of Pressure Instrumented Prostheses The calibration process for the instrumented prostheses includes calibration of the electrical output of the pressure transducers to applied pressure, but also must account for the effect of temperature on the output of those transducers. Other variables that may affect the transducer output are: time, power level supplied to the prosthesis, and length of time over which the prosthesis is powered. The transducer offsets are known to be affected by temperature and are known to drift over long periods of time (months). Powering the prosthesis for an extended period of time was expected to only affect prosthesis 33 which dissipates more power and therefore may heat up slightly if powered continuously for a long time. In addition, since the transducer gains may change over the prosthesis lifetime, recalibration of prosthesis 33 post-mortem was done in part to check this possibility. The major step in calibration of the pressure transducers is calibration of their output with respect to pressure. This is done prior to implantation of the prosthesis, but following the removal of prosthesis 33 it was also recalibrated because it had been over five years since the previous calibration was done and because some of the pressures measured by it were above the level for which it had been calibrated pre-implantation. A new pressure vessel was designed and constructed in order to calibrate the prostheses to higher pressures; the one used previously for number 33 163 pre-implantation relied on a restraint mechanism which exerted too high a stress on the cast stem region of the prosthesis. All pressure calibration was done hydrostatically in oil, with the entire ball stressed. The pressure vessel is shown in Figure B-i, with a prosthesis shown in the cutaway view. The stem extends out of the vessel to allow data transmission and powering of the electronics in the prosthesis. n Figure B-2 shows the entire set up for pressure calibration. A dead-weight tester was used for pressurization, up to 2500 psi (17.2 MPa) in increments of 25 psi (0.17 MPa). An external pressure gage was used primarily to check for any rapid transients in pressure, and also to double-check the dead-weight tester. During later tests the pressure vessel also could be heated via a coil which surrounded the base of the pressure vessel and was attached to a power source with thermostat control. The heating element was only used with prosthesis 43, in which there is a thermistor; there was no means for monitoring the internal temperature with prosthesis 33. Data acquisition from the prosthesis during calibration tests was similar in equipment and procedure to data acquisition from prosthesis 43 in vivo as described in Chapter 3. An AT&T 6300+ PC was used, data was saved at 500 Hz for transducers in prosthesis 43 and 250 Hz for the transducers in prosthesis 33. Statistics for each data set were found; for calibration of transducer output with respect to pressure or temperature the mean of each data set is plotted vs. the variable of interest. Calibration was done in psi (because the dead-weight tester weights and piston were calibrated for psi); four different tests were done on prosthesis 43 and it was calibrated to 2500 psi (17.2 MPa), two tests were done on prosthesis 33 and it was calibrated to 2000 psi (13.8 MPa). Table B.1 summarizes the days and the test formats for both prostheses. For prosthesis 33 both tests were at room temperature (78 F, 25.5 °C) and one was up to 1000 psi (6.9 MPa) in increments of 50 psi (0.34 MPa ) and back down in large increments (about 200 psi (1.4 MPa)). The second test with prosthesis 33 was up to 2000 psi (13.8 MPa) in increments of 100 psi (0.69 MPa) below 1100 psi (7.6 MPa) and in increments of 50 psi (0.34 MPa) above 1100 psi (7.6 MPa). During the second test, when pressure was decreased it was done in 164 iL I i Fgr es l rsr s , f iri i Figure B-l: Pressure Vessel used for Calibration of Prosthesis 165 Hydrostatic Pressure Calibration Setup Prothais Tatar Pressure Gage Dead Weight Tester Figure B-2: Experimental Setup for Pressure Calibration of Prosthesis 166 Prosthesis Date 33 Nov. 29, 1990 33 Dec. 10, 1990 43 Jan. 43 Jan. 18, 1991 43 43 Feb. 19, 1991 Mar. 5, 1991 Range [psi] Increment [psi] 17, 1991 0-1000 1000-0 0-2000 2000-0 0-1000 1000-0 0-2500 2500-0 0-1000 0-1000 a 50 200 100 100 50 50 100 100 100 100 'Four cycles between 0 and 1000 psi Table B.1: Pressure calibration tests 167 Temp. [°F] 78 78 78 78 78 78 78 78 98 98 increments of 100 psi (0.69 MPa) between 2000 and 1000 psi (13.8 and 6.9 MPa) and in increments of 200 psi (1.4 Mpa) below 1000 psi (6.9 MPa). Prosthesis 43 was calibrated with respect to pressure on four days, using four different protocols. Two of these tests were done at room temperature ( 78 F, 25.5 °C) and two were attempted with the temperature of the pressure vessel raised to approximately body temperature. Of the two tests performed at room temperature, the first one was done to 1000 psi (6.9 MPa) in increments of 50 psi (0.34 MPa) both on the way up and on the way down, the second test was up to 2500 psi (17.2 MPa) in increments of 100 psi (0.69 MPa) for both increasing and decreasing pressure. For the first test with the pressure vessel heated the temperature of the vessel was raised to around 98 °F (36.7 °C) but no control was exerted over the temperature as the pressure was raised to 1000 psi (6.9 MPa) in 50 psi (0.34 MPa) increments. During the second test with the heated pressure vessel the temperature was monitored and was more stable than in the first heated test. The second heated test consisted of 4 cycles in pressure between 0 and 1000 psi (6.9 MPa). Only the first cycle was used in pressure calibration. Results for the pressure calibration of prosthesis 33 are shown in figures B-4 through B-17. These figures show the means of the data taken at each pressure during the test run. Also shown in these figures is the best fit line to these means. The transducers which have a linear relationship with pressure are the only ones for which results herein have been reported. For these transducers the relationship of output to pressure can be described by an offset and a gain. Table B.2 summarizes the results of pressure calibration of prosthesis 33, giving the post-vivo gains and also presenting the gains used during the implantation period. Table B.3 presents the difference in pressure estimates that would result from the different gains. Results from the pressure calibration of prosthesis 43 are presented in figures B-18 through B-30. Only transducer 4 appeared to be nonlinear with respect to pressure. Figure B-3 shows the temperature during the pressure calibration tests, these temperature estimates were obtained from the thermistor in prosthesis 43 which had previously been calibrated in a series of thermal calibration tests. Table B.4 sum168 Transducer Nov. 29, up Nov. 29, down Dec. 10, up Dec. 10, down Nov. 29, all Dec. 10, all ex vivo pre-implant 1 0.488 0.513 0.482 0.492 0.498 0.487 0.493 0.49834 2 0.818 0.813 0.776 0.768 0.819 0.775 0.795 0.7955 3 0.622 0.622 0.590 0.595 0.625 0.595 0.61 0.61685 5 0.755 0.752 0.755 0.742 0.756 0.751 0.75 0.65058 7 0.684 0.668 0.629 0.649 0.680 0.642 0.66 0.62767 Transducer 9 10 11 12 13 Nov. 29, up Nov. 29, down Dec. 10, up Dec. 10, down Nov. 29, all Dec. 10, all ex vivo pre-implant 0.521 0.573 0.551 0.576 0.544 0.561 0.55 0.59583 0.689 0.742 0.726a 0 . 7 51 b 0.715 0.737c 0.73 d 0.78429 0.840 0.819 0.805 0.812 0.834 0.808 0.82 0.94738 0.902 0.900 0.937 0.928 0.902 0.932 0.917 0.91537 0.652 0.684 0.684 0.681 0.667 0.683 0.675 0.74245 aBelow 1300 psi bBelow 1300 psi CBelow 1300 psi dBelow 1300 psi Table B.2: Gains of prosthesis 33 pressure transducers Transducer AP [MPa] AP [psi] 1 0.01 1.45 2 0.0 0.0 3 5 0.011 -0.132 1.6 -19.1 7 -0.049 -7.1 9 10 11 12 13 0.08 0.074 0.16 -0.002 0.1 11.6 10.7 23.2 -0.29 14.5 Table B.3: Difference in pressure estimates for different gains 169 marizes the results of pressure calibration, presenting the gains found. Offsets were found to vary with time for this prosthesis as well as for prosthesis 33. The variation in temperature during the first heated test appeared to cause a variation in transducer outputs; this data was ultimately not used in calculation of transducer calibration. The differences found in the transducer gains for prosthesis 33 were on the same order as the different gains found prior to implant. Evaluation of the maximum pressure reading by each transducer and the maximum error in gain revealed that the largest changes would be about 0.3 MPa. This is on the order of the noise in transducer output. The transducer with the largest changes in gain did not measure very high pressures, and the transducer which transmitted the highest readings appears to have a very stable gain. Only one transducer was found to have different behavior at pressures above the level to which it had previously been calibrated. This transducer (shown in figure B-13) appears to have a change in gain above 1300 psi (8.96 MPa). Fortuitously this transducer has never reported outputs above or near that level. Pressure tests on prosthesis 43 at body temperature as well as room temperature indicated that transducer gains were independant of the temperature of the prosthesis, as had been expected from results of calibrating other prostheses. 170 II~r . [ . . - - T L N 7_ ,I . 0 cn DO 0 a) I i1 I I i 0 cn O O 0 p I ! o Q L._ cO -> / /1 i e 1 Cn 1 i5 I Q. cO i I I I I i a) C 8· I \ O O E 0 , _ L- _ \\, . L- I / / / a,- EM I , I w ia Ii E I 0LO I i E I (D - u: c: I T I \ T~ I Cc i I 0 O- .6 !© 1 I I 0CD ( I I · I · .I I _I 0co (j) eiJneJadwe Figure B-3: Temperature during Pressure calibration tests 171 o N~ 0 0D D. Transducer Gain [cmv/psi] 1 1.22 2 3 5 6 7 8 9 0.987 0.678 0.976 1.23 0.960 0.870 0.795 10 0.885 11 0.814 12 13 0.839 0.888 Table B.4: Prosthesis 43 pressure transducer gains 172 E 0 In In 4n M 2 4n 0 5D U c Si - E v p 0L 0 9 0. 2 0 -u 0 f0 c 8 Fj I!o 0 0 lndln 0 u'lndln ro cr 0 8 5 o I 0 vI , 0c 0mC 12 U rG, 8 .. o 0 a; s zC 8 Z i e >t : 8 z0 ,- oS - 8 o -: F-8 8 N I 8 ° Figure B-4: Pressure Calibration of Prosthesis 33; Transducer 1 173 8 0AT E! M M Q. a, 5 1 0 0. 0 Ic 9 5 i, d § 4@ _ S .1 C, rv Y .rF m 8 CI; f , X a C' - ry T 0 c 0 NL3'lnaln .u')lndflnO 8 El 0 , UD , a 0 In In .2U, a2: 8 0) t . a C1 z I i, m kt O ST aX o U Z , r. T Z h 8 rN - 2a 0 _ _ > ; i 0 0 8 _ _ Figure B-5: Pressure Calibration of Prosthesis 33; Transducer 2 174 El En 11) 8 v) 5D () 0 T o a o o) - o : cL a I- 8 u c ZI .n 8 8 ,;lzndlnO ,n'jndjnO R _ S_O 0 9? D 8 . nE UM p C En 5n C RI U 0..t% C a 0Ir It 8 v 10 V z o o t Nm 8 z U C rc 8O. 8 C LI c C, : o POrue3onaln ;eCalano Figure B-6: Pressure Calibration of Prosthesis 33; Transducer 3 175 a v _· T ___ _ _1 · __ E! a -U 8 O 0 (L b9Vn L) 0 a. YI . ~~i~~~~~i 35D e In 9Y m e CJ - V I p C; U v, C 5r ! I . o 0 e1 EE v i 4 i 8 u o _ 8 i i k ! o 0 o0 A'ndiO ,; InalnO ° R Y O ..-Wb 1 .~ - 7a o e 8 .D 0 o r zm CD 8 o zc 0. aC I l fi B , t , -0 a r.~ i ~ ~ 0) 0 8 'R 2"O O 8 N Ci O 2 0 8 I c cu .Y -. C 8 Figure B-7: Pressure 0 8 8 Calibration of Prosthesis 8 33; Transducer 8 4 Figure B-7: Pressure Calibration of Prosthesis 33; Transducer 4 176 G Q D C 2 i! v, n y) 0 _ c) 8 5D 9 ZF s a 4,'a'V nt. 'a ,; I o a a) a o4; Vl _ a) I 0. 9 u cX r. lri 8 I 0 0 , i.8 i 8 ,'a C- 0 Y zo 11 8Im O 0 tr. 0 C. 0 0. cn 't, 8 6 8 Z. E; 0 O .. z ru7 z8 - ,i o r CG II, Z ; 1; E 3 -: 8 8o 8 0.10 88 8 -jo aln Figure B-8: Pressure Calibration of Prosthesis 33; Transducer 5 177 8 ___ .1_ _ rF _ _· _ __ __ w IL w 6.4 0) a 0) 8 y, a! I4X .9 'Al 0 P , 0. e0 0) 0...... . . . . - a .e I I a W, v 44 8 , e cL 0 0 .. - a; @ o 4 vI cL o0) c, o C 0) a. Dfo 8 44 4i a u U 'V I p or 44 -""% , * % .. ribe ,o, . :O PO---.) - 8 10 § 8 o I h.-xvnC)ng · _ - . .. . . ...-.. 44 8 ) v) p. (t 'U 9In 0' 0) Z,, I' 8 !i t04 a e , 8 . aA v _ 8N~; a.. 2t z -i~~ ;, .4 o a e _- . 8 rN . -c ....---- ------- ------ o m 0- ZI § I.-: I §~~~~n 'r.11-CO 8 0 , in'ln 8 o Figure B-9: Pressure Calibration of Prosthesis 33; Transducer 6 178 c a a0 U a) i c 2) QI F V) m 0 r- Ca 8 a I."A~ § 8In § PhLujln i~~~~ lnOO l A'jnln O 8 S ° 6 0a) 8 o 2u) 8 , u) .' 0 m zC- 8 _ C) .v , 8U o Ru o 8 - 8 Z0 > 8 C C. L 8iN o .. o .' I,:.,r, ,~.u3 in(]n O Figure B-10: Pressure Calibration of Prosthesis 33; Transducer 7 179 tL 0--l~-. .-- · r-- ----- -- ·- r-- · ~~~~~~~~~~~~~---r-·--r-r--~~~~~ TT I --& 4 -s ,--- ' c---------r 0) 1 ! t c--ar? `` -··M a P - -~ -4~~~~~~~~4 a . ·, g c--49------ tU v --------k=-------o ~~~ 1~~~ 91 i 8 -9 '' id O (L '' 8 h--r O.. U, c CL · 'V 0 o L ~ c9-( (--8n L v, o , , , o . , Ut - o -.------- e-c 0 1 &avindino a.~~~~~~~~~~~~~~~~~~~~. d' , , ,u'lnOln 2 / V, U, i, .9 U) tm ':, , (n D r m T c G LS 0, CY a 0 _ c a,, a t o u 0. ,'" , o 4; z 0 I , i '7, 66 !~~~~~~~~~~~~~~~~~~~~~~~~~ 0 0 o o 0 8 0 8 0 AftLl"ndino ln Figure B-ll: Pressure Calibration of Prosthesis 33; Transducer 8 180 LD 0 (n 0 b I ! 5_ I 2 00 g 41 § 5 0 CL 8 o cr 0a A o 0 0 e oU § 0V) I0L 4; 5 I V z a. 8,(U 0 oD o 1 ° 0~~~~~~~~~~~~~~~~1 ° o o -c o 8 '"'DIlndano u,lndlnO Figure B-12: Pressure Calibration of Prosthesis 33; Transducer 9 181 0 8o a 1.) m C L 0 § S. 4 0al i D C E: cU) 0 8 ew N J'Ldln olr'FJlno ' CD § 0 4 . 0- -Q 2! U) F C !C t z 080. a o S z wI C n C; 1C 8 T oJi a 0 0 8 "I I i c ';ndn ;nQ 8 N n' o 8 8 N _ lncnO Figure B-13: Pressure Calibration of Prosthesis 33; Transducer 10 182 8 E a 8 I I, ( g - c o' . o 9 -4 - ow . o A E, 1 0sU9A U Z U 8 8 E 0 6: o ^z'anajn O fua'lndlno 6 O 0 g , g 0 'A n V) 8 cm CL 0} E .r P F (P u) M. a,0 N zEE a cco C. 0 I 8 IV (L a. U 8 z 'F 8 8 g Ca 8 Io o 8 8 &"3 8 P mndlanO 8 'wlIndino Figure B-14: Pressure Calibration of Prosthesis 33; Transducer 11 183 0 0 C, 0. e 8 t 8 CL F m %) 'a I0 n_ 0 0, 0 e A 0 0. C) 8 0C. Cu 2 C 0- 011 oO 11 1<:D T a ' §n tncln0 ln ALAJ11t~d~flO QLu0'ln MCJ~V~d~no _ 0 8 o 8 10, 0 !I 0 .D C IV C 0, 1 e m 0G C, o) 0.. 0 00' C. a n §C P 0) 0) z0 C, 9 rs Zo cl 88 Cu, 8 i N 8 c, oo° 8 o 8 o8 , InClr.: no s0 0 &.l"ndlno Figure B-15: Pressure Calibration of Prosthesis 33; Transducer 12 184 2 I a0 0. a.4 Ce n 064 a I O 0 M 8 (3 H :0 0 8 ° 8 | 8 8 o ° 38 8 8z 8 0 oO cD n4 0 u, tL F V. CL m U, 0 aG 8 IC a. -B e o z z I C.) c 0 8 0 r2 I 5 8 S ,: _ 0c C 8 8 8 0 a3'lnno .n,-u Figure B-16: Pressure Calibration of Prosthesis 33; Transducer 13 185 8 ...I w .. .. .. . . ..... L jl -'--- - - - F . ...... i . . ... 4 - - a.. 'MI Ic--~-O ---- 4-4 1 a g -'--- I 6 i I', -p*' a 6; c---4--- -1 r I o , f t * c i- I A 0 . 5,~~~~a _ O a_ 0_ .9 ,uz ^ - ^ . o, _ nalno A'lndlnO r i - N - - . - - . _ .- q----- 8 0 a. p CL cm ff-----Q'-----4 a * ~~. 0 I n N 9 § a; , £S I: 01 zet z i Ii 0 2 CU 8 8 1 C -~~l J _ I .p r, 1. I r , -S . o C . c,. I C D F n:u. :nolno o N N ul; ndlno Figure B-17: Pressure Calibration of Prosthesis 33; Transducer 14 186 Ii I I I Ii Ia AUglnnQ muwno AUOVdVO it An'lldnlnO 0 0 0 0 8c Or 0 0 (D 0 C 0 ,3 U) C 0 IC N Im 0 0D O 0V 0 0 0 CY V 0 0 0 oo o 0 0 o ud 0 AUlndlno ^AW'lndlno Figure B-18: Pressure Calibration of Prosthesis 43; Transducer 1 187 o) II F 'I I 2 I aL - I iV Uwrva ig ijI% - Il ,S El ii AJucfno Aulmdln l Two o _ 0 _W Y 0 0 In o8 0 9 -._ aa c a C2 _a a 1 i-- o LO U, C Q E o 88 3 CU F 1 S CM ns P P t Figure B-19: Pressure Calibration of Prosthesis 43; Transducer 2 188 I I U li I i .i i;B T I It I Ai I 2 & a- ,;"E r 89 88 RR 2 ~, 9 Auo'Flnno AuVanmlO Au'irtnlo AuDlnO g o cg 0 CY O 0D 8CY o 0 m 0 is C,D 0 .I I C 'a r 8 I- 0 v) .. 2 In Q It ( 0 0 CY ee 0, o 0 ° Nm A'r:lddlo u.n'jdlno! Figure B-20: Pressure Calibration of Prosthesis 43; Transducer 189 3 e o 0 ,. ! + w I qr" I .I IT I I I . 4 a 'iI it 6 I 4 I i I i _ 8 I. .-i .L 8& . I I It' I I T, CL etc I § "4" I , . 4 4i ol I I I I I I I 8 4. - - o _ _ I I I I I § E - A'Olndfno A=XlndO Auxnfoko m - ___ 0 0 0O C co .. so us .4t..4 .,_~~~* A.; . :* of r 0QQ ~0 liw . 80 §o8CI-i I- .S. Ds cv 0 0 isIE . ;6_ 8W) s4q4Ot w :a . 0. - 144 'I. i oo 404 mm 0 cJ o 0 o 0 CY Awlinndlno A.rwl'dxJO Figure B-21: Pressure Calibration of Prosthesis 43; Transducer 4 190 o a, U) U) P (0 0- i I 4. ~4. 4. I I 4. i 4.1 ia.d 4.L~ 4. I Ir, A. J1 t:. ii, 44 I a I 9 I 0 -L I CL s -6. i I ini I 0- 4 §o I i I IL II -4 4 i R Xc o e 1 Ie g| '6 tIt i i 6 i J o O G MAUWWO _ i _ O - W A1D0rdM AUD 8 o0 NO -. a0 = 0-e m 72 v OD0 00 ai 0 a '* 4' C 0W; Iu, Iis§7 88 a, U) o4' iN - I g 0e "1*,. §0; . I _ I§ 44 I o o )e 40 W vC §§ - - u- rx-lir I I 44 -m a AuWOnlv flO Figure B-22: Pressure Calibration of Prosthesis 43; Transducer 5 191 oo u o F a r ia fI 4i 5 I8 I $ $I .1 }x h 8& q Ft Io m: J . u'lfnO ewrllno AHLVncrO 'lndino 0 8 m Cy 0 0 CD in =0 N X C . AD cr 7U S a _ hesn7g (6 e I-. _ o AwllcdnO sO'IldlnO Figure B-23: Pressure Calibration of Prosthesis 43; Transducer 6 192 w X Pm 2i O) gm 0 (12 8p 8 &n 0t (aco0 -i I at I I III A a }i fl 4i i~ i dNAnyo) ww4no o Adfo AUAVo 52 ~~ ~~~ ~ " 0 N 2 ~ ~ ~ 0 (U 0O = co 8 0 co o8 as 2, 7 8 oo.. N I-c co e i 7 I N o § §o §o § Figure B-24: Pressure Calibration of Prosthesis 43; Transducer 7 193 .a 0 0 r I i 1 I. i ti. 3 i Ii I q11, i '4 I' I.3 tl I i 2Q o 0 0 U-5 A, IS s CQ o c 0 00 ata s CD 51 *') 0 a3 oe 7 In Sr co OD N g sa _ 0°oH _% 8° - CD C. a Auwlndino Aulndln 0 Figure B-25: Pressure Calibration of Prosthesis 43; Transducer 8 194 iI i 'i 2.1 4 I ia I ij i !I j i A&VO o iAU o AwronO a~~~~~~~~ 9 m c 0 CY r CY - coo o(0 c to 7CY . 0 I- o aO! _9 X t 8 0 0 cY I & § , Fiur§ : ildlnr I -U Figure B-26: Pressure Calibration of Prosthesis 43; Transducer 9 195 I r I I I v2' S. I I5 I22' F I. 6 I 9a eS a If - I I 29! I AW" AUnDo AiLOvw m 0 a C 0 e 0 8 ai og I C o II C, C ESc Rc 0 O O C5 04 w Awu'lnO X - 8 8 -§ 8 w 0 rAU'dlno Figure B-27: Pressure Calibration of Prosthesis 43; Transducer 10 196 I"i I i FI a I fi ig , i G 3 la i c j. i AUDIOM AUsnr AbDbeO 00 0 N O 0 0o co 0 C 0i I: ~o o. g 8 I- ut up 0 - 0 0 0 0 cmJ o o 8 co mwlndlno §8 &g Cq 8 C O a 0 w CYJ m'lrnlo Figure B-28: Pressure Calibration of Prosthesis 43; Transducer 11 197 tL i I -I s .1 I. ii /, I; I 4i i II }2 5 0raaWo AIuclo AL0ndnO8 Juo'v R 8 cg 00 O o a o a= as O C , co . 8 I Y 0 C 0 26 (D 5: C is b-0 oN 0 C O) E CMn ) Cyl _ Figure B-29: Pressure Calibration of Prosthesis 43; Transducer 12 198 I I I .a JE 3 Ia .. i i 5 I I I .- A& - M&rdo Q. AUf1 9 R 0 CY 00 co Ias I; ai C) o U* toI40 O _ 0 O co Nh 4 C cl . 1L l)7 5 Q 8CY e%' -Wld'O -° O Figure B-30: Pressure Calibration of Prosthesis 43; Transducer 13 199 8 e 200 Appendix C Temperature Calibrationof Pressure Instrumented Prostheses Calibration tests prior to the implantation of prosthesis 33 indicated that transducer output was dependant on temperature, via a dependance of the transducer offsets on temperature. Transducer gains were found to be independant of temperature. Ac- cordingly a series of tests to calibrate the prosthesis thermally were done. These tests were carried out on both prosthesis 33 and prosthesis 43. Prosthesis 43 additionally contains a thermistor internal to the prosthesis but in a well similar to the pressure transducer wells. Thermal calibration tests also were done for the calibration of this thermistor. Thermal calibration tests were carried out in a fluid filled bath, with the water heated and circulated by a Thermomix 1441. A diagram of the equipment used is shown in figure C-1. The fluid bath temperature was elevated and held at a value (independantly measured with an accuracy of 0.1 °C) for 20 minutes prior to data collection at each temperature. For most of the data the heater was turned off during the actual data collection; comparison with tests in which it was left on indicate that the heater status (off or on) had no effect on the data. Data was also taken while reducing the fluid bath temperature, this was done by exchanging some of the heated water for cooler water, which was difficult to control and as a result there is less information on transducer behavior during temperature reduction. 201 (9.) T14 e M A L. CAA Be ATIoJ SF,-Tu P Figure C-1: Equipment for thermal calibration of Prosthesis 43 202 Thermal calibration in the fluid bath was done on three days for prosthesis 33. On the first day data was only taken for increasing temperature, from 29.2 °C to 41.1 °C (84.5 F to 106 F). The second day on which data was taken the temperature was raised from 24.2 °C (75.6 F) to 45.5 °C (114 F) and lowered to 26 C (78.8 F). The third set of tests was done between 25.8 C (78.4 F) and 40 °C (104 F). When implanted in the human body the temperature is fairly constant, it was expected to be 37 °C (98.6 F), and has been measured in the second subject at 38 °C (100.4 F). Figures C-2 to C-11 show the results for working transducers from all thermal calibration tests and the best fit line and quadratic through each set of means. A linear estimate was used. Table C.1 presents the slope of the line fit to each set of data and to composite sets of data, also the gain found prior to implantation. Table C.2 presents the difference in pressure estimates that would result from using ez vivo calibration data. These differences are independant of the pressure measured, as the temperature only affects the zero-pressure output from the pressure transducers. Calibration of prosthesis 43 with respect ot temperature was done using the same equipment and procedure used in re-calibration of prosthesis 33. Fluid bath tests were done on two days; on the first day the temperature was raised from 72 F to 107 F. On the second day tests were done the temperature was raised from 73 °F to 106.7 F and then decreased to 75 F. Figure C-12 shows the results from both days of testing for the thermistor in prosthesis 43. These tests indicated that the thermistor output was well represented by equation C.1, y = 0.3391 F 2 - 2861. (C.1) which is also shown on figure C-12, in which y is the thermistor output in corrected millivolts and F is degrees Fahrenheit. Figures C-13 through C-25 show the results of the temperature calibration tests for the pressure transducers in prosthesis 43. Table C.3 lists the relationship between transducer offset and temperature that was found from these tests. Equation 4.2 indicates the use of these.factors. Another set of tests was done in the fluid bath with prosthesis 43 determine how rapidly the 203 Transducer Feb. 20, up Feb. 22, up Feb. 22, down Feb. 22, all Mar. 1, circ. Mar. 1, still Mar. 1, all ex vivo pre-implanta 1 -45.4 -42.7 -39.2 -41.0 -43.3 -42.3 -42.5 -41.8 -2.67 2 -4.53 -4.57 -7.3 -5.54 -6.47 -4.32 -5.25 -5.38 -8.45 3 -24.2 -22.9 -25.2 -22.9 -22.7 -21.3 -21.8 -22.5 -20.15 5 6.18 5.87 5.52 5.74 3.07 7.24 5.21 5.23 2.52 7 13.0 12.5 11.7 11.3 4.59 12.1 8.41 11.2 0.48 Transducer Feb. 20, up Feb. 22, up Feb. 22, down Feb. 22, all Mar. 1, circ Mar. 1, still Mar. 1, all ex vivo pre-implantb 9 -31.3 -34.8 -30.2 -34.1 -42.4 -39.8 -40.8 -36.7 -32.95 10 -103. -101. -107. -102. -100. -96.6 -97.8 -100.0 -96.2 11 23.5 22.6 24.8 23.7 18.8 24.5 21.7 22.9 16.13 12 5.68 3.17 4.20 3.42 -0.332 2.83 1.42 2.68 3.925 13 -40.2 -40.7 -38.5 -39.5 -43.0 -40.5 -41.5 -40.4 -37.3 Average of gain above and below 37 °C bAverage of gain above and below 37 °C Table C.1: Gains of prosthesis 33 pressure transducers offsets with temperature Transducer AP/C 1 2 3 5 7 9 10 11 12 13 0.54 -0.027 0.026 -0.029 -0.118 0.043 0.033 -0.049 0.009 0.029 [MPa/°C] AP/°C [psi/°C] 78.52 -3.86 3.81 -4.17 -17.08 6.29 4.85 -7.15 1.37 4.18 Table C.2: Pressure estimate difference for prosthesis 33 using ex-vivo temperature calibration 204 0 -1 - I --· · - - - · I - - U', / c5 6 0) 6) I/ / 0 10 -/'O/ '/,' E 2 I- ID O a // h.. co a . 0C WOS/ IO K (U E I0 . / // ,// ttw F V-a / -a Q T 0 ~~~I,~~~~~~~~ E 0. ;0) U C) :O a> CI CI /, , . ./0g O / lx / ' II II o I 8 8 8 8 Ij I AuJW'lndlno Figure C-2: Temperature Calibration of Prosthesis 33; Transducer 1 205 I 1 1 I .~~·. 1 ._-1 7 , 1 1 · r r 1. -·. ·. I, -, --- 1, ·, I. - I/,,, // i'/ i, Ln ,/ ,o - 4o ~~~~~~~~II~~~~I I . ,i a) I C I. I ,o 0L 0 '''~ A0 )o & :3 0, 0 0 i- 0 0 ii. cwd i/ ,/ I I I I i/j .I I I I 10 AW3o'ndno Figure C-3: Temperature Calibration of Prosthesis 33; Transducer 2 206 E (2 C9 CL I.) a I A A 0 & L I ,, ,,, 1 -1 ,,,, ............................ I -r , Crr~ r ·-w . 1l ! · --· · _ _ ~ ~~/ / // co .0" a cu 0 9' e / "// a) E i 0t'j/i - E Q) 0- + ~~/*j / cm .. . . , , , , o , , _, , , > II tn co ^w'lndnc Figure C-4: Temperature Calibration of Prosthesis 33; Transducer 3 207 -·----- ------ · ··- · · -- · -- 'S oo\o \ tol 0 15 C 0 a ,\\ \'," V.. \', 0 - : S. \'o 0a o- 0'!,,, E E C.) *0 C, (1) CI 0 d:~~~~~~~~~~L 1! 1.. 09 I uT ?i 0 I II, ~5 x Ic \ I I I I . . . I U9 . . . . I , - 8 ,. ' .. .I sr O+ i\i +-I ~+ , )5 . 8 AWD'lndfno Figure C-5: Temperature Calibration of Prosthesis 33; Transducer 5 208 ! I · ___ _ r W y \, \\\0 0 \\\0 0 c C) 0 13 \\ \\, \ \\ _ , -. C LI n I. 0Q :3 Ca E a,. E C,- 0**. L ad a) 0 C, 10 co X a a- I \ O lo ii+C II -:+-N N ++ + x I I \ 8 l co I 8I . I . \ \. I ^AWu'1ndlno Figure C-6: Temperature Calibration of Prosthesis 33; Transducer 7 209 a, 0 ,D iC Q: a) - E 'I- C) C * 0 cm a~~~ § 8 0~~ T-6~~~1 I AWu1'lndlno Figure C-7: Temperature Calibration of Prosthesis 33; Transducer 9 210 --r - I I 1 I -- I I 1 -. · ·I I I / I // / // ! // */ (a I/ Ca , I' C c .0 0 Cu 1 c) of/ / I1. 41 a E a) ,I, I- 4 C) CM InK ' 8 In L: + ,'I I /1 I 8 I II 2 I 0 0cm c AWuo'lndlno Figure C-8: Temperature Calibration of Prosthesis 33; Transducer 10 211 . , ' ' '' "II . .. , - U-5 ....... ,_ - \ \\U \ \\ \.\) a0 \\0 c O. O.~~~~~~ ka~~~~° 0 3 Co L_ Q. E $ E (2 U _ At_ _ ia L 0 V +x+ 0 t.- 0I = I 4!M U II I I _ s ~ ~ii I 8 , - ~ I ~ ,\. \\\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \I \ .~ __ L II L * N l \ ....... ° 8 to W,~k i[~~~~~~~~~- 8 AW3'lndlno Figure C-9: Temperature Calibration of Prosthesis 33; Transducer 11 212 - - - -- - - - - - - - I \ 0 I \ \\\\ \ C 0 00 ' CT o 0= 13 .0 C7 O a \Q\ 8 O \ 8 Ut = i U I I I I \\ v· !5 E CO ID X a t _-: L 0 I- 0 \\, E 0 I- aE 0 x+ O 0'\ 00 0 C) L C) \" II i 0C i II I I.. ., .. I\ I I \ · J ......- j O 0 CN I ,ll- AWuo'lndlno Figure C-10: Temperature Calibration of Prosthesis 33; Transducer 12 213 cr 0Cu C) CU 4. 0CO . a E al :r I- 0 8 3 0 8 8 (9 1. 8 (9 AW''lndlno Figure C-ll: Temperature Calibration of Prosthesis 33; Transducer 13 214 Table C.3: Thermal adjustment to transducer offsets for Prosthesis 43 Transducer ai cj 1 2 -0.0308 -0.275 -153 1009 3 -0.412 22 5 6 -0.150 0.201 555 359 7 8 -0.113 -0.0564 150 251 9 10 11 12 13 -0.2899 -0.4408 -0.177 -0.0815 -0.0722 314 695 -159 1068 -175 thermistor would respond to changes in temperature. The results of this series of tests are shown in figures C-26 and C-27. Additionally, prosthesis 43 was subjected to pressure calibration tests at both room temperature and close to body temperature (38 C) to determine if transducer output gain with respect to pressure would be affected by temperature. The gains for the pressure transducers in this prosthesis, like those in the earlier instrumented prostheses, were found to be unaffected by temperature. 215 _ _ %-O V- C0) 0- tn cu a) E a) CD U- w E 4- a).. CZ E -o 0 E a) C, cu C a) c, E a) oo o 0 AWo'lndnln Figure C-12: Thermistor calibration 216 00 0 O A - = - w~~~~~~~~ - 8 !( C 8 cI iI Is~ i! a i p S 8 ? 89 8 9 o O 8 8 e t0 . C oo S_C S Lo iI- al1 'L le- 2 0 0o 0 8 ^Au'ndW AWoldl Figure C-13: Temperature Calibration of Prosthesis 43; Transducer 1 217 0) - 9- 8 i 8 .I L E i4 8 l OOD e- /q M E 0 Q H~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > AWO'1ndi 0o AwUO'vndlO aI p 8 1 $t 9 IR IU) I- 8 .9 0 5 ° 8°§ 8 A'I1=10 ° E A='dcO ° Figure C-14: Temperature Calibration of Prosthesis 43; Transducer 2 218 0 - ii U. I 8 i C E I I i // Auo'fIfO ~auWorfd Pr~~~~~~~~~~~~~~uon Into o Mr -~~~~~~ - 8 0I- 46 ILL 14 I', *1 I u t ,I I e! I- Si a a C 2 0 C P a 2 r N Afdfo AwJuo Figure C-15: Temperature Calibration of Prosthesis 43; Transducer 3 219 _ O U. f' a a laZ aL X Ij1.1 )n u v 0 rn N N.O Mwud A=V~f~nl . o _ O 142 C 0 LL 9 C C ii z I t: U. I *1 iW ! I * . I * S0 e g S 0, 9 + '_ , pi - a , . U U 4i t U a en F. In CY A 0 3-.- 3-. . 0 C Awvwm W'Vwld Figure C-16: Temperature Calibration of Prosthesis 43; Transducer 4 220 . r x 8 I a 4i' J I. 1 II-. 8 I 8 p I I § § & I § § § %WAInOM AWOL'vwm 0 a 8 8 is eii I I-n aa I S p 8 P Fg rCnioB 1 TemrAu A T4 o Figure C-17: Temperature Calibration of Prosthesis 43; Transducer 5 221 elA I r. f 8} I Mj 9 J a p P I 9 9 8 & 8 E uo~nong t0oO 8 8 a IL id -id 8 e I- oa 8 F o 8 8 F AfuP'vO awOu l Figure C-18: Temperature Calibration of Prosthesis 43; Transducer 6 222 o o I S I i 'it a 0 0 b o §8 I MII)PdlO Aui1vog 0 a %d I -aa i. Ii . I- a 8 o o :) Ado Aucdnol Figure C-19: Temperature Calibration of Prosthesis 43; Transducer 7 223 elA i'- I. i- 9 1t I i 8 i6 1 8 2 P AW'Ind3o O ^A0O 0 a 8 8 o I - g a X e 2 U. I I- pa 2a rB 8 Figure C-20: Temperature Calibration of Prosthesis 43; Transducer 8 224 o 2 - I-. I- U. 0 C I (6 9- pa 2 il a IL 0 _1 S P a S S 0O- u. 8 8 0 u, C Ul. o, i I - X S9¢0' ?Igr 0 0 §- e8O 8 Fuguel-O - § u0aisnl e Figure C-21: Temperature Calibration of Prosthesis 43; Transducer 9 225 o O 8 I- 8 M ~co A. U. 4a 9IiL ID 9 44e 21 . .9 a6 - o 1 c 2 E2 2 2 8 2o § AWUO'VldlflO § ° 0 Au'VO nO 0 0 8 8 (-, IL c s4 IL 51 aS S I- 12 K p o eAUID iin oA - n'd Figure C-22: Temperature Calibration of Prosthesis 43; Transducer 10 226 a e-1 I' 8 , C - LL iI i:C M - Xi_ P - a U. 2 C 8 8 8 O - 0 AUIdftlQo AU'VUdMn 0 8 _ u) U,0 C C a 0- (3 0L I CtD E La F- I- CDl 2 8 C T ep P te 0o 8 AunHB22 uaWOrnDO Figure C-23: Temperature Calibration of Prosthesis 43; Transducer 11 227 o o- I I, FU. U icb' d u cu a R Au3l7rlnO ALuOWVO o 0 w an c u. r iYi c ICu e R i I It 4 o 0 Fig ure Calbration of Prosthsis 43;Transducer 12 Figure C-24: Temperature Calibration of Prosthesis 43; Transducer 12 228 0 en x lu_ *1 a I 0- R If i 9 8 &a LI AWuO'ltn AWI*VdM O 0 o ad In i C i I I a a 0r8 o 0o 0 R 8 Jundo w=a'lO AUJOV4Vhn Figure C-25: Temperature Calibration of Prosthesis 43; Transducer 13 229 0 In 6e 'eiJnleedwel. LO 00 N C Mo uM _ __ LO 0 C> 60. =3 Nr 40-' a) Cu 0 0 E - a) 40-, 1 (P ci Q 0U 6 40-' w 0. E 0 C e C 8 ) -' C a) at) 00 cm - C 0 O CM Ln) 0 CN L) I L I N I 0 0 I AWO'lndlno Figure C-26: Thermistor response to changes in temperature 230 (n el E *1= O O C) C) 0 u) 0 4) 4-. 0 C) a U) C 0 0 E c .2 C0 cM c -C 0CD C 0 O C3 L) Mv 0) cf, O4J 03 LO c'- 6ep' aJneedwejl Figure C-27: Response to changes in temperature 231 E .Iz 232 Appendix D Interface circuit between Prosthesis data receiver and the AT&T 6300+ PC The interface between the receiver for the prosthesis output and the AT&T PC used to collect data in vivo from prosthesis 43 is straightforward for the most part. The data channel and the alarm channel are routed to A/D channels 0 and 1, auxiliary input is routed to A/D channel 2, and the strobe signal from the receiver which indicates the time at which the A/D channels should be sampled is routed to the external trigger set and external convert lines and used to trigger each scan of the channels being read. However, there is also a simple circuit that works in concert with the counter/timers on the A/D board to decrease the data collection rate from the prosthesis so that data can be continously collected for longer periods of time. Figure D-1 shows the circuit diagram for the interface box. In order to take data for longer than 1 second(with prosthesis 43) and not overrun the DMA buffer the frequency at which data is taken needs to be sloweddown. The A/D channels are sampled in sets of 32 to do this and still collect all transducers at essentially the same instant in time. Thus, the first reduction in data samplingrate is to alternate between collecting 32 samples of each A/D channel and skipping 32 times the A/D channel should be sampled. This is done by counting the channel-sample 233 PC ADAPrrR - /P P4SotrL/f$/$ f O.1Pw MALI (/14. l ir pEsSUIKtDATA C. z) SYvuC/IALA AR C-1) AUX-MU) .4) SYNC s Isp IS M .3*) I Mr '41,, bMrst5 !' Figure D-1: Circuit Diagram for the Interface Box 234 indicator, a strobe signal, using one of the counter/timers on the A/D board. The circuit in Figure A.3. suppresses the transmission of this strobe to the A/D sample trigger during the times when data shouldn't be collected. Table 4.4 and 4.5 show the reduction in data sampling rate required when taking data for a given length of time. 235 236 Appendix E Initial Processing of pressure data The procedure to be followed to take pressure data on the PC is extremely simple. the connections which must be made in order to correctly input data Figure BMshows to the computer. One program is run, PCOLLECT.EXE; written in C. Figure E2 shows a sample run through this program. The number of channels to collect is determined by whether any auxiliary data needs to be collected, such things as Selspot synch, forceplate forces, goniometer measurements. With no auxiliary data only 2 channels need to be collected, otherwise 3 channels must be collected. All data and the data directory is stored in ASCII so that it can be accessed more readily and transferred between machines more easily. The filename format that has been used includes the date data was taken and the file number, as mmddyy##.dat, where m stands for a two letter abbrev. for the month, d is the day of the month, y is the year. The programs used in data collection can be found in [8]. Processing of the data has a several steps. Three programs are used in the first stage of processing. The first of these is LONGDAT2.EXEwhich has as output a file with each frame of data, pressures in psi. The program AVGZERO.EXE must be used to process the zero data for the day if in vivodata was taken, the procedure followed is to run longdat2 on the zero data, then avgzero on the zero data, then use the results of that processing in longdat2 when processing the rest of the data for the day. Finally a program called AUX20D.EXE is used to turn the results into a format that can immediately be plotted. Figure E-3 shows a flowchart of the 237 data natiorI Figure E-1: Equipment Set up for Data Collection 238 E:\PESS43>pcollect Enter the number of channels to sample: 3 Enter the length of time to sample: Please hit G 1.5 hen the prosthesis is powered up: G (fli.pswitch on interface box to start data collection) Unplug the prosthesis and type C: C (unplug prosthesis if it is prosthesis D:Nj? I Do you want to display the data Do you want to save this data 33) D:N]: Y Enter the prosthesis number: 43 Enter the complete filename: jn089303.dat Enter the short filename: jn089303 Enter the data directory name: jun0893.dir Enter the test description (30 letters or less): Free speed gait Do you want to take more data D:J? E:\PRESS43 Figure E-2: Sample run through pcollect.eze 239 processing procedure. The programs used in processing are printed in [8]. The programs used to obtain acetabular locations of pressure measurements are also available in [8]. Three different programs exist, one for processing data from prosthesis 43 and two for processing data from prosthesis 33. Data files from prosthesis 33 were saved in a slightly different format from 1986 on, thus necessitating different programs to read the files. A flowchart of the programs used to obtain acetabular locations of pressure measurements is shown in figure E-4. The names of the executable programs are LOCATE43.EXE for processing data from prosthesis 43, KINE33.EXE for processing of early data from prosthesis 33, and KINE2.EXE for processing later data from prosthesis 33. E.1 Programs for collection of pressure data PCOLLECT.C / LONGIO.C Data acquisition programfor use with triggered$/ / * data collection. Set up for prosthesis data. / This version to collect longer data sets by /* ignoring some of the triggers. (Lower sampling rate)*/ Mar. 8, 1991 */ '/ $/ #include <stdio.h> #include <stdlib.h> #include <conio.h> lo #include <time.h> #include <pio.h> void ad_setup(void); void clk setup_2(int,int, int, int); int dma_setup(int *,int); void press display(int*, int, int); void makelong (int *, int, int, int, float, float, int, int,\ long,long,long, long); 240 - r---------------- Data File - I I I I . i Find Frame-Synch I ,, , I I Check Alarms I I Find mean temperature from thermistor data I I I I I f I .- - __ Use temperature, information Find in vivo zero offsets , ~1 channels, calibration data - I L Restina data Pressure Data File Figure E-3: Initial Processing Procedure 241 Representation of Pressure Data on the Acetabulum Select Data Set Select View A .. ,l' Get transducer locations F Read kinematic data file 1 f I~~~1~~~ Get transducer locations Smooth joint angles from early data _I l~~~~~~I Transform from transducer locations to acetabular ,E Read Pressure Data file ... V Smooth pressure data from prosthesis 33 Write output files Figure E-4: Procedure for obtaining acetabular locations of pressure measurements 242 20 int varl[D ARRSIZE]; main(){ int *pvarld; register i; register j; int idelay = 0; ao int n = 0; extern int varl0; int er; int count = 2; int nsamp = 99; float stime = 0.1; float samp,eff freq; unsigned outl; unsigned out2; unsigned lowmux; 40o int arr times; int dmastat,adstat,cllk stat,mux stat; int cur addr; int check; int byt_count = (count * nsamp * 2); int trig_count, trigskip; int nrep = nsamp-1; long powtime,start time,end_time,off time; char reply[5]; char cwait[2]; char contin[5]; contin[O]='Y'; 243 so for(i = 0; i < DARRSIZE; i++){ varl[i]=0; p_varld = &varl[0]; 60 while(contin[0]== ' 'II contin[O]=='y'){ / Get input of the number of delay cycles, # scan cycles, # channels */ printf("Enter the number of channels to sample: "); scanf( "%d",&count); printf("Enter the length of time to sample: "); 70 scanf("/. "f,&stime); if (count > TOTCHAN){ count = TOTCHAN; I low mux = 128+count; samp = stime*count*P43FREQ; /* Only figuredfor 43 / /* Not working correctlyhere, perhaps only one elseif is allowed? so Could use switch, would bejust as convenient */ arrtimes = (samp / DARRSIZE); switch (arrtimes){ case 0: /* printf('This data set could be collectedwith trigio\n"); printf("which would result in a faster sampling rate.\n"); printf("Continue? [D:N l); contin[O] = 'N'; so scanf("%s",contin); if (contin[O]=='nl lcontin[O0== 'N') ezit(0); 244 ,/ ttig.skip = 0; triLcount = 32; nsamp = samp; eff freq = P43_FREQ; break; case 1: trig skip = 32; trigcount = 32; 1oo nsamp = samp/2.; eff freq = P43_FREQ/4.; break; case 2: trig_skip = 64; trig.count = 32; nsamp = samp/3.; efffreq = P43_FREQ/6.; break; 11o case 3: trigskip = 96; trig_count = 32; nsamp = samp/4.; eff freq = P43_FREQ/8.; break; case 4: trigskip = 128; trig_count = 32; nsamp = samp/5.; eff freq = P43_FREQ/10.; break; case 5: trig_skip = 160; trig_count = 32; nsamp = samp/6.; efffreq = P43FREQ/12.; break; 245 120 case 6: trig-skip = 192; trig.count = 32; 130 nsamp = samp/7.; eff freq = P43_FREQ/14.; break; case 7: trigskip = 224; trig_count = 32; nsamp = samp/8.; eff freq = P43_FREQ/16.; break; case 8: 140 trig_skip = 256; trig_count = 32; nsamp = samp/9.; ef freq = P43_FREQ/18.; break; case 9: trig_skip = 288; trig_count = 32; nsamp = samp/10.; eff freq = P43_FREQ/20.; 150 break; default: printf("Programnot prepared for this length"); printf("data set. Edit longio.c.\n"); exit(O); break; nrep = (nsamp/count)-1; bytcount = nsamp*2; /$ 16o printf ("%;z\n",byt_count);*/ check = 0x80 + count; 246 /* Ask user to wait until prosthesis is plugged in*/ printf("Please hit G hen the prosthesis is powered up: "); dof scan'f("%s,"cwait); while( strcmp(cwait,'g' )== 0); 170 /* Get the time here and save it */ time(&powtime); / Initializethe board*/ INIT(&er); if (er!=O){ printf("Error during initialization }1~~~~~~~~~~~ /h \n",er); ~~~180 /* Use the new setup routines / /* Order:AID Counter Chip DMA controller */ adsetup(); clk_setup_2(MULT, count, trig.count, trigskip); dmastat = dmasetup(p_varld,byt_count); i = nrep; /* 190 printf("i = %d\n", i);*/ time(&starttime); / * Use clock status as clue to whether or not have collecteda scan $/ / * Found I need to set up two do...while loops to do this correctly */ out1_l= outp (PORTCLK, 0x3c); while(i > 0){ 247 do{ 0zoo clk stat = inp(PORTCLK); while ((clklstat & Ox20)=-- 0); do{ clkstat = inp(PORTCLK); while ((clk stat & 0x20)!= 0); outl = outp (PORTMUX, ADMUX_1); 1 -- ; 210 } / * end the sampling loop */ / * Make sure have last sample */ do { clkstat = inp (PORTCLK); w while ((clk stat & 0x20) != 0); 220 time(&end time); / get the time here too, and also get it when prosthesis is unplugged */ printf("Unplug the prosthesis and type C: "); dof scanf("%s",cwait); } while( strcmp(cwait,'c' )== 0); time(&off time); / * disarm counters */ 248 230 out l = outp (PORTCLK, OxDF); /* Displaythe data */ printf("Do you want to display tbe data?"); 240 scanf("% '",reply); if (reply[O] == '' reply[O] == 'y'){ press display(pvarld, nrep, count); } /* Here ... Need to write the data to a file, and enter the file name in a data directory */ printf("Do you want to save this data? [D:N] "); scanf("%s",reply); if (reply[O] == 'Y' 2so0 J1reply[O] == 'y'){ /* Need to add effjreq (effective sampling rate) to the output file */ nrep = nrep +1; makelong(p_varld, nrep, count, MULT,\ stime, eff fieq, trig_skip, trigcount,\ pow time, starttime, end_time, off time); 260 contin[O]= N'; printf("Do you want to take more data? D:N] "); scanf("% ",contin); } /* End the outside loop ... while(contin ... CLK.H 249 */ /' This file contains definitions for the counter timer chip on the RTI-815 board. */ #define GLOBAL / For referenceinga common quantity */ #define SEMIGLOBAL static #define IMPORTextern #deflne AD_BASE 0x350 / Base addressof A/D board */ 10 #define PORTSB 0x350 #deflne COMCLK 0x35D #define DATCLK Ox35C / * Commands to enter for counters 4 and 5 (Put in header file later) */ Disarm counters 4 Li 5 */ #define DISARM45 OxD8 / #define DP4 MODE 0x04 / Data pointer to 4, mode register */ #define DP_5MODE 0x05 / Data ptr to 5, mode reg */ #define LOW_MODE 4 0x21 / * Low byte of counter 4 mode (MODE E) */ #define HIMODE_4 Ox8b / High byte of counter 4 mode (MODE E)*/ #define LOAD4 0x48 #define LOW_TOGGLE_4 #define LOWMODEJ_5 #define HIMODEJ_5 OxE4 0x62 20 / Load counter 4 with load reg*/ / Clear toggleout for counter 4 / /* Low byte - MODE J (repetitive counts)*/ 0x00 #define LOW_MODEL_5 0x62 / * Low byte of MODE L ... reloads*/ #define HI MODEL_5 OxF5 / Hi byte of MODE L ... same as in SCAN */ #define LOW_LLOAD OxOl1 / Loadedinto Load reg of 5 in MODE L */ #define HILLOAD 0x00 30 #define LOW LHOLD 0x01 /* To load in hold register of 5 in MODE L */ #define HILHOLD 0x00 #define #define #define LOAD 5 0x50 / * Load counter 5 with load reg */ HI TOGGLE_5 OxED / * Set toggle out high for 5 */ ARM_5 0x30 / *ARM counter 5 */ 250 OxF5 / * Step counter 5 */ #define STEP65 #define LOWTOGGLE.5 OxE5 /* Clear toggle out for counter 5 */ 40 /* Commands for counters 1 & 2; Used in clk4setup.c--for taking data slower */ #define DP 1 MODE #define LOW MODE_1 Ol01 /* Set data pointer to mode of cntr 1*/ 0x25 / * Mode E for counter 1; active low TC pulse*/ #defline HIMODE.1 0x81 /* Gate w/active high; Source is src 1 */ #define LOAD_1 0x41 /* Load counter 1 ( use LLOAD defnd above) */ #define 0x02 / Set data pointer to mode of cntr 2 DP 2_MODE #define LOW MODEJ2 0x62 '/ / * UseModeJ w/ TC toggled*/ #define HI MODEJ_2 0x01 / * Source 2 is same as I (trigger/strobe) */ #define LOAD_2 0x42 /* Load counter 2, calc quantities in prog */ #define ARM 2 0x22 / *Arm 2 so can count it down '/ #define LOW TOGGLE 2 OxE2 / #define STEP_2 #define ARM_1245 #define DISARM_1245 60 Start 2 out low */ OxF2 / * Count down in program */ 0x3F / Arm all counters being used */ OxDB /* Disarm all counters being used */ _I PIO.H /I* pio.h ... Contains some definitions used in setting up the RTI-815A, the DMA controller on the AT&T 6300+ and the Counter/ Timer chip (AM9513) on the AID boardfor data acquisition of */ pressure data. #define GLOBAL #define SEMIGLOBALstatic #define IMPORT extern / * used to define a semiglobalvariable*/ /* used to refer to a globalor semiglobalvar*/ 251 0o / * * referenced elsewhere */ / * Some definitions specific to AID board,Pressure I/O */ #define D.ARRSIZE 21752 / #define P43_FREQ 8000 #define P33_FREQ 4000 #define TOTCHAN 8 / * Currently RTI boardconfiguredfor 8 */ / #define MULT 25 As big as possible - 21752*/ differential channels / /* Time in microseconds betweenAID channel samples */ 20 #define PORTSB 0x350 /* Base address of RTI board- Status byte */ #define PORTCF 0x359 / Clearflags byte */ #define PORTCLK 0x35d /* Clock control/status byte / #define PORTMUX 0x351 / * Muz and Gain byte */ #deflne PORTDMSK OxOa /* Mask byte -- DMA controller */ #define MUXTEST Ox80 /* Muz test */ #define AD_BASE0x350 / * Base addressfor RTI-815 */ #define ADMUXI 0x80 /* Muz entry for DMA scan, gain of 1, start at O/ #define ADSTAT 0x08 / * Get status set to go */ 30 #define F_CLEAR 0x19 /* Any write to BASE + 9 clears the flags */ / * DMA controllerPorts, see A TJT Device Drivers */ #define DMA_COMM 0x08 / * Status(R)/command(WR)byte */ #define DMA_MASKOxOA/ * Single Mask $/ #define DMA MODE OxOB /* Mode byte */ #define DMA_CFF OxOC/* Clearflip/flop $/ #define DMA_ADD10x02 / Channel 1 address(WR)/current address(R) */ / 16-bits */ #define DMACNT1 0x03 / * Channel I # of bytes to transfer */ /* 16-bits */ #define DMA PG1 0x83 /* Channel I page (highest nibble of 20bitaddress)*/ 252 40 ADSETUP.C /* This file contains a subroutinefor setting up the RTI-815 for DMA transfers, gain of 1, starting at channel 0. The procedurefollows that done in SCAN (from ADI) prior to setting up the clock and DMA controller */ #include <stdio.h> #include <dos.h> #include <memory.h> #include <conio.h> #include "pio.h" 10 void adsetup(void){ int out_l; out_1 = outp (PORTCF, FCLEAR); out_1 = outp (PORTSB, ADSTAT1); out_l1 = outp (PORTMUX, ADMUX_1); 20 DMASETUP.C /* This file contains setup routines for the DMA controllerfor use with the RTI-815 board */ /* See AT&JTDevice Drivers section of System Programmer's Guide */ /* For the ATFT 6300+ #include #include #include #include / <stdio.h> <dos.h> <memory.h> <conio.h> #include "pio.h" 10 253 int dma setup (int *p_dat, int tot_bytcount){ int dmast; int out_l; int d page,d addr; int low daddr, hi daddr; int lo bytcnt, hi byt_cnt; 20 long long_addr; / * Start by selecting channel, turning things off * out_l = outp (DMAMASK, 0x05); /* Set the mode ... Don't change, use what was used in SCAN */ /* This is single transfer, increment address,no autoinit, */ */ /* write, using channel 1, 30 out_1 = outp (DMA_MODE, 0x45); out_l = outp (DMA_CFF, 0x45); /$ Now want to get the address set and enter it */ longaddr = FPSEG(pdat); long_addr= longaddr << 4; longaddr += FPOFF(p_dat); d page = long_addr >> 16; daddr = long_addr & 0x0000FFFF; 40 low d addr = d addr & 0x00ff; hi d_addr = d addr & OxFF00; hi daddr = hid_addr>> 8; out_1 = outp (DMAADD1, low_daddr); 254 out_1 = outp (DMA_ADD1,hi daddr); out_l = outp (DMA_PG1, d.page); out_1 = inpuw DMA ADD1); outl so = inp (DMAPG1); /* Nezt thing, Enter the number of bytes to transfer (-1) */ / * Version A ... Enter the total number of bytes to transfer */ tot byt count -- ; lobytcnt = totbyt count & Ox00ff; hi byt cnt = tot_bytcount & OxFF00; hibytcnt = hi byt cnt >> 8; outl = outp (DMACNT1, o bytcnt); outl = outp (DMA CNT1, hi byt cnt); so /* Now, get status to send back, and enable transfers on chan 1 */ dma st = inp(DMA_COMM); out-l = outp (DMAMASK, Ox01); return(dma st); CLKS.C /* This file contains setup routines for the counter timer chip on the RTI-815 board. This version allows longer data sets to be collected. This version uses counter 3 as well as 4 & 5 $/ #include <stdio.h> #include <dos.h> #include <memory.h> #include <conio.h> to #include "clk.h" 255 #deflne DISARM ALL Oxdf #deflne LOWMODA_3 0x02 #define HIMODA3 0x00 #define DP 3.MODE 0x03 #define LOW_MODEE_3 0x22 #define HI MODEE 3 0x8b #define LOAD 3 0x44 #define LOWTOGGLE3 Oxe3 #define ARM_3 0x24 #define HI TOGGLE_3 Oxeb #define STEP_3 / 20 Oxf3 This subroutine sets up the counter/timer chip (an AM9513A) to do scans of length specified by user Assumes that INIT was calledprior to calling this routine. This version sometimes ignores triggers -- lower sampling rate but can collect longer data sets. so See data sheet for information / void clklsetup_2 (int interval, int scancount, int trig_count, int trigskip){ int out_l; int i; 40 int low-interval,hi interval; int lowsccount,hisccount; int low trigcount,hi trigcount; int low trig_skip,hi_trigskip; /* Enter the commmands -- First disarmall counters$/ 256 out l = outp (COM CLK, DISARMALL); so /* Set up so can do either trigio or longio mode 12/4/91 */ /* This is new, (10/16/91) Hi toggle $ so compatiblewith longio and circuitry. May need to disarm S too */ if (trig_skip == 0){ out_1 = outp (COMCLK, DP_3_MODE); outl = outp (DATCLK, LOW MODA_3); outl = outp (DATCLK, HI_MODA.3); out_l = outp (COMCLK, HI_TOGGLE3); so } else { /* Set up 3 to take place of cnter 1*/ out_l1= outp (COMCLK, DP_3_MODE); out_1 = outp (DATCLK, 0x62); out_l = outp (DAT CLK, 0x13); /*I think want trig_skip in LOAD ( the one that gets counted downfirst ) * / and tig_count in HOLD. Could try both ways */ low_trig_skip= trigskip & 0x00ff; 70 hitrig_skip = trig_skip & 0xFF00; hitrig_skip = hi.trig_skip >> 8; out_l = outp (DAT CLK, low trig_skip);/ *Load counter 2 LOAD*/ out_l = outp (DAT.CLK, hi.trig_skip); low_trig_count= trigcount & Ox00ff; hi trig_count = trigc'ount & OxFF00; hitrig_count= hitrigcount >> 8; out_l = outp (DATCLK, low_trigcount);/ *Loadcounter 2 HOLD* out_1 = outp (DAT_CLK, hitrig_count); out_l = outp (COM_CLK, LOAD_3); out_l = outp (COM_CLK,LOW_TOGGLE3); 257 so / * Don't count down this counter, used to, but clearlydoesn't work.... looked at scope output from circuit */ / * Set up counter 4 to countdown continuously over interval */ 90 out_l = outp (COMCLK, DP 4_MODE); out_1 = outp (DAT_CLK, LOW_MODE.4); out_l = outp (DAT_CLK, HI MODE_4); / * need to split up interval into high and low bytes */ low interval = interval & 0x00ff; hi interval = interval & OxFF00; hi interval = hi interval >> 8; outl = outp (DATCLK, low interval); 100 out_l = outp (DAT_CLK,hi-interval); outl = outp(COM_CLK,LOAD); out_l1= outp (COM_CLK, LOW TOGGLE 4); / * Set up counter 5 to countdown over scancount */ out_l1 = outp (COM CLK, DP_5 MODE); 110 out_1 = outp (DATCLK, 0x62);/ * Mode L, alternates */ out_l = outp (DAT_CLK, 0xf5);/ * reloads from HOLD and */ / LOAD regs low sc count = scan_count & 0x00ff; low sccount -- ; / * Need to put number of channels- 1'/ hi sc count = scan count & OxFF00; hi sc_count = hi sc count >> 8; 258 $/ 120 out 1 = outp (DAT.CLK, lowsc count); /* Load cntr 5 LOAD */ outl = outp (DAT.CLK, hi sc.count); out_l1= outp (DATfCLK, LOW_LHOLD);/* Load counter 5 HOLD */ out1 = outp (DATCLK, HI.LHOLD); out_l = outp (COMCLK, LOAD5); outl = outp (COMCLK, ARM 5); out_1 = outp (COM.CLK, HI TOGGLE5); 130 / *Step through Load regiJter*/ / *then toggle output low*/ for (i=O; i<scan_count;i++){ outl = outp (COM_CLK,STEP_5); } / * Counter 5 armed and ready to go, counter 4 will be armed when everything (DMA) is set up */ 140 E.2 Programs for initial processing of data from Prosthesis 43 LONGDAT2.C / * Data reading and looking at program */ /$*For use with data collectedusing "longio" *$/ / Jan 27 1992 / #include <stdio.h> #include <string.h> 259 #include "pfile.h" 10o int datarray (21752]; / Shouldbe $3767 */ / 'Currently not multidimensioned because:number of AID channels changes and can restrict the ize of the data set */ /' Makedatarraya multi-dimensionalarray:sample,a/d channel and output channel as dimensions / / Set dimensions to mazimum ize ( Set for #33 -- 16 channels)*/ 20 /'#define SAMPLES #define PROSCHAN 16 #define ADCHAN 4 int datarray [SAMPLES] [PROSCHAN] [ADCHAN]; '/ datainfo *); FILE *getoutf(struct 30 int *read lfi(struct datainfo *); void convcut(int *, FILE *, struct datainfo *); void main(void) char reply[3]; int *p_arr; struct datainfo *pjinfo; struct datainfo thisdata; FILE *p-out; reply[O]=' 40 '; / Associate pointer with data information structure $/ 260 pinfo = kthisdata; / * Allow to loop through */ do { / * Load the data into an array */ so p-ar = read lfi(p_info); / * Put means, brief information into output file */ p out = get outf(pinfo); convcut(p arr, p_out, p info); fclose(pout); / Ask if want to do another file */ printf("Process another data file? scanf("%",reply); "); 60 while (reply [0] == 'Y' 1[ reply [0] == 'y'); exit(O); } r'ILE *get outf(struct datainfo *pspec){ char filename [NAMESIZE]; FILE *pout; 70 / * Information that need to get from user: Name of File to put data into */ printf("Enter the output file name: ); scanf("%s",filename); / * Start fillingdatinfo */ p out = fopen(filename,"v"); I cn'p out); so80 261 } CONVCUT2.C /* Converts raw data to SORTED ATOD VALUES. Link to readlfi.c, get4beg.c,*/ /* alarmcut.c,longdata.c*/ /$ DECEMBER 9, 1991*/ /*Modified in January 1992 so that temperatureslope not used.*/ #include 10 <stdio.h> #include <math.h> #define D ARRSIZE 32767 /* Should be 32767 */ #define ATODVOLTS204.8 /* Can I use a float? This is aid units per volt */ #define ATODMV 0.2048 /*This is a/d units per millivolt */ #define FRAMESYNC -5.29 / This is value for frame synch / #define PCHAN 16 /' The number of output channelsfrom prosthesis */ #define PCHAN43 18 /* Number of separateoutput quantities from 43 */ # iefine CALEVEL 165 / * nominal value for acceptingcal and zero */ #define CALEVEL2 215 #define VTOMV 1000.0 /* convert to my / #define MINIT 10000.0 #define ALARMCHEK OxBFFF 20 #define JUMPCHEK OxDFFF #define DISCARDHI0x8FFF #define SET HI 0x7FF #define JUMPX OxDFFF struct datainfo { 30 char name[9]; char id[3]; 262 int samp; int adchan; int mult; int trig; char time[5][12]; char descr[32]; int startoff; int frames; 40 int alarmch; int synchch; double freq; }; / * This program is for Prosthesis 43 only. */ / ezternalcode / void alarmcut(int *, FILE *, struct datainfo *); 50 void get43 begin(int *, FILE *, struct datainfo *); int *tempflux(int*, FILE *, float *, double, int, int, int, int); double linefit(int *, int, int); void convcut(int *p_arr, FILE *p_out, struct datainfo *pspec){ char blah; int chan,atodchan,scans,frames,adjust jumpedvalue; int framesize,cal,zero,startoff,oldstartoff,framepair; int i,h,n,alarmsj,alarmch,synchch,diff,nframe,data,l; int lot[32][3], *beginfile,level; double frequency; float datum,datum2; double il4zero,tl4slope,*f t14; float zerovalue[14]; FILE *zerofile; char zeroname[14]; / Get information on channel to start on from get43_begin*/ 263 60 get43.begin(p.arr, p.out, pspec); atodchan =p.spec->adchan; 70 scans = p spec->samp; startoff = p spec->startoff; begin file=p arr; framepair=scans/32; jumpedvalue=O; frequency = (p_spec->freq)/16;/*This is now the transducerfrequency*/ / *NOW START AT STARTOFF IN ORDER TO RESORT AND CHECK DATA FOR ALARMS*/ oldstartoff=startoff; so / *Loopthrough all sets of 32 values (framepairs) and reshuffle*/ for(n=O; n<framepair; n++){ for(i=O; startoff<(atodchan*32) && i<32; i++){ for (h=O;h<atodchan;h++) lot[i][h]= *(parr+h+startoff); / LOOP BA CK TO FIRST VALUE A T END OF FRAMEPAIR*/ if(startoff==(atodchan*31)&&i<31) startoff- =atodchan*31; /*OR GO TO NEXT SET OF ATODCHANNELS*/ else startoff+=atodchan; 90 / *AND CHECK FOR BEGINNING OF LOOP*/ if(startoff==oldstartoff) i=32; } /*set startoff back to its original value*/ startoff = oldstartoff; / *replace framepair with newly shuffled framepair*/ 1oo for(i=O;i<32;i++){ for(h=O;h<atodchan;h++) *(p_arr+h+(i*atodchan))=lot[i] } 264 [h]; p_arr+=atodchan*32; /*put p_arr at beginningof new framepair*/ / *MUST NOW RUN THROUGH THE ALARMCUT PROGRAM BEFORE CONTINUING CONVERSION*/ 110 alarmcut (beginfile, p out, p_spec); atodchan-=l; /alarmcut doesn't return the alarm values*/ / *nezt step is to get a linefit for the thermistor data*/ tl4zero = linefit(beginfile, framepair, atodchan); /*set p_arr backto beginning of data*/ p_arr = begin-file; / *Makeheader for output file */ 120 fprintf(pout,"%.s %s\n",p_spec->name, pspec->id); fprintf(pout,"Frequency of transducers: fprintf(p_out,"fframes: %.31f\n",frequency); %d\n",framepair); fprintf(p_out,"Channels: %d\n",atodchan); / *Function for getting zeros from resting data set*/ printf("\nEnter the name of the zerofile for this day's data"); printf("\nor 'n' if no zero values are to be used:"); 130 scanf("/.s",zeroname); if(zeroname[O]== 'n' ){ fprintf(p_out,"Zerosnot used.\n"); for(i=O;i<13;i++) zerovalue[i]=O.O; else { zerofile=fopen(zeroname,"r"); fprintf(p_out,"Zeros were used.\n"); for(i=O;i<13;i++) 140 265 fscanf(serofile,"'i",&serovalue[i]); fclose(serofile); / *start loop of framepairs (now with 18 values after alarmcut)*/ for (nframe=O; nframe<framepair; nframe++){ / *at beginning of framepair, set cal, zero and level for the transducer */ / data which is in that framepair. */ 150 p_arr += atodchan; /*move to CAL position*/ cal = *parr; / *checklimitsfor cal */ if(cal<4001 cal>600) for(i=2;i<framepair-nframe;i++){ if(*(p arr+(8*i*atodchan))>4sn))00 * rr(8*i*atodchan))00) cal=*(p_arr+( 18*i*atodchan)); i=framepair-nframe; 160 p arr += atodchan; / *move to ZERO position*/ zero = *p_arr; zero = zero & DISCARDHI; for (l=0;1<3;1++){ zero = zero I ((zero & SET_HI) << 1); } parr +=(15*atodchan); /*move to LEVEL position*/ level= *parr; / *checklimitsfor level */ 170 if(level<7001 Ileve>l1100){ for(i=2;i<framepair-nframe;i++){ if(*(parr+(18*i*atodchan))>700&&*(parr+(18*i*atodchan))<1100){ level=*(p.arr+(18*i*atodchan)); i=framepair-nframe; } 266 (17*atodchan); /*move back to beginning(T)*/ parr -= 1so / *Begin with T, cal and zero beforedoing transducer loop*/ adjust = cal - sero; / *if alarmcharacter on T, then use nezt (or last) T */ data = *p arr; if ((data & ALARMCHEK) !=O){ for(i=1;i<framepair-nframe;i++){ if((*(p_arr+(18*i*atodchan))& ALARMCHEK)!=0){ *p_arr=*(p_rr+(18*i*atodchan)); lo i=framepair; data = *p arr; / *cae where there is no more good data*/ if(i==framepair-nframe) nframe=framepair; } / *if JUMPED, then disregardbecauseof slowness of temperature change*/ if ((data & JUMPCHEK)!=O0){ data = data & DISCARDHI; 200 for (1=0;1<3;1++){ data = data I ((data & SETHI) << 1); / check for compression/} datum = data; if(datum > level){ diff = datum - level; datum = level + 4*diff; } datum2 = VTOMV*((float)(datum-zero))/ ((float) adjust); 267 210 / *convert datum2 to fahrenheit*/ datum = sqrt((datum2+2861.0)/0.3391); / *write datum to file*/ fprintf(p.out," %.2f ",datum); / *write cal and zero to file*/ fprintf(poput," .2f %.2",(float)cal,(float)zero); 220 / *positionp_arr at lst transducer*/ parr+=(3*atodchan); / *Begin loopfor transducers I through 13'/ / *Do compression in tempfluz before temperatureadjustment*/ p_arr=tempflux(p_arr,p_out,zerovalue,tl4zero,atodchan,cal,zero,level); / *write power and level to file*/ fprintf(pout," %.21 /. 2f",(float)*p_arr,(float)level); parr+=(2*atodchan); 230 /*place at start of new framepair*/ /*WRITE A UXMUX DATA TO FILE AT THIS POINT IF ATODCHAN=2*/ if(atodcban==2){ p_arr-=(18*atodchan); / *position at T*/ p_arr++; /*increment to lst auzmuz value: auz 10*/ for(i=O;i<16;i++){ fprintf(p out," %d",*p arr); p arr+=atodchan; } p-arr +=(atodchan +1); /* Position at T */ } fprintf(pout,"\n"); } / *end offramepair loop*/ } 268 240 / *Linefit is used on channel (thermistor) in order to do the */ / * temperature calibrationon the other transducers */ 250 double linefit( int *y_arr, int samples, int atodchan){ int i,l,data; double sum,sumy; sum = (double) samples; sumy = 0; / *loopthrough samples and total them up*/ 260 for(i=0; i<samples; i++){ / *if no ALARMED character*/ if ((*y arr & -ALARMCHEK) == 0){ /*if there is a JUMPED value $/ if ((*y arr & -JUMPCHEK) != 0){ printf ("yarr = %d",*y_arr); / * Get correctvalues for y_arr $/ data = *y arr; data = data & DISCARDHI; printf ("data = %d",data); 270 for (1=0;1<3;1++){ data=(data I ((data & SET_HI)<<1)); printf ("data = %d\n",data); sumy += (double)data; y_arr+=(18*atodchan); / *casefor normal values*/ else { sumy += (double)*yarr; y arr+=(18*atodchan); 269 280 /*calculate the mean */ return(sumy/sum); } / *This is the temperaturefluz function, usedfor all channels $/ 290 /*ezcept 1(transducer 14), 2, 3(CAL, Zero, power, level) and 7 / / *(transducer not working properly) */ int *tempflux(int *parr, FILE *p_out, float *zerovalue,double tl4zero, int atodchan, int cal, int zero, int level) { int i,diffjumpedvalue,l, data; / *intermediate variable in data conversion*/ float datum; float b,m; /*intercept and slope for data conversion*/ float newvalue; 300 float c[14],d[14],e[14]; / *assign values to arrays accordingto equationsfor each transducer. */ c[l] = -.0308; d[1] = -153 ; e[1]= 1.22; c[2]= -. 275; d[2] = 1009; e[2]= 0.987; c[3]= -. 412; d[3] = 22; e[3]= .678; c[4] = 0; d[4] = 0 ; e[4]=1; /transducer not done*/ c[5] = -. 150; d[5] = 555 ; e[5] = .976; c[6] = .201 ; d[6] = 359; e[6] = 1.23; c[7] = -.113; d[7] = 150; e[7]= .960; 310 c[8]= -.0564; d[8]= 251; e[8]= .870; c[9]= -. 2899; d[9] = 314; e[9] = .795; c[10]= -.4408 ; d[10] = 695; e[10]= .885; c[11]= -.177; d[11] = -159; e[11]= .814; c[12] = -.0815; d[12] = 1068; e[12]= .839; c[13] = -. 0722; d[13] = -175; e[13]= .888; / *now loop through transducers and calculate new pressure values according*/ / * to the thermistor readings / 320 270 jumpedvalue=0; for(i = 1; i < 14; i++){ data = *p_arr; / *checkfor ALARMED value of data*/ if((data & -ALARMCHEK)==0) { / *checkfor JUMPED value of data*/ if((data & JUMPCHEK)!=0){ jumpedvalue = 10000; } data = data & DISCARDHI; 330 for (l=0;l<3;1++){ data = data I ((data & SET_HI) << 1); /* } */ / *checkfor compression$/ datum=(double) data; if(data > level){ diff = data-level; datum = level + 4*diff; 340 } newvalue = VTOMV*((float)(datum-zero))/ ((float)(cal-zero)); / now convert by temperature"/ b = c[i]*tl4zero + d[i]; m = e[i]; datum = (newvalue - b) / m; newvalue = datum - *zerovalue; / now write the newvalue to file*/ if (jumpedvalue !=0){ fprintf(pout," *%.2f ",newvalue); else { fprintf(p_out," %.2f",newvalue); } p_arr+=atodchan; 271 350 jumpedvalue = 0; else { fprintf(p out," %f", (float) data); 360 p_arr += atodchan; zerovalue++; /*increment zerovaluefor nezt transducer*/ } return(parr); / *p_arrnow points to P in the framepair*/ } 370 380 390 ALARMCUT.C 272 /* Function to check alarms and pare down data acquired */ /* using longio */ /$ Dec. 10, 1991, rewritten Jan 27, 1992 */ /, / /* ChangedDec. 15, 1992 to deal with change in alarms */ /* that first became apparent Nov. 13, 1992. Alarm */ /* level during no alarms is now: 63 - 76 or so in the / /* high field and -1000 to -965 or so in the lowfield */ /* Only change to program is to changethe value of */ /$ "ignore" to 0z13F. See Prosth notebook #5 near the $/ /$ end, under data collection 12/14/92 for calcs. /$ K.C. 10 */ * #include <stdio.h> #include <math.h> #include <p file.h> #define DARRSIZE 21752 #define 20 ATODVOLTS 204.8 #define FRAMESYNC -5.29 #define PCHAN33 16 #define PCHAN43 18 #define ALARMED 20000 #define JUMPED 10000 #define ALARMHI -4.9*ATODVOLTS #define ALARMLOW -5.3*ATODVOLTS 30 #define DISCARDHI 0x8FFF #define JUMPX OxDFFF #define ALARMX OxBFFF void alarmcut (int *parr, FILE *p_out, struct datainfo *p_spec){ 273 int *p wrt,*p strt; int level, field, levelo, leveln; int fram,chan,atodchan, scans, frames, tframes; int data, startoff; 40 int i, alarms, j, alarmch; int jumpjumped,alarmed; int ignore = Oxl3F; /$ ChangedDec. 15, 1992 from 02107 */ / * Get informationfrom datinfo / atodchan p spec->adchan; scans = p_spec->samp; alarmch = p spec->alarmch; / $ p_arr is locatedat first T right now. Want to save it. $/ so / Also, want to write backto same place $* frames = p spec->frames; tframes = scans/32; jumped = 0; alarmed = 0; pwrt = p arr; p_strt = p_arr; /* for (i=O;i<64;i++){ printf("%d",*parr); p_arr++; 60 } printf('\n"); */ p_arr= pstrt; for (fram=l;fram<=tframes;fram++){ field = 2; 70 /$ Firstdealwith T */ if (alarmch!=-1){ 274 p_arr +=alarmch; alarms = *p arr; alarms = alarms-63; if ((abs (alarms) & ignore) > O){ jump = atodchan*PCHAN33; p_arr+=jump; alarms = *p_arr; alarms += 5.29*ATODVOLTS; 80 alarms = alarms-63; jumped = 1; if ((abs(alarms)& 'ignore) > 0){ p_arr-=jump; alarmed = 1; jumped = 0; alarms= *parr; p_arr-=alarmch; 90 } / $ Now write backT to array $/ data = *p_arr; data = data & DISCARDHI; /$ if (jumped){ data = data+JUMPED;*/ data = data I JUMPX; p_arr -= jump; jumped = 0; } 100 if (alarmed){ data = data I -ALARMX; alarmed = 0; } *p_wrt = data; p_arr+=2; p wrt++; /* Write the auz-muz channel, any others */ 275 for (i=2;i<atodchan;i++){ data = *parr; *pwrt = data; 110 p arr++; p_wrt++; /* Nezt is CAL and ZERO just write to array / for (j=Oj<2j++){ data = *p arr; data = data & DISCARDHI; *p wrt = data; p_arr+=2; 120 p wrt++; for (i=2;i<atodchan;i++){ data = *parr; *pwrt = data; p-arr ++; p_wrt ++; } /* Now need to do the transducers, 1-13 */ field = 1; 130 for (j=0;j<(PCHAN33-3);j++){ if (alarmch != -1){ parr+=alarmch; alarms = *parr; alarms += 5.29*ATODVOLTS; alarms = alarms - 63; if ((abs(alarms) & 'ignore)>O){ jump = atodchan*PCHAN33; p arr+=jump; alarms = *p arr; alarms = alarms - 63; jumped = 1; if ((abs(alarms) & ignore)>O){ p_arr -=jump; 276 140 alarms = *p_arr; jumped = 0; alarmed = 1; parr -=alarmch; / * Now write back to array 150 / data = *parr; data = data & DISCARDHI; /*$ if (jumped){ data += JUMPED;*/ data = data JUMPX; p-arr -=jump; jumped = 0; } 160 if (alarmed){ += ALARMED;*/ /*$data data = data I -ALARMX; alarmed = 0; } *pwrt = data; parr +=2; p wrt ++; for (i=2;i<atodchan;i++){ data = *parr; *pwrt = data; 170 p_arr ++; p_wrt ++; } /* Closes the transducer loop $/ p_arr += atodchan; /* Skip the second T recording*/ /* Now write back P and L $/ for (j=O;<2 j++){ data = *p_arr; data = data & DISCARDHI; 277 180 *p wrt = data; parr +=2; p_wrt ++; for (i=2;i<atodchan;i++){ data = *parr; *pwrt = data; parr ++; p wrt ++; } /$ Close the P and L loop $/ 190 p_arr += (atodchan * (PCHAN33-3)); /* Position at T again */ } /* Close the tframes loop $/ parr = p strt; for (i=O;i<18;i++){ printf("%d",*p_arr); data = p_arr; data = data & Oz8fff; for (j=O;j<3;j++){ data = data I ((data 8 -OzO7FF)<< 1); } 200 printf("%Cd",data); parr++; $/ p_arr = pstrt; 210 GET43BEG.C 278 /$ Function to locate the start of output from a prosthesis $/ / *Jan. 15, 1991 original version*/ /* April 18, 1991. Tim changedthe part where the program asks for the */ / alarm channel. It is now automatic. GET BEGIN. C was renamed GET BEG2. C */ / * July 15, 1991. The part of the original program that worked on #43 was */ / modified to work with the new pressure conversionprogram. The new / 10 / *version finds and returns the first transducer 14 occurenceinstead of */ /* CAL and Zero. $/ #include <stdio.h> #include <math.h> #include <pfile.h> #define ATODVOLTS204.8 /* Can I use a float? This is aid units per volt */ #define ATODMV0.2048 / *Thisis a/d units per millivolt*/ #define FRAMESYNC -5.32 / * This is value for frame synch */ 20 #define PCHAN33 16 /$ The number of output channels from prosthesis */ #define PCHAN43 18 /$ Number of separate output quantities from 43 $/ #define CALEVEL 180 / $ nominal value for acceptingcal and zero $/ #define CALEVEL2 210 #define VTOMV 1000.0 /* convert to my #define $/ MINIT 10000.0 /$ struct datainfo { char name[9]; char id[3]; 30 int samp; int adchan; int mult; int trig; char time[5][12]; char descr[32]; int startoff; int frames; 279 int alarmch; int synchch; 40 double freq; $/ / * This one is to get start of a file written from 43 */ / * Look for first occurence of CAL and Zero, tricky because / /* They don't occur every frame, only every other */ / * For now, have user input which A\D channel alarms are on*/ 50 void get43_begin(int *p arr, FILE *p_out, struct datainfo *p spec) int atodchan, scans, alarms, startoff=-1, frames, ij; int chanchek [32]; int field, start, diff, new, old; int alarmch= -1; int synchch= -1; int alcomp = OxOF; int fivevolt = 1024; 60 / Get information on data from the structure thisdata $/ atodchan= pspec->adchan; scans = p spec->samp; alarmch = 1; /*This is the automatic line $/ / * read the first 32 values of alarmch into an array */ p_arr += alarmch; for(i=O;i<32;i++){ chanchek [i] = *p_arr; 70 p arr+=atodchan; } /*Reset parr to datarray[O],actually to the 4th scan start $/ 280 alarmch); p_arr -=((32*atodchan)+ / *Nowlook at alarmch and use to determine which field are in*/ field=O; start=O; do{ 80 diff = chanchek[start+l]-chanchek[start]; if ((diff & alcomp) == 0)( if (chanchek[start] < ) field = 1; if (chanchek[start] > ) field = 2; else { start++; } while (field == 0); 90 /* Nezt step, is locate an edge of the field, doesn't changefast*/ / * Looking for a 5.3 V change */ old = chanchek[start+l]; i=1; new = chanchek[start+l+i]; while ((abs(new-old))< fivevolt ){ i++; new = chanchek[start+l+i]; i -1 ) * atodchan); if (field == 2) startoff = ((start if (field == 1) startoff = ((start + i + 15)* atodchan); loo printf("alarm ch Yd synch ch %d \n",alarmch,synchch); / startoff is the number of elements of datarray before */ /* the first full frame starts (frame alignment defined */ /* as starting with 14th transducer and ending with 13th $/ /* transducer.) NOTE that datarrayelementsare numbered*/ / * from zero, and that first 3 scans are skipped */ 281 110 frames = (scans - startoff/atodchan)/PCHAN33; if (startoff== -1) printf("This data may not be good," ); printf("or alarms may not be on a/d channel 2\n"); } pspec->startoff = startoff-atodchan; 120 p spec->frames = frames; p_spec->alarmch = alarmch; pspec->synchch = synchch; printf ("startoff %d frames %d\n",startoff,frames); } READLFI.C / * Subroutine to read the data files from "pio" */ / * currently this is calledfrom "datalook"*/ /* Jan 4 1990 */ #include <stdio.h> #include <conio.h> #include #include #include #include <ctype.h> <dos.h> <time.h> 10 <string.h> #include <pfile.h> FILE *getfile (struct datainfo *); int *pile_data (struct datainfo *, FILE *); 282 int *read lfi(struct datainfo *p spec) { 20 FILE *pdata; int *p_arr; Get the file in another function */ / pdata = getfile(p_spec); / $ Now readdata into array*/ parr = pile_data(pspec,pdata); /* Close the file */ 30 fclose(p data); return(parr); FILE *get_file(strnct datainfo *pspec){ char dataname [NAMESIZE]; FILE *pdat; 40 / Information that need to get from user: Name of File to put data into $/ /* Open the file to put stuff in */ $ printf("Enter the complete nameof file to look at: "); scanf("s",dataname); / Start filling datinfo *$/ 50 p_dat = fopen(dataname,"r"); fscanf(p_dat,"'Vs %s",pspec->name,p_spec->id); 283 return(p.dat); } /* Read the data from the file into an array */ int *pile_data (struct datainfo *pspec, FILE *pdata) so { IMPORT int datarray0; int *p_arr; char num[7],data[11]; /* e[0], c[20]; char s20],t[10o],f[10], int conl,con2; float sec; */ int dat index; 70 int chan index; int ij,chan,lsamp; /* Want to get to skip first three scans $/ p_arr = &datarray[O]; / First readsamplingparameters / / The first severallines contain plenty of writing as well */ fscanf(pdata,"%d %*s %*s %*s %*s %*ss",&(pspec->samp)); fscanf(p data,"%d %*s %*s",&(pspec->adchan)); fscanf(p data, "%*d%.*s%*s%*d%*s%*s"); fscanf(p_data,"%*s%*s%*s%*s%*s%*f"); fscanf(pdata,"%*s%*s%*s%lf",&(pspec->freq)); fscanf(p_data,"%*s %*s %*s %*s %d %*s",&(p spec->mult)); fscanf(pdata,"%*s %*s %*s %*s %*8 %*s %*s%*s %*a"); fscanf(p_data,"%*s %*s %sa%s sa %8 %s",pspec->time[1],\ 284 80 p_spec->time[2],p spec->time[3],p spec->time[4],\ 90 p spec->time[5]); fscanf(p /$* May .*s %*s%*s%*s%*s%*s.*s%*s%*s data,"%*s %*s%*s%*s%*s%*s"); also want stuff like: triggering, delays,... $/ chanindex = p_spec->adchan; datjindex = p_spec->samp; printf("Chans %d samples %d \n",chanindex,datjindex); printf("Frequency: %lf\n",pspec->freq); / * Read data : Note that for some reason data was written as strings */ / * Also ... would be more convenient later if this were a */ 100 / * multidimensional array */ / * Now start storing*/ for( i=O; i< dat index; i++) { fscanf(pdata,"%*s"); 110 for (j=O;j< chanindex; j++) { fscanf ( pdata,"%s",data); / * here need to convert the string to a number and store in datarray $/ sscanf ( data, "%d", p_arr); p_arr++; } parr = &datarray[O]; 120 return(parr); } 285 AUX20-D.C /* Jan 23, 1992 */ / *Programuses the .int files from longdat2and makes easyplot files. */ / *The current version works on the four foot switch channels, the */ / *goniometer channel, and the auziliary 11 channelfor the force cane.*/ / *If other channels are needed, the programwill have to be modified.$/ /$ Oct. 7, 1992 / / $ Programaltered from auzmuz20.c this version allows input of */ / * which channel to readforce cane signalfrom and can handle */ / synch signalfrom TRACK / /*K.C /$ o10 */ Dec. 15, 1992 / / * Programchanged to handle forceplate data from TRACK also. $/ /*K.C. */ / Should make major changes - change datarray to a structure $/ / $ and allocate memory for it using halloc */ #include <stdio.h> #include <conio.h> 20 #include <ctype.h> #include <dos.h> #include <time.h> #include <string.h> #include <pfile.h> #define ADFULLSCALE 2048 /* datinfo contains the information about the dataset struct auxinfo { char name[9]; 286 30 3/ char id[3]; double frequency; int frames; int channels; }; float datarray[330][43]; FILE *get-file (struct auxinfo *); 40 void piledata (struct auxinfo , FILE *); float fsvalue(float,int); main () FILE *p_data; char response[10]; struct auxinfo datinfo; struct auxinfo *p_spec; pspec = &datinfo; 50 response[O] = 'y'; == 'y'){ while (response[O] /* Get the file in another function $/ p_data = get file(p_spec); printf ("%d",p data); / Now readdata into array */ pile_data(p_spec, so60 pdata); printf("Do another file? "); scanf ("%s",response); } 287 FILE *getfile(struct auxinfo *p_spec) { 70 char dataname [NAMESIZE]; FILE *pdat; / * Information Name of File to put data i,to * / that need to get from user: * */ Open the file to put stuff in */ printf("Enter the nameof a data file for sorting: scanf("s ",dataname); "); 80 / * Start fillingdatinfo*/ p_dat = fopen(dataname,"r"); fscanf(pdat,"%s %s",p spec->name,pspec->id); return(pdat); } / Read the data neededfrom the file and write to new file void pile_data (struct */ 90 auxinfo *p_spec, FILE *p_data) { char temp_data[10]; char *cl,*c2; char filename[NAMESIZE]; FILE *pout; int check = 0; 100 int cane = 0; int fplates = 0; int fpright = 0; int fpleft = 0; int leftfoot = 0; 288 int rightfoot = 0; int gon = 0; int tsync = O; / * TRACK synch signal $/ int tsynch 9; int canech = 10; 110 int fpl = 10; int fp2 = 11; int fplzero, fp2zero; int ij,h; int chan; int aux chans = 41; char fill[8]; int x = 0; int goodsamp; extern float datarray[330][43]; float datum = 0.0; 120 float angle; float conversion = 0.0; float timeskip = 0.0; float data[5]; float fpfullscale; float freq; fill[O]=' b' ;fll[]=;fill[]=a'fill[2]='d' ;fill[3]= ' d' ;fill[4] = 'a'; fill[5]='t ';fill[6]= 'a';fill[7]=' \0'; 130 *cl='O'; *c2='*'; data[0]=0.0; / First readsamplingparameters*/ / * The first several lines contain plenty of writing as well $/ printf("'%d",pdata); fscanf(p_data,"%*s %*s '.%*s%1f",&(p_spec->frequency)); freq = (float)pspec->frequency; 140 289 fscanf(pdata,"%*s %d",&(p_spec->frames)); goodsamp=p_spec- >frame.fscanf(p.data,"%*s %d",&(p_spec->channels)); fscanf(p_data,"%*s %*s %*s"); printf ("%s %s\n",p_spec->name,p_spec->id); printf ("'"% %d %d\n",freq,goodsamp,p_spec->channels); /$ Find out what channels were used in this data set / if(pspec->channels>1){ printf("\nEnter 150 1 if a TRACKsync signal was taken:"); scanf ("'%d",&tsync); if (tsync == 1){ printf("Enter the channel TRACKsync signal was on:"); scanf ("/,d",&tsyn-ch); } printf("\nEnter 1 if force cane was used, 0 if not used:"); scanf("%d",&cane); if (cane ==1){ 160 printf("Enter the channel for force input:"); scanf( "'d",&cane ch); printf ("\nEnter the numberof forceplates used, 0 if not used: "); scanf ("%d",&fplates); if (fplates== 1){ printf("Enter the numberof the forceplate used (1 or 2): "); scanf("Yd",&fpright); if (fpright == 2){ 170 fpright = 0; fpleft = 1; } printf("Enter the channel forceplate data is on: "); scanf ("/,d",&fpl); if (fpright== 0){ 290 fp2 = fpl; fpl = 0; } printf ("Enter the zero value for this forceplate "); 180 scanf ("%d",&fplsero); if (fpright == 0) { fp2zero = fplzcro; fplzero = 0; printf("Enter the full scale value in Newtonsfor the forceplates: "); scanf ("%f ",&fpfullscale); I if (fplates==2){ fpright = 1; 190 fpleft = 1; printf("Enterthe channel forceplate (right) is on: I"); scanf ("%d",&fpl); printf ("Enter the channel forceplate 2 (left) is on: "); scanf ("%d", &fp2); printf("Enter the zero value for forceplate 1: "); scanf ("%d",&fplzero); printf("Enter the zero value for forceplate 2: "); scanf ("%d",&fp2zero); printf ("Enter the full scale value in Newtonsfor thee forceplates: "); 200 scanf ("%f",&fpfullscale); printf("\nEnter channel of left footswitch (1-4), or 0 \n"); printf("if footswitches were not used:"); scanf("'.d",&leftfoot); if (leftfoot > 0 && leftfoot < 5) /* IF FS ARE BEING USED */ 210 { printf("Enter channel of right footswitch (1-4):"); scanf("%d",&rightfoot); 291 } printf("\nEnter 1 if goneometer was used in this data set, 0 i not used:"); scanf("%d",&gon); / *Loopfor however many framepairs */ for (i=0O; i<pspec->frames; i++){ * * 220 / 'Loop for 18 prosthesis values*/ for (j=; j<18; j++) { fscanf(p_data, "%s ",temp data); / printf("%s ",temp_data); */ check=strcmp(&temp_data[0],cl); / *CONVERT TO MPA FROM PSI HERE*/ sscanf(temp_data, "%f ",&conversion); ifj>2&&j < 16&&j!=6){ datarray[i][(2*j)] = 0.006894 * conversion; 230 else { datarray[i][(2*j)] = conversion; } / prinzf("%.2An", datarray[i][2*j]); $/ if(chleck!=0){ / *case when at least one point was good*1 check=strcmp(&temp_data[0],c2); if(check!=0){ /*case when st point was used*/ datarray[i] [(2*j)+1]=timeskip; } else{ 240 /*case when second point was used*/ datarray[i] [(2*j)+l]=(timeskip+(1/(freq*2))); } else { /*case when data point was bad*/ datarray[i] [2*j]=-10000; datarray[i] [(2*j)+1]=timeskip; } 292 } /*end prosthesis loop*/ 250 timeskip+=l/freq; /$ Will need to do this differently, check if each channel is used */ if(p spec->channels==2){ for (h=36;h<43;h++){ datarray [i][h] = 0.0; } for =0;j<16j++){ chan = j+10; 260 if (chan > 16) chan = chan - 16; / * Footswitchesare auzmuz 12 - 15, if used $/ if (chan == 12 && ( leftfoot != 0 II rightfoot != 0)){ /*put nezt 4 values into an array. This simplifies the process.*/ for(h = 1; h < 5; h++){ fscanf(p_data,"%f",&data[h]); 270 } / *NEED TO INCORPORATE FSVAL UE FUNCTION INTO THESE*/ datarray[i][37] = fsvalue(data[leftfoot],leftfoot); / *assigns0.0 if leftfoot is 0*/ datarray[i] [38] = fsvalue(data[rightfoot],rightfoot); j += 3; / increment j to keep in order $/ } else if (chan == tsyn_ch&& tsync == 1) { fscanf (p_data, "%f",&datum); datarray [i][40] = datum; 280 } else if (chan == cane_ch&& cane == 1){ fscanf(pdata,"%f",&datum); datarray[i][36] = datum*0.110; 293 / THIS CONVERTS CANE DATA INTO bf */ } else if (chan == fpl && fpright == 1){ fscanf (p_data,"%f",&datum); 290 datarray [i][41]= (datum - fplzero) * fpfullscale/ADFULLSCALE; } else if (chan == fp2 && fpleft == 1){ fscanf (p data, "%f",&datum); datarray [i][42]= (datum - fp2zero) * fpfullscale/ADFULLSCALE; } else if (gon == 1 && chan == 16){ fscanf(p_data,"%f",&angle); datarray[i][39] = 3.485 * angle - 1646.1; / CONVERTS ANALOG UNITS TO DEG*/ 300 } else fscanf (p_data,"%.*f"); / Else, Throw this point away */ /* END OF FOR LOOP FOR FRAMES OF 34 */ I }/ close the outside loop for all framepairs*/ / Close the file *$/ fclose(p_data); / * FIND OUT WHERE TO PUT DATA, THEN WRITE IN DATA INFORMATION */ 310 printf("\nEnter the name of the oltput file:"); scanf("%8s",filename); p_out= fopen(filename,"w"); /* OPEN OUTPUTFILE */ fprintf(p_out,"%s s\n",pspec->name, pspec->id); fprintf(p_out,"Frequency of transducers: %1f\n" ,pspec->frequency); fprintf(p_out,"Samples: %d\n",p_spec->frames); fprintf(pout,"\n//forcepd 9.95 7.5"); 320 294 fprintf(p out,"\n//pos 0 .75 .2 .95"); fprintf(p out,"\n/ag"); fprintf(p out,"\n/sm OFF"); fprintf(p_put,"\n/et x 'time (sec)"'); /* fpirintf(p_out,"'n/et y 'temperature (F)"');*/ fprintf(pout,"\n/et g 'Thermistor Data"'); fprintf(p_out,"\n/or y 97 107"); fprintf(pout,"\n/td yx...."); for(h=O;h<goodsamp;h++){ if(datarray[h] [0]!=-10000) fprintf(p_out,"\n%5..21 330 %5.2f %5.2 %/,5.21 %5.21 %5.21", datarray[h] [0O,datarray[h][1],datarray[h] [36], datarray[h] [37],datarray[h] [38],datarray[h] [39]); else fprintf(pout,"\n'/.s %5.2f .5.2f %.5.2f %5.2f %5.2f",fill, datarray[h][1],datarray[h] [36],datarray[h] [37], datarray[h] [38],datarray[h] [39]); fprintf(p_out,"\n//nc"); fprintf(p_out,"\n\n"); fprintf(p_out,"\n//pos 340 .2 .75 .4 .95"); fprintf(p_out,"\n/ag"); fprintf(p_out,"\n/et x 'time (sec)"'); fprintf(p_out,"\n/et y 'cmv'); fprintf(p_out,"\n/et g 'Calibration Data"'); fprintf(p_out,"\n/or y 400 600"); fprintf(p_out,"\n/tdyx...."); for(h=O;h<goodsamp;h++){ if(datarray[h] [2]!=-10000) 350 fprintf(p_out,"\n%/ .21 %5.21 %5.21 %5.21 %5.21 %5.21", datarray[h] [2],datarray[h] [3],datarray[h] [36], datarray[h] [37],datarray[h] [38],datarray[h] [39]); else fprintf(p_out,"\n%s %5.21 %.5.2f %5.2f %5.2f1 5.21",fill, datarray[h] [3],datarray[h] [36],datarray[h] [37], 295 datarray[h] [38],datarray[h] [39]); fprintf(p out, "\n//nc\n\n"); fprintf(p out,"\n//pos .4 .75 .6 .95"); 360 fprintf(p out,"\n/ag"); fprintf(pout,"\n/et x 'time (sec)"'); fprintf(p out,"\n/et y 'cmv"'); fprintf(p out,"\n/et 'Zero Data'"); fprintf(p out,"\n/or y -50 50"); fprintf(pout,"\n/td yx...."); for(h=O;h<goodsamp;h++){ if(datarray[h] [4]!=- 10000) fprintf(p out,"\n%5.2f %5.2f %5.2f %5.2f %5.2f %5.21", datarray[h] [4],datarray[h] [5],datarray[h] [36], 370 datarray[h] [37],datarray[h][38],datarray[h][39]); else fprintf(p_out,"\n'/s%5.2f %5.2f 5.2f! %5.21%5.2f",fil, datarray[h] [5] ,datarray[h][36],datarray[h] [37], datarray[h] [38],datarray[h][39]); fprintf(p_out,"\n//nc\n\n"); fprintf(p out,"I\n\n"); fprintf(p out,"\n//pos 0 .5 .2 .7"); fprintf(p out,"\n/ag"); 380 fprintf(pout,"\n/et x 'time (sec)"'); fprintf(p out,"\n/et y 'pressure (MPa)"'); fprintf(pout,"\n/et g 'transducer 1"'); fprintf(p out,"\n/or y -1 7"); fprintf(pout,"\n/td yx......."); for(h=O;h<goodsamp;h++){ x=(2*i)+4; if(datarray[h] [6]!=-10000) fprintf(p_out,"\n'/%3.3f %5.21 %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f "5.21", datarray[h] [6],datarray[h] [7],datarray[h][36], datarray[h] [37],datarray[h] [38],datarray[h] [39], datarray[h] [40],datarray[h] [41],datarray[h] [42]); 296 390 else fprintf(pout,"\n,s %6.2f %6V.2f %5.2f %.2f ;,w.2f %6.2f %5.2f %6.2f", fill,datarray[h] [x+1],datarray[h] [36] ,datarray[h] [37], datarray[h](38,datarray[h][ataray39,datarray[h][40], datarray[h] [41],datarrayh] [42]); } fprintf(pout,"\n//nc\n"); /* fcloae(p_out); 40o printf('\nEnter the name of the 2nd output file:"); scanf("%s",filename); p_out = fopen(filename,"w"); OPEN OUTPUT FILE */ fprintf(p out,"\n//pos .2 .5 .4 .7"); fptintf(p out,"\n/ag"); fprintf(pout,"\n/et x 'time (sec)"'); fprintf(pout,"\n/et y 'pressure (MPa)'"); 410 fprintf(pout,"\n/et g 'transducer 2'"); fprintf(p_out,"\n/sm OFF"); fprintf(p out,"\n/or y -1 7"); fprintf(pout,"\n/td yx....... "); for(h=0;h<goodsamp;h++){ if(datarray[h] [8]!=-10000) fprintf(pout,"\n/.3.3f %5.2f %5.2f %5.2f %5.2f %5.2f %5. %.2f 5 .2 .2f", datarray[h] [8],datarray[h] [9],datarray[h] [36], datarray[h] [37],datarray[h] [38],datarray [h][39], datarrayrh][40],datarray[h] [41],datarray[h][42]); else fprintf(p.put,"\n/.s %5.2f %5.2f %5.2f %5.2f %5.2 %5.2f %.2f %5.2f",fill, datarray[h] [x+l],datarray[h] [36],datarray[h] [37], datarray [hi[38],datarray[h] [39],datarray[h] [40], datarray[h] [41],datarray[h] [42]); fprintf(pout,"\n//nc\n"); fprintf(p out,"\n//pos .4 .5 .6 .7"); 297 420 fprintf(pout,"\n/ag"); fprintf(pout,"\n/et x 'time (see)"'); fprintf(pput,"\n/et y 'pressure (Pa) "'); fprintf(pout,"\n/et g 'transducer 3'"); fprintf(p out,"\n/or 43o y -1 7"); fprintf(pp out,"\n/td yx....... "); for(h=O;h<goodsamp;h++){ if datarray[h] [10]!=-10000) fprintf(pput,"\n%3.31 %.2f 5.2f1%6.2f Y,6.2f ,%6.2f%6.2f %6.2f Y,5.21", datarray[h][lO],datarray[h][11],datarray[h](361, datarray[h] [371,datarrayh] [38],datarray[h] [39], datarray[h] [40],datarray[h] [41],datarray[h] [42]); 440 else fprintf(pout,"\n/s %6.21 %.6.2f1 b.2f %5.2f %5.2f %6.2f %5.2f %5.2f",fill, datarray[h] [11],datatray[h] [36],datarray[h] [37], datarray[h] [38],datarray[h] [39],datarray[h] [40], datarray [h] [41],datarray[h] [42]); fprintf(pout,"\n//nc\n"); /* fprintf(p_out, \n//pos .6 .5 .8 .7"); fprintf(p_out, '"\n/ag"); fprintf(p_out, '"\n/et z 'time (sec)"'); 450 fprintf(p_out,'\n/ et y 'correctedm V"'); fprintf(p_out,"\n/et g 'transducer4"'); fprintf(p_out,'\n/td yz........ ); for(h=O;h<goodsamp;h++){ if(datarrayh[l2]=-- 10000) fprintf(p_out,"\n%3.3f %5.2f %5.2f %5.2f %55.2f%5.2f s5.2f %5.2f %5.2f", datarrayhJ[12],datarray[h][1l,datarray[h[36, datarray[h][37,datarray][38], datarray[h][39], datarray[/h][40, datarray[hJ[41],datarrayLh][4l 2]); else fprintf(p_out, "\ns fill,data 460 %5.2f %5.2f %5.2f %5.2f %s5.2f %5.2f %5.2f %5.2f", dtrray[h][36], tary[h]3 datatrrayh][37], dat arrayl[3 8, datarrayh[3 9], dat arra y[ 0], datarrayh[4],datarray][42); 298 fprintf(pout, "\ n// nc\ n");*/ .6 . fprintf(p_out,"\n//po .8 . 7"); fprintf(p.out,"\n/ag'); fprintf(p out,"\n/.t x 'time (sec)"'); fprintf(pout,"\n/et y 'pressure (Pa)"'); 470 fprintf(pout,'\n/et g 'transducer 6'"); fprintf(pout,"\n/or y -1 7"); fprintf(pout,"\n/td yx....... "); for(h=0;h<goodsamp;h++){ if(datarray[h][14]!=-10000) fprintf(p_out,"\n%3.3f %.5.2f Y,5.2f Y5..2f Y,%.2fY,5.2f %6.2f %Y6.2f%Y5.2", datarray[h] [14],datarray[h] [15],datarray[h] [36], datarray[h] [37],datarray[h] [38],datarray[h] [39], datarray[h][40],datarray[h] [41],datarray[h] [42]); else 480 fprintf(pout,"\n/,s %5.2f %Y.2f %5.2f %Y.2f %Y5.2f%5.2f .%5.2fY.5.2f",fil, datarray[h]15],datarray[h] [3636],datarray[h] [37], datarray[h] [38],datarray[h] [39],datarray[h] [40], datarray[h] [41],datarray[h] [42]); fprintf(pout,"\n//nc\n"); /* fclose(p_out); printf("Enter the name of the 3rd output file:"); scanf(" s ",filename); 490 p_out = fopen(filename,"); fprintf(pout,"\n//pos .8 OPEN OUTPUT FILE */ .5 1 .7"); fprintf(pout,'"\n/ag"); fprintf(pout,"\n/et x 'time (sec)"'); fprintf(pout,"\n/et y 'pressure (Pa)"'); fprintf(p out,"\n/et g 'transducer 6"'); fprintf(pout,"\n/sm OFF"); fprintf(pout,"\n/or y -1 7"); 500 299 fprintf(p_out,"\n/td yx ......."); for(h=-O;h<goodsamp;h++){ if(datarray[h] [16]!=- 10000) fprintf(p out,"\n%3.3f! .6.2f %6.2f %6.2f Y,5.2! %6,.2f %6.2f! ,6.2! %56.2f", datarray[h] [16],dataray[h] [17],datarray[h] [36], datarray[h] [37],datarray[h][38],datarray[h] [39], datarray[h] [40],datarray[h] [41],datarray[h][42]); else fprintf(pput,"\nXo %6.2f %5.2f ,.5.21 '6.2f .6,.2f V6.2f 6.2f %5..2f",fill, datarray[h] [17],datarray[h] [36],datarray[h] [37], S10 datarray[h] [38],datarray[h] [39],datarray[h] [40], datarray[h] [41],datarray[h] [42]); } fprintf(poput,"\n//nc\n"); fprintf(p out,"\n//pos 0 .25 .2 .45"); fprintf(p_out,"\n/ag"); fprintf(pout,"\In/t x 'time (sec)"'); fprintf(pout,"\n/et y 'pressure (Pa)"'); fprintf(p_out,"\n/et g 'transducer 7'"); fprintf(p out,"\n/or y -1 7"); fprintf(p_out,"\n/td yx....... 520 "); for(h=O;h<goodsamp;h++){ if(datarray[h][18]!=-10000) fprintf(pout,"\n%3.3f! .5.2! % 5.2f %5.2! V.5.2! %5.2f %5.2! V 5.2! M5.2f", datarray[h] [18],datarray[h] [19],datarray[h] [36], datarray[h] [37],datarray[h] [38],datarray[h] [39], datarray[h] [40],datarray[h] [41],datarray[h] [421); else fprintf(p_out,"\n%s %5.2f %5.21 65.2f %,5.2f %5.2f %5.2! %5.2f %5.2f",fill, datarray[h][19],datarray[h] [36],datarray[h] [37], datarray[h] [38],datarray[h] [39],datarray[h][40], datarray[h] [41],datarray[h] [42]); } fprintf(pout,"\n//nc\n"); fprintf(p_out,"\n//pos .2 .25 .4 .45"); fprintf(pout,"\n/ag"); 300 530 fprintf(pout,"\n/et x 'time (sec)'"); fprintf(pout,'"\n/et y 'pressure (MPa)'"); fprintf(pout,'\n/et g 'transducer 8"'); fprintf(p out,"\n/or y -1 7"); fprintf(p.out,"\n/td yx....... 640 "); for(h=O;h<goodsamp;h++){ if(datarray[h][20]!=--10000) fprintf(p.out,"\n%3.3f %5.2f %'.2 %.2f %6.2f %6.2f %5.2f %5.2f %6.2f", datarray[h] [20],datarray[h] [21],datarray[h] [36], datarray[h] [37],datarray[h] [38],datarray[h] [39], datarray[h] [40],datarray[h] [41],datarray[h] [42]); else fprintf(p out,"\n%s %5.2f %6.2f %5.21 %6.21 %5.2f %5,.2f %.2f %5.2f",fill, datarray[h] [21],datarray[h] [36],datarray[h] [37], 550 datarray[h] [38],datarray[h] [39],datarray[h] [40], datarray[h] [41],datarray[h] [42]); } fprintf(pout,"\n//nc\n"); fprintf(p out,"\n//pos .4 .25 .6 .46"); fprintf(p out,"\n/ag"); fprintf(pout,"\n/et x 'time (sec)"'); fprintf(p-out,"\n/et y 'pressure (Pa)"'); fprintf(pout,"\n/et g 'transducer 9"'); fprintf(p out,"\n/or y -1 7"); 560 fprintf(pout,"\n/td yx....... "); for(h=O;h<goodsamp;h++){ if(datarray[h] [22]!=- 10000) fprintf(pout,"\n%3.31 %5.2f %5.2f %5.2f %5.21 %5.21 %5.21 %5.2f %5.21", datarray[h] [22],datarray[h] [23],datarray[h] [36], datarray[h] [37],datarrayh] [38],datarray[h] [39], datarray[h] [40],datarray[h] [41],datarray[h] [42]); else fprintf(pout,"\n%s %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f",fil, datarray[h] [23],datarray[h] [36],datarray[h] [37], datarray[h] [38],datarray[h] [39],datarray[h] [40], datarray[h] [41],datarray[h] [42]); 301 570 } fprintf(p out," \n//nc\n"); /* fclose(p out); printf("Enter the name of the 4th output file:"); scanf("'s ",filename); "w"); OPEN OUTPUTFILE '/ pout = fopen(filename, 580 .6 .25 .8 .46"); fprintf(pout,"\n//pos fprintf(pout,"\n/ag"); fprintf(pout,"\n/et x 'time (sec)'"); fprintf(pout,"\n/et y 'pressure (Pa)'"); fprintf(p_out,"\n/et g 'transducer 10'"); fprintf(poput,"\n/sm OFF"); fprintf(p out,"\n/or y -1 7"); fprintf(pout,"\n/td yx....... "); for(h=0;h<goodsamp;h++){ if(datarray[h] [24]!=-10000) 590 %.2f fprintf(pout,"\n%3.3f .5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f",datarray[h][24],datarray[h][25], datarray[h] [36],datarray[h] [37],datarray[h] [38], datarray[h] [39],datarray[h] [40],datarray[h] [41], datarray[h] [42]); else fprintf(pout,"\n%/.s %5.2f1 .5.2f %5.2f %5.2f %5.21 %5.21 %5.2f %5.21", fill,datarray[h] [25],datarray[h] [36], datarray[h] [37],datarray[h] [38],datarray[h] [39], datarray[h] [40],datarray[h] [41],datarray[h] [42]); fprintf(pout,"\n//nc\n"); .8 .25 1 .45"); fprintf(p out,"\n//pos fprintf(p out,"\n/ag"); fprintf(pout,"\n/et x 'time (sec)'"); fprintf(pout,"\n/et y 'pressure (MPa)'"); fprintf(pout,"\n/et g 'transducer 11"'); fprintf(pout,"\n/or y -1 7"); 302 600 fprintf(pout,"\n/td yx ....... "); 610 for(h=O;h<goodsamp;h++)( if(datarray[h] [26]1=- 10000) fprintf(p out,"\n%3.3! %.6.2f %65.2f%5.2f %.5.2f %.5.21 .5.2f",datarray[h] 5.6.2f%6.2f [26],datarray[h] [27], datarray[bh][36],datarray[h] [37],datrsray[h] [38], datarray[h] [39],datarraylh] [40],datarray[h] [41], datarray[h] [42]); else fprintf(p.out,"\n%s %5.2f %5.2f %5.21 %5.21 %5.2f %5.2f %5.2f %.5.2f",fill,datarray[h][27], datarray[h] [36],datarray[h] [37],datarray[h] [38], 620 datarray[h] [39],datarray[h] [40],datarray[h] [41], [42]); datarray[h] fprintf(pout,"\n//nc\n"); fprintf(p 0 0 .2 .2"); out,"\n//pos fprintf(ppout,"\n/ag"); fprintf(p out,"\n/et x 'time (sec) ''); fprintf(pout,"\n/et y 'pressure (MPa)'"); fprintf(p out,"\n/et g 'transducer 12"'); fprintf(pout,"\n/or e30 y -1 7"); fprintf(p out,"\n/td yx ....... "); for(h=O;h<goodsamp;h++){ if(datarray[h] [28]!=- 1000) fprintf(pput,"\n%3.3f %5.2f %5.2f %5.21 %5.21 %5.2f %5.21f%5.2f /.5.2I" ,datarray[h] [28],datarray[hi [29],datarray[h] [36], datarray[h] [37],datarray[h] [38],datarray[h] [39], datarray[h] [40],datarray[h] [41],datarray[h] [42]); else fprintf(p_out,"\n%.s%5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f1",fill,datarray[h] [29] ,datarray[h] [36], datarray[h] [37],datarray[h] [38],datarray[h] [39], datarray [h] [40],datarray[h] [41],datarray[h] [42]); ' ° ); fprintf(p_out,"\n//nc\n" 303 640 fprintf(p.out,"\n//poo .2 0 .4 .2"); fprintfp out,"\n/ag"); fprintf(pout,"\n/et x 'time (sec)"'); fprintf(pout,"\n/et y 'pressure (Pa) "'); fprintf(pout,"\n/et g 'transducer 13"'); fprintf(p out,"\n/or y -1 7"); 650 fprintf(pout,"\n/td yx....... "); for(h=O;h<goodsamp;h++){ if(datarray[h][30]!=-10000) fprintf(p out,"\n'/,3.3f %6.2f ,%65.2f ',5.2f '%S2.2 %6.2f ",datarray[h f %6.2f %.2f [30],datarray[h][31],datarrayh] [36], datarray[h] [37],datarray[h] [38],datarray h][39], datarray(h]40],datarray[h] [41],datarray[h] [42]); else fprintf(pout,"\n%,s %6.21 ,5.21 %5.21 %5.21 .5 .2f %5.2f %5.2f %5.2f ",fill,datarray[h][31] ,datarrayh][ 36], dsatarray[h][37],datarray[h][38],datarray[h] eoo [39], datarray[h] [40],datarray[h] [41],datarray[h] [42]); } fprintf(pout,"\n//nc\n"); /* fclose(p out); printf("Enter the name of the 5th output file:"); scanf("rs ",filename); p_out= fopen(filename,"w"); OPEN OUTPUTFILE */ 670 / *Now twritepower and level*/ fprintf(p_out,"\n//pos .6 .75 .8 . 95"); fprintf(pout,"\n/ag"); fprintf(p out,"\n/sm OFF"); fprintf(p_out,"\n/or y 600 700"); fprintf(ppout,"\n/et x 'time (sec)"'); fprintf(pout,"\n/et y 'cmv"'"); fprintf(pout,"\n/et g 'Power Data"'); fprintf(pout,"\n/td yx...."); for(h=0;h<goodsamp;h++){ 680 304 if(datarray[h] [32] 1= -10000) fprintf(p.out,"\n/,6.21 '/.6.21 %62 6.2f %6,.2 %6.2f", datarray[h][32],datarray[h][33],datarray[h][36], datarray[hl[37],d atarray(h]38,data38] ,datarray[] [39]); else fprintf(p out,"\n, %6.2f %6.21 %6.21 %6.2f %,.2f1",fill, datarray[h] [33],datarray[h][36] ,datarray[h] [37], datarray[h] [38],datarray[h][39]); fprintf(p.out,"\n//nc\n"); 90o fprintf(p out,"\n//pos .8 .76 1 .95"); fprintf(p out,"\n/ag"); fprintf(put,"\n/et x 'time (sec)"'); fprintf(pout,"\n/et y 'cmv"'); fprintf(p out,"\n/et g 'Level Data"'); fprintf(p out,"\n/or y 900 1100"); fprintf(pout,"\n/td yx...."); for(h=O;h<goodsamp;h++){ if(datarray[h][34]!=- 10000) fprintf(p_out,"\n%6,.2f %5.2f %,5.2f %5.21 ,%6.2f'5.2f", datarray[h] [34] ,datarray[h] [35],datarray[h] 700 [36], datarray[h] [37],datarray[h][38] ,datarray[h][39]); else fprintf(p out,"\n/,.s ,6.21 /,5.2f %5.2f1 ,5.2f %5.2f", fill,datarray[h] [35] ,datarray[h] [36], datarray[h] [37],datarray[h][38] ,datarray[h][39]); if(cane==1){ fprintf(pout, 710 "\n//nc\n"); fprintf(p_out,"\n//pos .4 0 .6 .2"); fprintf(p_out,"\n/ag"); fprintf(p out,"\n/et x 'time (sec) "); fprintf(pout,"\n/et y 'force (lbi)"'); fprintf(p_out,"\n/et g 'orce cane"'); 305 fprintf(p out,"\n/td yx"); for(h=O;h<goodsamp;h++){ fprintf(ppout,"\n%3. 2 %6. 2f",dataray[h][36],datarray[h] [1]); } 720 fprintf(pout,"\n//nc\n"); } if(leftfoot!=O){ fprintf(p.out, "\n//nc"); fprintf(pout,"\n//pos .6 0 .8 .2"); fprintf(put,"\n/ag"); fprintf(pout,"\n/et x 'time (sec)"'); fprintf(p_out,"\n/et g 'left foot"'); fprintf(p_out,"\n/or y 0 5"); fprintf(pout,"\n/td xy"); 730 for(h=O;h<goodsamp;h++){ fprintf(pout,"\n5 . 2f %5.2f",datarray[h][1],datarray[h][37]); fprintf(pout,"\n//nc"); fprintf(p_out,"\n//pos .8 0 1 .2"); fprintf(p_out,"\n/ag"); fprintf(p_out,"\n/et x 'time (sec)'"); fprintf(pout,"\n/et g 'right foot"'); fprintf(p_out,"\n/or y 0 5"); fprintf(p_out,"\n/td xy"); 740 for(h=O;h<goodsamp;h++){ fprintf(pout,"\n%5 .2f 5.2f",datarray[h][1],datarray[h][38]); . } fprintf(pout,"\n//nc\n"); } if(gon==l){ fprintf(p_out,"\n//nc"); fprintf(pout,"\n//pos .6 0 .8 .2"); fprintf(pout,"\n/ag"); fprintf(p out,"\n/et x 'time (sec)"); 750 fprintf(pout,"\n/et y 'angle (deg)"'); fprintf(pout,"\n/et g 'goniometer'"); 306 fprintf(pout,"\n/or y -140 140"); fprintf(p.out,"\n/td yx"); for(h=O;h<goodsamp;h++){ fprintf(p_out,"\n%3.2f %5. 2f",datarrayh][39],datarray[h][1]); } fprintf(p out,"\n//nc\n"); } if (tsync == 1){ 780 fprintf(p_out,"\n//nc"); fprintf(p_out,"\n//pos .8 0 1 .2"); fprintf(p_out,"\n/ag"); fprintf(p_out,"\n/et x 'time (sec)"'); fprintf(p out,"\n/et g 'TRACKsynch"'); fprintf(p_out,"\n/td xy"); for(h=O;h<goodsamp;h++){ fprintf(p-out,"\n'5 .2f %5.2f",datarray[h] [1],datarray[h][40]); fprintf(p_out,"\n//nc\n"); 770 } if(fpright==1){ fprintf(p.out,"\n//nc\n"); fprintf(p_out,"\n//pos .4 0 .6 .2"); fprintf(p_out,"\n/ag"); fprintf(p out,"\n/et x 'time (sec)"'); fprintf(p out,"\n/et y 'Vertical force (N)'"); fprintf(p out,"\n/et g 'Forceplate (right)"'); fprintf(p_out,"\n/td xy"); for(h=O;h<goodsamp;h++){ fprintf(p_out,"\n%3. 2 780 %6.2f",datarray[h][1],datarray[h][41]); fprintf(p_out,"\n//nc\n"); } if(fpleft==1){ fprintf(pout,"\n//nc\n"); fprintf(p_out,"\n//pos .6 0 .8 .2"); fprintf(p_out,"\n/ag); 307 fprintf(p_out,"\n/et x 'time (ec)"'); fprintf(p out,"\n/et y 'Vertical force (N)"'); 790 fprintf(p_out,"\n/et g 'Forceplate 2 (left)"'); fprintf(p out,"\n/td xy"); for(h=O;h<goodsamp;h++){ fprintf(p.out, "\n%3 .2f %6.2f",datarray[h][1],datarray[h][42]); } } fpleft = 0; fpright = 0; cane = 0; 800 fplates = 0; check = 0; leftfoot = 0; rightfoot = 0; gon = 0; tsync = 0; /* TRACK synch signal */ x = 0; datum = 0.0; conversion = 0.0; timeskip = 0.0; 810 fclose(p_out); return; /$ FSVALUE14 READS IN DATA IF FS CHANNEL I OR 4 WAS USED, AND RETURNS 1 IF FOOT IS NOT TOUCHING GROUND 2 IF ONLY HEEL IS TOUCHING GROUND 3 IF BOTH HEEL AND TOE ARE TOUCHING GROUND 4 IF ONLY TOE IS TO UCHING GR 0 UND 0 IF VALUE FALLS OUT OF RANGE (data is bad) */ 308 820 float fsvalue(float datum,int channel) { if(channel==0) return (0.0); 830 else if(channel==1 IIchannel==4){ if (datum > 277.0 && datum < 300.0) return (1.0); else if (datum > 240 && datum < 252) return (2.0); else if (datum < 236) return (3.0); 840 else if (datum > 259 && datum < 271) return (4.0); else return (0.0); } /*end channel I or 4 loop*/ else { if (datum > 282.0 && datum < 300.0) return (1.0); 850 else if (datum > 250.0 && datum < 262.0) return (2.0); else if (datum < 245.0) return (3.0); else if (datum > 266.0 && datum < 278.0) return (4.0); else 860o 309 return (0.0); } /*end channel 2 or 3 loop*/ __ _ __ _ __ 310 _ __ AVGZERO.C / *Functionfor averagingresting data sets into zero valuesfor*/ / *Prosthesis43's thirteen pressure transducers*/ / *January28,19921/ #include <stdio.h> #include <string.h> void main (void){ int i,hj; 10 int frames,adchan; char filein[14],fileoiut[14],datastr[20]; FILE *p_data,*pout; float data[14],datum,temp; float power,level,cal,zero; for(i=O;i<13;i++) data[i]=0.0; / *get input file */ printf("\nEnter the nameof the resting data set:"); scanf("%s",filein); 20 p_data=fopen(filein,"r"); / *Input header values*/ fscanf(p_data,"%*s %*s %*s %*s %*s %*lf"); fscanf(p data,"%*s %d %*s %d",&frames,&adchan); printf("\nFrames: %d",frames,adchan); %d Channels: fscanf(p data,"%*s %*s %*s"); / *Input and total up the transducervalues */ for(i=O;i<frames;i++){ fscanf(p_data,"%f %f .f",&temp,&cal,&zero); for(h=0;h<13;h++){ fscanf(p_data,"%s1",datastr); sscanf(datastr,"%f",&datum); *(data+h)+=datum; 311 / *transducers*/ 30 printf("\n%.!f %.f'",datum,*(data+h)); */ I/ } fscanf(p.data,", /* %f",kpower,&level); /*power and level*/ printf("\ nd\n%d",power,level); */ iftadchan==2){ forj=Oj;i<16j++) 40 fscan(p_data,"/,*s"); / *auz/muz values*/ datum=0.0; } / *end frames loop*/ fclose(p_data); / *now average the transducer sums*/ for(h=O;h<13;h++){ datum=data[h]/(float)frames; data[h]=datum; } 50 / *get output file*/ printf("\nlnput name of output file (ex: dcl6zero.dat):"); scanf("%s",fileout); p out=fopen(fileout,"w"); / *put averagesinto file*/ for(h=O;h<13;h++) fprintf(p out,"%. 2f ",data[h]); 60 fclose(p_out); E.3 Programs for obtaining acetabular locations of pressure measurements E.3.1 For data from prosthesis 43 Iclude files for LOCATE43.EXE / $*$**** $***t **$************************I 312 / * kinemat.h /* */ include file for "locate" */ */ /* /* / Dec. 5, 1992 K.C. */ ***************************************/ #define NTRANS #define MAXSEG 10 13 tO typedefstruct angles { double phi; double theta; } ang; typedefstruct struct f angles { angles ang[NTRANS]; } femoralang; typedefstruct struct atrans { 20 angles ang; double mpa; }; typedefstruct a frame { struct a frame *next; /* For doublylinked list */ struct aframe *prev; double time; double flexion, abduction, extrotation;/ *clinicaljt angs at hip*/ struct a_trans alltrans [NTRANS]; / * phi,theta, and pressure */ float fpl.vert, fp2_vert; / *ScaledFP Y forces / } trans-a; / If using femoral view: no need to duplicatephi and theta / typedef struct f frame { 313 30 struct fframe *next; / * For creating a linked list */ struct fframe *prev; double mpa [NTRANS]; 40 ) transf; trans_a huge *aentry; / * anchorfor aframe list */ trans_f _huge *f entry; / * anchorfor fframe list */ femoral ang *ang; typedefstruct kineinfo { char name[12]; char descr[40]; char side; int nseg; /* File name */ /* Description*/ / $ Right or Left */ / * Numberof segmentscollected*/ int frames; /* frames of kinematic data taken*/ int synch frames; / *# of synched frames (w/pressure)*/ int nfp; /* # of forceplatesused */ 50 float wgt; double freq; / * frequency of kinematic data $/ double prosth tofemoralrot [NTRANS] [3]; / * Rot matriz - transducer*/ /$ position in femoral coordinates $/ double pelvistoacet rot [3][3];/* Rot matriz -pelvis to acet. */ float segvec [MAXSEG][3]; / * Segment vectors from kine header*/ float seg rot [MAXSEG][3][3]; /* Segment rot. matriz from T4header*/ 60 float arraypos [2][3]; float array_rot [2][3][3]; typedefstruct pzeros { float offset[16]; float gain[16]; 70 float tempcorr[16]; float temp; 314 / * Headerfile for use with programs that accessprosthesis / /*data files Jan. 17, 1990 #define GLOBAL * #define SEMIGLOBAL static #define IMPORT extern / /* used to define a semiglobalvariable*/ / * used to refer to a globalor semiglobalvar*/ referenced elsewhere */ #define SHORTSIZE 9 #define PATHSIZE 80 #define PROSTH IDSIZE 3 #define DESCR SIZE 32 #define DIRNAMESIZE 50 #define NAMESIZE 30 struct $/ 10 datainfo { 20 char name[9]; char id[3]; int samp; int adchan; int mult; int trig; char time[5][12]; char descr[32]; int startoff; int frames; 30so int alarmch; int synchch; double freq; int ntrans; / number of transducers */ 315 int date[3]; char hip; int synch-frames;/ * Numberof frames TSYNCHactive */ int binary; 40 SEMIGLOBALchar short dataname [SHORTSIZE]=-""; SEMIGLOBALchar prosthid [PROSTH IDSIZE] = ""; SEMIGLOBAL char description[DESCR SIZE] = ""; SEMIGLOBALchar namdir[DIRNAMESIZE]= ""; / * _ _ tlistruct.h / * From MGH /* 11/2s/92 _ */ $/ / / $_ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $/ #define DNAMESIZE 12 #define MAXDESCR 40 #define TIMESIZE 26 #define MAXLED 32 #define MAXCAM 2 #define MAXFP 2 #define KSCHAN 16 #define MAXSEG 10 #define NU_SUBJ PARS 48 #define MAX ECHN / * Really 2 * number of FP 's / 8 #define MAXEVENT 24 #define MAXLINE 10 #define TERMCAR 10 / * MADE THESE 2 UP */ 10 typedef struct { 316 20 char char char char char char char char char char duml; /* Dummy vairiables to be on even word boundary*/ char dum2; /* ditto float sord_raw; / smoothingfunction order for raw data */ float sord 3dp; float sord bcs; / *smoothingfunction order for dp data*/ / * smoothing function order for track data*/ float fltcut_fpd; / *lowpassfilter cutoff for fcplate*/ char data windo; / *Processingwindowflag*/ char char only_3dp; /* Compute D data only flag */ selspot_flag; /* CollectSelspot data char kistlerflag; char char char char analog-flag; /* collectKistler data */ / * collectAID dataflag / fpsideflag; / camlflag; /* first camera flat [1,2,3,4]*/ cam2 flag; / * secondcameraflat[1,2,3,] */ long badpoints; /* number of bad points */ long nbfplates; / number of forceplatesused / long nb_frames; / * numberof framescollected*/ long nb segment; /* number of selspot segments used $/ long nb channel; /* number of selspot channels used $/ long act framel; /* number of frames windowed (?) */ long f channels; / * numberof badchannels*/ long ftsegments; / * number of bad segments */ long sray badpt; / * badpoints due to skew ray error long f wframe; / * first frame of window*/ long l_wframe; / * last frame of windwo $/ long led segmnb[MAXI LED]; /* segment number for ea. channel?*/ float led xcoord[MAXL ED]; / *seg z-coord for ea channel*/ file raw[DNAMESIZE]; / * Name of originalraw */ dir raw[DNAMESIZE]; / * Directory of orig. raw */ file_segm[DNAMESIZE]; / * Segmentfile name */ description[MAXDESCR] / * Data description */ sampltime[TIMESIZE]; / * Time of data sampling*/ smooth_raw; / * Raw data smoothing flag*/ smooth 3dp; / * 3d data smoothing flag */ smoothbcs; / * BCS data smoothing flag */ filter_fpd; / * F'platefilteringflag */ 30 40 $/ forceplate to associatewith ?*/ 317 $/ 50 float led ycoord[MAXLED]; / *eg y_coordfor ea, channel*/ float ledrcoord[MAXLED]; / *seg zcoord for ea. channel*/ float campos[MAXCAM][3]; / *camerapositions*/ float fppos[MAXFP][3]; / * forceplate positions */ float cam_rotmtx[MAXCAM][3][3];/ *camerarot. matriz for et. cal.*/ float fp.rotmtx[MAXFP][3] [3];/ *fp rot matriz for est. calib. */ float focal_cam1; / *focallength camera 1*/ float focal cam2; / * focal length camera 2 */ float max ledvar; /* max seen inter-led error $/ float skewray mx; / * maz seen skew ray error / float frequency; / * frequency of collection */ float worstled; /* worst inter-LED length */ float globx_axis; /* global origin relocation */ float globy_axis; /* globalorigin relocation */ float globz_axis; /* globalorigin relocation */ float float fpxscl; fpyscl; /* forceplateX scalefactor */ / * forceplateY scalefactor */ float fpzscl; / * forceplateZ scalefactor */ float fp_zero[KSCHAN]; short iscal; short xseg[MAXSEG][10];/*segment descr. MEGATEK artifact / short yseg[MAXSEG][10];/* segment descr. MEGA TEK artifact */ short zseg[MAXSEG][10];/*segment descr. MEGATEK artifact */ char dum3; char dum4; /* dummyvar. */ float segvec[MAXSEG][3]; float seg rot[MAXSEG[3][3];/ *array to segment zform matriz float fxyz[12][3]; float subj_params[NUSUBJPARS]; short fs_dat[MAX_ECHN][2][MAX EVENT]; /*event marker record */ float rd[MAXSEG][3]; /*distal joint vector from crgeom */ float rp[MAXSEG][3]; /*prozimal joint vectorfrom crgeom */ float rcg[MAXSEG][3];/ segment cg vector from crgeom */ float float segmas[MAXSEG]; / segmentmassfrom dinert*/ seginert[MAXSEG][3]; / principalmomentsof inertia $/ float segintmat[MAXSEG][3][3];/ *moments of inertia rot matriz */ o0 70 / * forceplate zero offsets t1 /* segment file scale param - MEGATEK*/ so80 /* dummy var. to be on even word boundary / /*array to segment vectors / $/ /* fp segment description */ 318 /*age, ht, wt.,measurements*/ so } t4header; struct t4tree { char ciata[MAXLINE]; char F)arameter[MAXLINE]; char segment[MAXLINE]; char , rork[MAXLINE]; 100 struct t4terminal{ char liineup[TERMCAR]; char c learscr[TERMCAR]J; char c:lean int n b ines; int nb columns; page[TERMCAR]; 110 typedef struct{ char bytel, byte2, byte3, byte4; } Value; /* Functionprototypesfor locate49.c*/ FILE *select data (struct datainfo *, FILE *); char getview(FILE *); femoral_ang*f locate(struct datainfo *); struct fframe huge *get_mpamemory(struct datainfo *); void fstorprs (FILE *, struct datainfo*, transf huge **); void astor prs (FILE *, struct datainfo *, struct kineinfo*, transa huge **); void xform(FILE *,trans_a huge **, struct datainfo *, struct kineinfo *, femoral ang *, double); transa _huge*get angles(struct datainfo *, struct kineinfo *, FILE *, int, FILE *); void fwritetec (trans f_huge **, struct datainfo *, femoral ang *, FILE *); 319 10 void awrite tec (trans-a huge **, struct datainfo *, truct kineinfo *, FILE *); void freealist (transa huge **); void freeflist (trans.f huge **); void calc matrices (FILE *, struct dtainfo *, struct kineinfo * femoral.ang *); 20 void hipzxform(FILE *,double, double, double, struct kineinfo*, trans a huge *, truct datainfo *); void get dtl(struct kineinfo *, FILE *); void ang.calc(struct kineinfo *, transk huge **, struct datainfo *, FIL *, FILE *); int findsynch(FILE*,struct dataino*,int); trans a _huge *get memory(int); void hip.ang(float *, double *, double *, double *, char); void mgh ang (float *, double *, double *, double *, char); void mult matrices(float*, float *, float *, int, int, int); so LOCATE43.C /* Programto determine transducer locations /* and write locations and pressures to a file. /* File structure not yet determined. */ / */ $/ /* Dec. 2, 1992 K. C. $/ / $/ /* Feb 9, 1993: Changedto LOCATES4, just deal /* with data from 43. Make another verson to deal $/ /$ with 33 - just too many options right now. */ / ********************************************************/ #include #include #include #include <stdio.h> <stdlib.h> <sys\types.h> <sys\stat.h> 320 10 #include <string.h> #include <math.h> #include <errno.h> #include <malloc.h> 20 #include "pfile.h" #include "kinemat.h" #include "fnc.h" struct datainfo pinfo; struct kineinfo kinfo; void main(int argc,char *argv ) { 80 char view[2], reply[4]; double freq; int frames, syn_chan; struct datainfo *ppinfo; struct kineinfo *pkinfo; femoral ang *f a; char filepath[40]; char paramfile[40]; 40 struct stat *buffer; FILE *pfile; FILE *outfile; FILE *parfile; if(argc < 2){ printf("Enter file of processing parameters: "); scanf ("%s", argv[1]); so50 } strcpy(paramfile,argv [1]); parfile = fopen(paramfile,"r"); 321 /* For nowjust readsynch-channelout */ fscanf(parfile, "%d",&synchan); ppinfo = &pinfo; pkinfo = &kinfo; pfile = selectdata (ppinfo,parfile); * eo #ifdef _X_DEBUG outfile = fopen("debugx .dat","'"'); #endif fscanf (parfile,"%s ",view); / fclose(parfile);*/ fang = f locate(ppinfo); switch (view[O]) { case 'f': f entry = getmpamemory (ppinfo); fstor prs (p_file, ppinfo, &f entry); 70 break; case 'a': a_entry = getangles(ppinfo,pkinfo,p_file, syn_chan,parfile); if ((ppinfo->freq) < (pkinfo->freq)) freq = ppinfo->freq; else freq = pkinfo->freq; #ifdef _KJCPRINT_ printf("Freq = %li\n",freq); printf("'ant to go on?"); scanf("%s",reply); #endif xform (outfile, &a-entry, ppinfo, pkinfo, f ang, freq); #ifdef KJC_PRINT_ printf("Amback from xform"); #endif astor prs(pfile, ppinfo, pkinfo, 322 so &aentry); break; go #ifdef _XDEBUG fclose(outfile); #endif if (fentry == 0){ awrite_tec(&aentry, ppinfo, pkinfo,parfile); freealist (&aentry); } else o100 fwritetec(&f entry, ppinfo, f ang, parfile); freeflist (&f entry); } printf("Memory should be freed."); fclose(parfile); void freealist (transa huge "list) transa huge *hold; transa huge *current; 1lo current = *flist; while (current->prev) current = current->prev; while (current) { hold = current->next; hfree(current); current = hold; } 120 return; void freeflist (transf _huge **list) 323 { transjf huge *hold; transf .huge *current; while (current->prev) current = current->prev; while (current){ 1ao hold = current->next; hfree (current); current = hold; return; / * SELECT-D.C select_data - */ /* function to determine data set to /* look at. / / /* Dec. 2, 1992 $/ */ K.C. #include <stdio.h> #include <string.h> lo #include "pf ile. h" #include <malloc.h> FILE *select data(struct datainfo *p spec, FILE *parfile) { int pfreq,i; char dataname [NAMESIZE]; char shortname [7]; 324 char reply[3]; 20 char *dum; FILE *p dat; /* printf("Enter the complete name of file to look at: "); */ fscanf(parfile,"/,s",dataname); / Ask what format file is in */ / * printf ("Is this file in old MGH format? "); */ fscanf(parfile,"%s'",reply); if (reply[O] == 'y' /* 30 reply[O] == 'Y'){ printf("Is this file in binary format? "); */ fscanf (parfile,"%s",reply); if (reply[O] == 'y' 1[reply[0]== ''){ p dat = fopen (dataname,"rb"); dum = (char *)calloc(siseof(char),76); for (i=O;i<11;i++){ fread( dum, siseof(char),76,p_dat); } free(dum); 40o p_spec->binary = 1; strcpy(p_spec->id,"33"); p_spec->freq = 254; else { p_dat = fopen (dataname, "r"); fscanf (pdat, "%d %d",&p_spec->frames,&pfreq); fscanf (p_dat, "%d %d %2d%.*d",&p_spec->date[O], &p_spec->date[1], &p_spec->date[2]); sscanf (dataname,"U%6s",shortname); strcpy (p_spec->name, shortname); strcpy (p_spec->id,"33"); p_spec->freq = (double)pfreq; 325 so else { / * Start fillingdatainfo*/ p.dat = fopen(dataname,"r"); fscanf(p dat,"%,s %e",p spec->name,p fscanf (pdat,"%*, %* Y spec->id); Y s %l",&(p_spec->freq)); eo fscanf (p dat,"%*s %d",&(p_spec->frames)); #ifdef KJC PRINT printf (" %lf %d\n",p.spec->freq, p_spec->frames); #endif fscanf (pdat,"%*s %d",&(p_spec->adchan)); fscanf(p-dat,"%*s /* Leave p_dat at tart of data %*u %*a"); */ } if (strncrmp(p_spec->id,"33",2)==0) pspec->ntrans = 13; if (strncmp(pspec->id,"43",2)==O)p.spec->ntrans = 13; 70 return(p_dat); GETDTL.C /* getdtl--/$ /* function to get the .DTL file. Not sure yet what to read or how ..... */ /* /* */ / Dec. 9, 1992 */ K.C. /************************************** #include <stdio.h> #include <stdlib.h> 10 #include <string.h> #include <malloc.h> #include "pfile .h" 326 #include "kinemat.h" #include "t4istru.h" void getdtl( struct kineinfo *kinfo, FILE *finl) { 20 float nrec,fchn,frame,fseg,ddum; int index,rec,ireturn; t4header *lfile header; int iijj,kk,jk,retval; nt nseg l, side; int nframe; int nfp; int kscal; float wgt, freq, cutoff; 80 Ifile-header = (t4header *) calloc(1,(unsigned long)siseof(t4header)); /* Program was altered assuming a left leg - but should */ / w work for either. Need to determine ide, tore in kineinfo. */ retval = fread(lfileheader, (unsigned long)siseof(t4header),1,finl); if(retval){ nsegl = fileheader->nb segment; 40 kinfo->nseg = nsegl; nfp = lfileheader->nbfplates; kinfo->nfp = nfp; strcpy(kinfo->name, lfile header->fileraw); strcpy(kinfo- >descr, Ifileheader->description); printf("'This file contains data for: %s\n"',kinfo->descr); nframe = Ifile header->nbframes; #ifdef _KJC_PRINT printf ("The number of kinematic frames is: 327 Xd",nframe); #endif 60 kinfo->frames = nframe; kinfo->freq = (double) (lfile.header->frequency); #ifdef KJC PRINT printf (",%lf\n",kinfo->freq); #endif for (ii =0; ii < nsegl; ii++){ for(jj = 0; jj < 3; ij++)( kinfo->segvec[ii]Uj] = lfile.header->segvec[ii]j]; for(kk = 0; kk < 3; kk++){ kinfo->seg_rot[ii]ij][kk] = Ifile header->segrot 60 [ii] [j] [kk]; wgt = Ifileheader->subj_params[3]; kinfo->wgt = wgt; printf(" Subject weight is: printf(" Subject height is: %.f\I", wgt); %f\zn", lfile_header->subj params[2]); free (file header); return; } FLOCATE.C 1/* flocate -- * function to get femoral /$ I/* /. locationsfrom file /. prosthesisserial # ID.ang (where ID is *1 *1 *1 *1 /* Dec. 2, 1992 K.C. 328 70 / **********#*************$$*$*$$*$****/ 10 #include <stdio.h> #include <string.h> #include <malloc.h> #include "p.f ile. h" #include "kinemat .h"femoralang *f locate (struct datainfo *pinfo) FILE *angfile; char angname[20]; 20 int i; f ang = (femoralang *)fcalloc (1, (unsigned long)siseof(femoral ang)); /* Get the file name with the femoral locations */ strcpy (angname, pinfo->id); strcat (angname,". ang"); /* Read the femoral locations of transducers / /* phi is latitude; theta is longitude 30 */ angfile = fopen (angname, "r"); for (i=O;i<pinfo->ntrans;i++){ fscanf (angfile,"%lf %if,&(:fang->ang[i].phi), \ &(f ang->ang[i.theta)); #ifdef_KJC_PRINT_ printf("%lif, %lf\n",fiang->ang[i].phi, f ang->ang[i].theta); #endif 40 } fclose(angfile); return(f ang); 329 } FINDSYN.C /**************************** /* find_synch --- *********/ */ function to determine how many synched /* /* frames there are in a pressure data file (.INT) */ /* Synchis TRACK synchsignal. May as well start /* reading the file, store the information, leave */ /* file pointer at the start of first synchedframe*/ /* */ $/ Dec. 23, 1992 * K.C. /~t*$$$$*$******$*$$**$*$**$$*$**$*$$$$*$* $**/ 10 #include <stdio.h> #include <stdlib.h> #include <errno.h> #include "pfile.h" #include "kinemat .h" int find-synch (FILE *prsfile, struct datainfo *pinfo, int sync) char sdata[lOj; 20 int syn chan, idata, sumframes; int i, j, retval, skip, frames; fpos t *begin; fpost *hold; /* prsfile was left at start of data by "select_data" $/ sum frames = O; retval = fgetpos(prsfile, begin); #ifdef _KJC PRINT_ 30 printf("begin = %ld\n", *begin); #endif 330 if (pinfo->adchan < 2) { printf ("This data did not have synchronizing signal."); abort; else { syn chan = sync; synchan += 6; if (synchan > 15) synchan = syn chan - 16; 40 } frames = pinfo->frames; for (i=O; i<frames; i++){ retval = fgetpos (prsfile, hold); #ifdef _KJC_PRINT if (i<10) printf("hold = %ld ", *hold); #endif for (j=O;j<18; j++){ 50 fscanf (prsfile,"'%*s"); } if (pinfo->adchan == 2){ /* HADBETTER BE!!!*/ forj=Oj<16j++){ if (j==synchan){ fscanf(prsfile,"%s",sdata); == ,,){ if (sdata[O] ' '; sdata[O]= sscanf(sdata, "Y.d",&idata); else fscanf (prsfile,"Y%*s"); #ifdef _KJCPRINT if (i<10) printf ("frame: #endif } 331 %d; Yd\n",i,idata); so if (idata < 50){ 70 sum-frames++; if (sumrnames==1) *begin = hold; #ifdef _KJCPRINT printf("begin - %ld\n", *begin); #endif /* This is where to start aving data*/ / , Reset the file pointer to tart of data want to read '/ } so #ifdefKJC_PRINT_ printf("begin = %ld\n", *begin); #endif retval = fsetpos(prsfile, begin); printf ("synched frames Y\n",sumframes); pinfo->synchframes = sumJframes; return(sumframes); 90 * /$ / /* GETANGL.C get-angles --- / function to get the .DTL file. Not ure */ /" yet what to read or how..... will read .dtl file "/ /"' in a ubfunction (cut-down version of process from "/ /* MGH), decide on frequency to use, allocate memory */ /* /* for the transa tructure,and calculatejoint angles and tore them in transa tructure. / / /' Also, try to read .FPD file if it iJ available /o */ 332 / / o10 /+4, Dec. 9, 1902 K.. #include <stdio.h> #include <string.h> #include <malloc.h> #include "p.file.h" #include "kinemat.h" 20 #include "t4istru.h" #include "ifnc.h" trans a huge get angles(struct datainfo *pinfo, struct kineinfo *kinfo, FILE *prsfile,int sync, FILE *parfile) FILE *ddata, *f data; char dataname[80],fpdname[80]; char leg[5], side[5]; int i, nframe, synch frames; so /* Get the file name '*/ /* printf("Enter the name of file to look at (no eztension): ");*/ fscanf(parfile,".s",dataname); printf("%s\n',dataname); strcpy(fpdname,dataname); strcat(fpdvame," .fpd"); /$ prsntf ("Is thiu right or left leg data? ");*/ fscanf (parfile,"%s",leg); 40 kinfo->side = leg[O]; if (leg[O]== 'L' II leg[O]== '1') strcat(dataname,".dtl"); if (leg[O] == 'R' Ileg[O] == 'r') strcat(dataname," .dtr"); ddata = fopen(dataname,"rb"); get_dtl(kinfo, ddata); 333 /' Decide whether to use TRA CK or pressurefrequency /4* Perhaps don't want to do this here... / .... Need to account for non-synchronicity of TRACK */ /* and pressure data - need to find TSYNCH signal in .INT */ /* file and figure out how to synchronize the two sets */ /* of data. It won't affect much here, ezcept the memory */ /* allocatation. (TRACK always tarts after pressure) */ /* Need to know - which pframe to tart on, how many frames*/ /* it is active for. /* /* *! / so */ Having memory troubles- need to read the TRACK data a frame at a time instead. */ *! eo synchbframes = findsynch (prsfile, pinfo, sync); if (pinfo->freq < kinfo->freq){ nfamne = synch frames; pinfo->synch frames = nframe; } else ( if ((synchframes/pinfo->freq)< (Iinfo- >frames/kinfo->freq)){ nframe = synch frames/pinfo->freq * kinfo->freq; 70 else nframe = kinfo->frames; kinfo->synchjframes = nframe; /* Allocatememoryfor transa structure $/ a_entry = get memory(nframe); /* Calculatethe angles so f data = fopen(fpdname,"rb"); angcalc(kinfo, &a_entry,pinfo, ddata, f data); #ifdef_JC_PRINT. 334 printf("Backin get.angles.n"); #endif fclose(d data); fclose(f data); return(aentry); ANGCALC.C /* /* * ang calc --function to calculate the clinical / */ /* joint angles. UseJ Groodand Suntay /* formulation, from Pat Lord. May also do /* Tupling and ? as at MGH - for comparison */ /* Dec. 22, 1992 K.C. */ 10 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <math.h> #include "p_file.h" #include "kinemat.h" #include "inc.h" void ang calc (struct kineinfo *kinfo, trans a huge **aentry, struct datainfo *pinfo, FILE *fdata, FILE *fpdata) char side,reply[4]; int skip, kframe, curframe, num, nip; 335 20 int i, j, k, 1, nframe, iside, ioint, nseg, nsynch; float smt[2][4][4];/* Check dimensions ???? */ float smt2[2][3][3]; float segrot [2][3][3];/ * Store only for the two float seg_vec[2][3]; $/ /* around the joint of interest */ float array.pos [2][3];/ Array position '/ 80 float arrayrot [2][3][3];/ * Array rot. */ double f,a,e; double *flex, *abd, *extrot; double bad, tinle, rem,freq; float *psmt2, *psegrot, *parrayrot, *psmt; float *data hold, *data; float *fpd; float wgtnt; double *skipptr, kf; trans a huge *base; transa 40 huge *hold; transa huge *current; /* For linked list $/ FILE *debug; #ifdef _KJC_DEBUG_ debug = fopen ("debugang.dat","w"); #endif bad = -1000.0; 50 nsynch = 0; side = kinfo->side; if (side == 'L') iside = 2; else iside = 1; nfp = kinfo->nfp; ijoint = 3; / * Hope this is the right answer! Want the hip joint*/ nseg = kinfo->nseg; base = *aentry; /* Set up linkedlist */ current = base; curframe = 0; 60 336 data = (float *) calloc (16*nseg, siseof(float)); datahold = data; if (fpdata != NULL)fpd = (float *) calloc(6*nfp,siseof(float)); wgtnt = kinfo->wgt * 9.8/2.2; /* wt. in lbs -> wt. in Newtons */ skipptr = &kf; flex = &f; abd = &a; extrot = &e; /* Set all of smt to 0.0 */ 70 for =0;j<2;j++){ for (k=;k<4;k++){ for (1=0;1<4;1++){ smtLi][k]p] = 0.0; } } for (k=0;k<3;k++){ for (1=0;1<3;1++){ arrayrot[j][k]p] = 0.0; 80 } arrayposU][k] = 0.0; } } /I 1* Fill the segment vector and rotation matrices */ from kineinfo structure. ,/ I, Assume the segments of interest (femur, pelvis) */ 1, are segments S and 4 ,/ 90 Transposethe segment rotation matrices now in $/ /, preparationfor matriz multiplication for (k=2;k<4;k++){ $/ /* Segmentloop */ for (i=O;i<3;i++){ segvec [k-2][i] = kinfo->seg-vec[k][i]; 337 for j=Oj<3j++){ segrot[k-2] [j][i]=kinfo->seg_rot[k][i] j]; '} /~*Now 100 eztract the array position and rotation matrices*/ /* from the stored data. 16 numbers per segment per frame /* Order - array position, 4 unidentified #'s, array rot. */ */ Deal with interpolation at this point if pfreq < kfreq */ #ifdef X DEBUG_ printf("kfreq = %if\n",kinfo->freq); 110o printf("pfreq = %f\n",pinfo->freq); printf("ksync = %d\n",kinfo->synch frames); printf("psync = %d\n",pinfo->synchframes); #endif if (pinfo->freq < kinfo->freq) { skip = 1; nframe = pinfo->synch frames; freq = pinfo->freq; else { 120 skip = 0; nframe = kinfo->synch frames; freq = kinfo->freq; } for (i=O;i<nframe;i++){ if (skip){ time = ((double) i)/ freq; rem = modf((time * kinfo->freq),skipptr); kframe = (int)(time*(kinfo->freq)); if (rem > 0.5) kframe++; 'ifdef _KJC_PRINT 338 lao %d\n',kframe); printf ("kframe #endif if (kframe > kinfo->frames){ printf("kinematic data exceeded\n"); scanf("%,s",reply); fread(data,siseof(float),16*nseg,fdata); if (fpdata != NULL) 140 fread(fpd,siseof(float),6*nfp,fpdata); #ifdef _KJCPRINT_ printf ("Read 1"); #endif for (j=curframe;j<kframeu;++){ /* */ Increment pointer past the tuff don't want to use num =fread(data,siseof(float),16*nseg,fdata); if (fpdata != NULL) fread(fpd,sizeof(fioat),6*nfp,fpdata); /* 150 Increment curframe now for nezt i-loop */ curframe = kframe+1; else { fread(data,sizeof(float), 16*nseg,fdata); if (fpdata != NULL) fread(fpd,siseof(float),6*nfp,fpdata); data += 16*2;/ Increment pointer to femoral array(seg3)*/ for (j=Oji<2j++){ /* Segment loop / for (k=0;k<3;k++){ array-posl][k] = *data; ++data; } data+=4; / Pass the 4 unidentified numbers */ for (k=O;k<3;k++){ for (1=0;1<3;1++){ 339 160 arrayarotj][k][l] = *data; data++; 170 data = data hold; /* Multiply the array orientation matriz into body segment coord.*/ for j=0<2j++){ / * Segment loop*/ psmt2 = &smt2[j][O][0]; psegrot = &seg-rotj][0][0]; parrayrot = &arrayrotu][0][0]; 180 if (arrayposj][O]!=bad && array.posj][1]!=bad && array-poslj][2]!=bad){ mult matrices(psegrot,parrayrot,psmt2,3,3,3); for (k=O;k<3;k++){ for (1=0;1<3;1++){ smt[] [k]]=smt2j] [ [1]; ] /* printf(" f ", mt[j]k]fl]);*/ } smt[j][k][3] = 0.0; /* printf("oAn",mt[j]lk][ ]);*/ 190 for (1=0;1<3;1++){ smtlj][3][R] = 0.0; /* printf("%f ",asmt[j][9fl]);*/ smti][3][3] = 1.0; / Good data /* printf( */ ",Jmt[j][s][s]); /;* } else smt[j][3[3] = 0.0; /* Bad data */ printf("An"smt[j][s][s]);*/ / 340 200 /* Do angle calculation elsewhere */ psmt = &smt[Oj[O][O]; #ifdef _KJC_PRINT printf ("Going to hipang\n"); #endif /* 210 hip.ang( psmt, fez, abd,eztrot, ide); / mghang( psmt, flex, abd, extrot, side); #ifdef _KJC_DEBUG fprintf(debug,"%lf %lf %lf\n",*flex, *abd, *extrot); #endif if (*flex !=bad && *abd!=bad && *extrot!=bad) { /* Store in a trans */ current->flexion = *flex; current->abduction = *abd; = *extrot; current->extrotation 220 current->time = ((double) i)/freq; /* Scale the FP data by 100/body wt in Newtons (as at MGH) */ if (fpdata != NULL){ fpd++; current->fpl vert = -(*fpd)*100./wgtnt; fpd+=6; current->fp2vert = -(*fpd)*100./wgtnt; fpd-=7; 230 nsynch++; /* Set up the linked list and update "current" */ hold = (transa _huge *)halloc (1, ( unsigned long) iseof(trans_a)); if (NULL== hold){ printf("Out of memory"); while (current->prev){ hold = current->prev; 341 240 hfree(current); current = hold; } hfree(current); free(data); abort; current->next = hold; hold->prev = current; hold->next = NULL; 250 current = hold; } free(data); if (fpdata != NULL) fee(fpd); pinfo->synch frames = nsynch; kinfo->synchframes = nsynch; #ifdef_KJCDEBUG felose(debug); #endif 260 return; } MGHANG.C /$ * /$. Function to get flez, abd, eztrot /* */ array orientation in body egmen */ /$ *given / */ hip_ang --- coordinates. Dec. 22, 1992 */ */ K.C. 10 #include <stdio.h> 342 #include <math.h> #include <errno.h> #include "pfile.h" #include "kinemt .h" #include '"nc.h" #define PI 3.1415927 #define BAD -1000.0 20 void mgh ang (float *psmt, double *flex, double *abd, double *extrot, char side) { int i, j, k, l; float smt[2][4][4]; float distal[3][3]; float proximal[3][3]; float result[3][3]; float *dist, *prox, *res; double fvect [3],numerator,denominator; o30 double scale = 1.0; double flexion,abduc, extrotation,factor; if (side != 'R') scale = -1.0; /* Fill mt - too lazy to keep track of pointer */ for (i=O;i<2;i++){ for (j=0;<4j++){ for (k=O;k<4;k++){ smt[i]U][k]= *psmt; psmt++; /* 40 Checkfor bad data if ( (smt[0][3][3] == 0.0) II (smt[1][3][3] == 0.0))( *flex = BAD; 343 *abd = BAD; *extrot = BAD; return; /* so Transposethe prozimal matrix in prep for matriz mult. */ for (i=O;i<3;i++)( for (j=Oj<3++)( distal[i]j] = smt[O][i]U[j]; proximalj][i] = smt[1][i]li]; result[i]llj] = 0.0; eo0 dist = &distal[O][O]; prox = &proximal[O][O]; res = &result[OI[O]; /* /* Here - switch to MGH formulation of angles */ Wasn't too sure of answers I was getting with */ MIT formulation. 70 multimatrices( dist, prox, res, 3,3,3); abduc = asin(result[l][2]); /* printf("%lf%An",abduc,result[l][2]);*/ if (abduc!= (P1/2.) &&abduc!= (-PI/2.)){ factor = (double) result[l][O]/cos(abduc); if (factor < -1.0) factor = -1.0; if (factor > 1.0) factor = 1.0; flexion = asin(factor) * scale; if (result[l][1] < 0.0) flexion = PI - flexion; if (flexion > PI) flexion = flexion - 2*PI; factor = (double) result[O][2]/cos(abduc); if (factor<-1.0) factor = -1.0; if (factor > 1.0) factor = 1.0; 344 so extrotation = asin(factor); if (result[2][2]< 0.0) extrotation = PI - extrotation; extrotation = extrotation * scale; if (extrotation > PI) extrotation = extrotation - 2*PI; } else ( extrotation = 0.0; 90 flexion = asin((double)result[0][1]); *flex = flexion*180.0/PI; *abd = abduc*180.0/PI; *extrot = extrotation*180.0/PI; #ifdef _KJCPRINT fprintf (".1f %1!l%1f\n", *flex, *abd, *extrot); #endif return; 100 XFORM.C *form ----/ /* function to transformtransducer /* */ /* locations into acetabular locations. */ /* Clinicaljoint anglesare obtainedearlier */ /* and are stored for eachframe in the transa */ /* structure. Joint angles are from GroodL */ Suntay defn's. */ */ /* /* Bulk of the program from TRANS(in FORTAN*/ /* by Bob Fijan and me - but may be significant /* alterations for use with left as well as right */ /$ hips and becauseam working from notes made $/ /* a couple years ago - reworked TRANS and found */ /$ some bugs/better ways to do things. / */ /$ 345 10 / */ /~ Dec. 10, 1992 / K.C. ************************ / *+********* / 20 #include <stdio.h> #include <math.h> #include <errno.h> #include "pfile .h" #include "kinemat.h" #include "inc.h" #define PI 3.1415927 void xform (FILE *outfile,transa huge **aentry, struct datainfo *pinfo, struct 80 kineinfo *kinfo, femoral ang *f ang, double freq) { char hip, reply[4]; int i, j, frames; trans_a _huge *base; transa _huge *current; transa _huge *hold; double flex, abd, rot; double phi,theta; 40 base = *a entry; current = base; hip = pinfo->hip; if (pinfo->freq > freq ) frames = kinfo->synchframes; else frames = pinfo->synchframes; #ifdef KJC_PRINT_ printf("frames = %d; ksynch = %d; psynchf = %d\n",frames, kinfo->synch frames,pinfo- >synchframes); so scanf("%s",reply); #endif /* First calculate the matriz products that 346 /* /f */ are constantfor allframes. pos. acetab.= [clcl [c][positionmatnal ha fh f ps */ proath '/ calcmatrices (outfile,pinfo, kinfo, fang); / Convert to radians / ao for (i=0O;i<frames; i++){ flex = current->flexion * PI/180.0; abd = current->abduction * PI/180.0; rot = current->extrotation * PI/180.0; hip form (outfile, flex, abd, rot, kinfo, current, pinfo); #ifdef _KJC_PRINT printf (".d, flex = %.lf\n",i,flex); #endif hold = current->next; 70 if (hold == NULL){ printf("gone off end of list\n"); return; else current = hold; return; so HIP.XFOR.C /* /* 1 --hip_zform function to transformtransducer /* locations into acetabular locations. /* Clinicaljoint angles are obtained earlier $/ / 347 */ /* and are stored for each frame in the trana $/ /* structure. Joint angles are from GroodU */ /* Suntay defn'. */ /* */ /* Bulk of the progrumfrom TRANS(in FORTAN*/ /* by Bob Fijan and me - but may be significant */ /* alterationsfor use with left as well as right */ /* hips and becauseam workingfrom notes made */ /* a couple years ago - reworked TRANS and found */ /* some bugs/better ways to do things. */ /* ,/ /* /* 10 $/ Dec. 10, 1992 K.C. */ / ***********************$$$**************/ 20 #include <stdio.h> #include <math.h> #include <errno.h> #include "pfile.h" #include "kinemat.h" #define PI 3.1415927 void hip_xform (FILE *outfile,double flex, double abd, double rot, struct trans_a _huge *current, struct kineinfo *kinfo, 30 datainfo *pinfo) { char hip,reply[4]; double u[3],c[3][31,rad,theta; double f[3],a[3],c2[3][3]; int ij; hip = kinfo->side; for (i=O;i<2;i++){ for j=O;i<2j;++){ 40 c[i]j] = 0.0; 348 c2[i]j] = 0.0; } u[i] = 0.0; f¢i]= o.o; e[i] = 0.0; /* Calculatethe rotationmatrizfirst * / * Worked this out for a right leg in 2/90 ...is also different / /* from TRANS. so */ c[0][0] = cos(rot)*cos(flex); c[O[1] = cos(rot)*sin(fiex) + sin(rot)*sin(abd); c[0][2]= sin(rot)*cos(abd); if (hip == 'L') c[0][2]= -c[O][2]; c[l][0] = -cos(abd)*sin(flex); c[l][1] = cos(abd)*cos(flex); c[1][2] = -sin(abd)*cos(flex); 60 if (hip == 'L') c[1][2]= -c[1][2]; c[2][0]= -sin(rot)*cos(flex); ¢!2][1]= -sin(flex)*sin(rot) + cos(rot)*sin(abd); c[2][2 = cos(iot)*cos(abd); if (hip == 'L'){ c[2][0] = -c[2][0]; c[2][1]= sin(fiex)*sin(rot) - cos(rot)*sin(abd); #ifdef XDEBUG_ 70 fprintf(outfile,"Rotationmatrix: for (j=O;j<2;j++){ fprintf(outfile,"%lf, femoral to hip\n"); %lf, %lf\n",c[O]],c[1][j],c[2][j]); } #endif 349 /* Now get c (pelvisto.acet rotation matriz) from kineinfo */ for (j=Oj<3j++){ 80 for (i=0O;i<3;i++){ c2U] [i] = kinfo->pelvisto.acetrotj] [i]; } } /* Now rotate for each transducer */ for (j=O;j<pinfo->ntransj++){ for (i=0;i<3;i++){ f[i] = kinfo->prosth_to femoralrotlj][i]; /* 90 if (j==2) printf("f[%d]= %Ifn",i,f[i]);*/ /* Now need to go into pelvis coordusing the clinical $/ /* joint angles. Assume angles in radians. */ u[O] = c[0][O]*fO] + c[1][0] * 41] + c[2][0] * 42]; u[I] = c[0][1]* f0] + c[1][1]* 41]+ c[2][1]* f2]; u[2] = c[0][2]* f[0] + c[1][2]* f1] + c[2][2]* f[2]; 100 #ifdef_XDEBUG fprintf(outfile,"Point %d\n"j); fprintf (outfile,"Pelvis coord: %lf, %lf, %lf\n",u[O],u[1],u[2]); #endif /* /* Now changeto acetabularcoordinates */ /* in pelvisto_acetrotin structurekineinfo*/ /* Transposedrelative to the previous matriz */ Use the rotation matriz calculatedin calc matrices and stored */ a[0] = c2[0][0o]* u[o] + c2[0][1] * u[l] + c2[0][2]* u[2]; 350 110 a[l] = c2[1][0]* u[O]+ c2[1][1]* u[1] + c2[1][2]* u[2]; a[2] = c2[2][0] * u[O] + c2[2][1] * u[1] + c2[2][2] * u[2]; #ifdef X_DEBUG_ fprintf(outfile,"Acetabular coord: %lf , %f, %lif\n",a[O],a[1],a[2]); #endif /* Now change[a] into an acetabularphi and theta and store as degrees */ /* For a left hip, phi measuredfrom pos Za azis -- 120 so change sign there*/ if (hip == 'L') a[2] = - a[2]; current->alltranslj].ang.phi = (acos(-1 * a[2])) * 180./PI; rad = sqrt((a[O]*a[0]+ a[l]*a[l])); theta = acos((a[0]/rad)) * 180./PI; if (a[l] < 0) theta = -theta; current->alltrans[j].ang.theta = theta; if (a[0] > 0. 0){ /* current->alltrans[j].ang.theta = atan2(a[1],a[2])*180./PI; 130 else { current->alltrans[j.ang.theta= atan2( a[O],a[l]) * 180./PI; } */ #ifdef XDEBUG fprintf(outfile,"Acetabularphi, theta: %lf, %lf\n",\ current->alltrans[j].ang.phi, current->alltrans[j].ang.theta); #endif 14o return; * CALCMAT.C / ********************************************************/ / /* calcmatrices */ Calculatesthe constant matrices 351 */ /$ I* 1* and stores their product in the kineinfo */ structure. */ */ 1* 1* 1* 1* 1* 1* I* Bulk of the programfrom TRANS(in FO RTAN/ by Bob Fijan and me - but may be significant */ alterationsfor use with left as well as right */ hips and becauseam workingfrom notes made */ a couple years ago - reworked TRANS and found */ some bugs/better ways to do things. $/ */ Dec. 10, 1992 */ /~ /* K.C. #include <stdio.h> #include <math.h> #include <errno.h> 10 20 #include "pf ile .h" #include "kinemat.h" #define PI 3.1415927 void calc matrices ( FILE *outfile, struct struct datainfo *pinfo, kineinfo *kinfo, femoral ang *f ang) char hip; so int i, j; double phi, theta,dtr,rtd; double angle[6]; /* Need to allow to be different*/ /* May want to put in datainfo $/ Assumeare in radians $/ double u[3],s[3],c[3][3[3],tan,tan2,tan3; double f3],a[3]; hip = kinfo->side; 352 dtr = PI/180.; 40 rtd = 180./PI; angle[O] = 25.0*dtr; angle[l] = 7.0*dtr; angle[2] = 10.0*dtr; angle[3] = O.O*dtr; angle[4] = 20.0*dtr; angle[5] = 30.0*dtr; for (i=0;i<6;i++){ if ((angle[i]== PI/2.) 11(angle[i]== -PI/2.)) angle[i] = (angle[i] - .001); so50 } #ifdef _XDEBUG fprintf(outfile, "%c\n",hip); #endif /* /* /* First calculatethe matriz productsthat are constantfor allframes. /* ha h f ps Convertto radians prosth Calculate matriz for transformation into femoral coordinates eo */ / /* found errors there, (at least I think */ /* they wereerrors */ /* Uses anglesthat define prosthesis */ /$ orientationin femur /* / */ This part majorly revised from TRANS - /$ $/ pos. acetab. = [c] [c] [c] [c] [position matriz] /* /* */ */ Note that Zfemoral points laterally for a right hip $/ */ but mediallyfor a left hip. /$ Matriz notationis transposeof that usuallyuse, just */ /* happenedto write that way when calculatingelements / tanl = tan(angle[1]); 353 70 tan2 = tan(angle[2]); tan3 = tan(angle[3]); c[l][l] = 1.0/(sqrt(1.9 + tanl*tanl + tan3*tan3)); c[l][0] = -tan3 * c[l][1]; c[1][2] = tanl * c[l]l1]; if (hip == so 'L') c[1][2] = -c[1][2]; c[2][2] = 1.0 /(sqrt(l.0+ tanl*tanl + tan2*tan2)); c[2][0] = tan2 * c[2][2]; c[2][1] = -tanl if(hip== c[2][21; 'L'){ c[2][O] = - c[2][0]; c[2][1] = - c[2][1]; } c[0][O]= c[l][1]* c[2][2]- c[1][2] * c[2][1]; c[0][1] = c[1][2] * c[2][0] - c[1][0] * c[2][2]; c[0][2]= c[1][0]* c[2][1] - c[l][l]*c[2][0]; /* Calculatethe positionmatrizfor transducers*/ for(j=O; j<pinfo->ntrans; j++){ phi = fang->angj].phi * PI/180.0; loo theta = fang->ang[j].theta * PI/180.0; /* Define a vector from center of prosthesis head to / /* the point in question in prosthesis coordinates */ /* Let theta = 0 define X directionfor a R hip */ /* Let theta = 180 define X for a L hip /* Let theta = 90 define Y in both cases /* u[S] ends up pointing in opp. direction */ if (hip == 'R'){ / $/ llO u[O] = sin(phi) * cos(theta); 354 u[2] = -cos(phi); } if (hip== 'L) u[O]= -sin(phi) * cos(theta); u[2] = cos(phi); } u[1] = sin(phi) / $ /* * in(theta); Go to "stem" coordinatesnezt */ 120 Use the angle[0]- of head to tem */ s[O] = u[O]; if (hip == 'R') s1] = u[1] * sin(angle[O])- u[2] * cos(angle[O]); s[2] = u[1] * cos(angle[O]) + u[2] * sin(angle[O]); } if (hip== 'L') ({ s[l] = u[1] * sin(angle[O]) + u[2] * cos(angle[O]); s[2]= - ul] * cos(angle[O]) + u[2]*sin(angle[0]); 130 } /* Now transform into femoral coordinates /* Use matriz calculatedabove. */ */ f[0] = c[0][0]* s[0] + c[1][0] * s[1] + c[2][0] * s[2]; ff1] = c[0][1]* s[O] + c[1][l] * S[1] + c[2][1] * s[2]; f2]= c[0][2]* s[O]+ c[1][2] * s[l] + c[2][2] * s[2]; #ifdef X_DEBUG 140 fprintf(outfile,"Point %d\n"j); fprintf(outfile," Prosthesis fprintf(outfile," Stem coord: coord: %lf, fprintf(outfile," Femoral coord: %lf, %1f, %lf\n",u[O],u[1],u[2]); %lf, %lf\n",s[O],s[1],s[2]); %lf, %lf, %lf\n",ff[],f[1],[2]); #endif / $ Store this information in kineinfo in prosth_tofemoral_rot*/ 355 for (i=O;i<3;i++)( kinfo->prosth to femoralrotuj][i] = f[i]; } 150 } /* Calculate the rotation matriz between the pelvis coordinates*/ /* and the acetabular coordinates */ c[0][0] = cos(angle[4]); c[0][1] = 0.0; c[0][2] = -sin(angle[4]); c[2][2] = 1.0+tan(angle[4])*tan(angle[4])+tan(angle[5])*tan(angle[5]); 16o c[2][2] = 1.0 / sqrt(c[2][2]); c[2][0] = tan(angle[4]) * c[2][2]; c[2[1] = -tan(angle[5]) * c[2][2]; if (hip == 'L') { c[2][0] = -c[2][0]; c[2][1]= -c[2[1]; c[0][2] = -c[0][2]; } /* Yes, OK to do here, signs work out the same $/ 170 c[l][0] = c[2][1] * c[0][2] - c[2][2] * c[0][1]; c[1][1] = c[2][2] * c[0][0] - c[2][0] * c[0][2]; c[1][2] = c[2][0] * c[0][1] - c[2][1] * c[0][0]; #ifdef XDEBUG_ fprintf (outfile,"Rotation matrix: for (i=0;i<3;i++){ fprintf(outfile,"%lf, hip to acetabular\n"); %lf, %li\n',c[O][i],c[l] [i],c[2][i]); #endif 180 for (i=O;i<3;i++){ 356 for (j=O0;<3j;++){ kinfo->pelvistoacet.rot[i][] c[i]Lj]; return; 190 MULTMAT.C /* mult matrice--- / /* function to multiply two matrices. /* Probably should make it general - is taking /* the place of GMPRD - old Fortran subroutine */ */ /* /* */ Dec. 23, 1992 K.C. */ / *********************************$*** #include */ <stdio.h> 10 #include <math.h> void mult matrices (float *ml, float *m2, float *mresult, int rowl, int coll, int co12) { int i, j, k; float *basel, *base2, *baser; #ifdef _KJCPRINT_ 20 printf("hi. \n"); #endif basel = ml; base2 = m2; baser = mresult; 357 for (i=O;i<rowl;i++){ for (j=Oij<col2;j++){ *mresult = 0.0; for (k=O;k<coll;k++){ 30 *mresult = *mresult + (*ml)*(*m2); ml++; m2 += col2; mresult++; ml -= coll; m2 -= coll*col2; m2++; /$ set at start of nezt column $/ 40 ml +=coll; /* et ml at tart of nezt row / m2 -= coI2; /* set m2 at start of first column */ } ml = basel; / * Returnpointersto start position */ m2 = base2; mresult = baser; return; } ASTOR-PR.C / **$*********$**~~$*d~ *****~$$$$*******************/ /,$ /* astorprs --- *1 function to read .PRS files in the *1 new data format and transfer /$ /$ /* /* /$ /* the data to transa linked list. Should give *1/ option of normalizing as well (w.r.t BW/H^2?) Dec. 8, 1992 K.C. 5/ / ***********$**********************************/ 358 10 #include <stdio.h> #include <errno.h> #include <math.h> #include "pfile .h" #include "kinemet.h" #define PSITOMPA 0.0068948 #define END 10000 /*Define END a number will never get more frames than'/ 20 void astor prs (FILE *prsfile, truct datainfo *pinfo, struct kineinfo *kinfo, trans a buge **aentry) char sdata[10], reply[4]; int i, j, k, skip, pframe, kframe, frames, curframe; trans a huge *base; transa huge *hold; transa huge *current; double time, rein; 30 double pf, *intptr; double data; base = *a entry; current = base; intptr = &pf; data = 0.0; /* Read the data then convert to MPa /* Read.INT files - alreadyin psi */ */ /* Only deal with 43 for now! Requires lots of */ /* changesif alterlater. */ /* File pointer is set at first synched frame */ /* Read only the synched frames. */ 359 40 /* Need to deal with skippingframes here if kfreq */ /* is less than pfreq (else in get.dtl and xform) */ if ( kinfo->freq < pinfo->freq){ so skip = 1; frames = kinfo->synchframes; curframe = 0; else { skip = 0; frames = pinfo->synch frames; } for (i=O;i<END;i++) { time = current->time; so rem = modf ((time * pinfo->freq), intptr); pframe = (int)(pf); if (rem > 0.5) pframe++; if (skip){ for (k=curframe;k<pframe;k+) /* Remember - this is set for prosth #4 { */ for (j=O;j<18;j++){ fscanf(prsfile,"%*f '); } 70 if (pinfo->adchan == 2)( for j=O;j<16j++){ fscanf (prsfile,"%*d"); curfame = pfame+l; /*Increment curframe nou/ for (i=0;j<18; j++){ if (j>2 &&j<16 &&j!=6){ " fscanf(prsfile, "%s ,sdata); if (sdata[O]== '*') sdata[O]= '; 360 so sscanf(sdata,"%1i ",&data); data = data * PSITOMPA; current->alltransj-3].mpa = data; data = 0.0; else fscanf (prsfile,"%*f"); } if (pinfo->adchan == 2){ g0 for=0;j<16j++){ fscanf(prsfile,"%*d"); #ifdef _KJCPRINT if (i<10) printf("%d\n",i); #endif hold = current->next; loo current = hold; if (current->next == NULL){ i = END-1; } /* Close the file */ fclose(prsfile); return; / * AWRITET.C ~~~~~/$ awritetec -- - /$ writes output file suitable for entry to /* Tecplot (I hope!). This version writes acetabular info */ /* writes: t, trans#, phi, theta, and pressure (MPa) */ */ / 361 /* Now also writes two other files - joint angles and /* forceplate data. Need to figure out not to write these */ / files if that data wasn't available. */ ~~~~~/,~~~~~~~~~~~~~ ,~~/ /$ / */ Dec. 28, 1992 o~~10 * K.C. ****************************************************************/ #include <stdio.h> #include <string.h> #include "pfile.h" #include "kinemat.h" void awrite tec (trans a _huge **a entry, struct datainfo *pinfo, struct 20 kineinfo *kinfo, FILE *parfile) int ij,k,nframe; double time, phi, theta; FILE *outfile, *angfile, *fpdfile; char filename[40],angname[40],fpdname[40]; trans a _huge *base; transa huge *current; transa _huge *hold; so nframe = pinfo->synchframes; if (pinfo->synchframes== 0){ nframe = kinfo->synchframes; base = *a entry; current = base; printf ("Enter the name of the output file [ezt. will be .tec]: ");*/ fscanf (parfile,"I.s",filename); strcpy(angname,filename); 40 strcat(angname," . ang"); strcpy(fpdname,filename); 362 strcat(fpdname," . p"); strcat(filename,". tec"); outfile = fopen(filename,"v"); angfile = fopen(angname,"w"); fpdfile = fopen(fpdname,"w"); so50 fprintf(outfile,"TITLE = ""%s""\n",pinfo->name); = t, trans, phi, theta, P\n"); fprintf(outfile,"VARIABLES fprintf(angfile,"TITLE = Angles%s\n",angname); = t, flex, abd, extrot\n"); fprintf(angfile,"VARIABLES fprintf(fpdfile,"TITLE = Vertforce%s\n",fpdname); = t, yfpl, fprintf(fpdfile,"VARIABLES y_fp2\n"); 6o for (j=Oj<(pinfo->ntrans)j++){ fprintf(outfile,"ZONE T=Trans%d, I= %d, F= POINT\n", \ (j+1),nframe); for (i=O;i<nframe;i++){ fprintf(outfile,"%lf %1f %1f %lf %lf\n",current->time, ((double) j),current->alltransj] .ang.phi, current->alltrans ].ang.theta, current->alltransUj].mpa); hold = current->next; current = hold; } 70 current = base; } fclose(outfile); /$ Write the fidewithjoint anglesin it J/ fprintf(angfile,"ZONE T=ANGLES, I = %d, F = POINT\n",nframe); for (i=O;i<nframe;i++){ 363 fprintf(angfile,1"%.1f %lf %lf Y,1\n",current->time,\ current- >fiexion,current->abduction, current->extrotation); 80 hold = current->next; current = hold; I current = base; fclose(angfile); Write the file with forceplateforces in it */ / $ fprintf(fpdfile,"ZONE T=FP_FORCES, I = %d, F = POINT\n",nframe); for (i=O;i<nframe;i++){ 90 %f %\n",current->time,\ fprintf(fpdfile,"'%lf current->fpl_vert,current- >fp2_vert); hold = current->next; current = hold; I current = base; fclose(fpdfile); return; 100 } For data from prosthesis 33 E.3.2 Include files for KINE2.EXE /'****** ****$************** kinemat.h /,1* /$ /$ ********** $/ include file for "locate" */ K.C. Dec. 5, 1992 / ************************************************/ #define NTRANS 13 364 #define MAXSEG 10 typedefstruct 10 angles { double phi; double theta; } ang; typedef struct f angles{ angles &ng[NTRANS]; struct } femoral ang; 20 typedef struct atrans { struct angles ang; double mpa; }; typedef struct aframe { struct aframe *next; /* For doublylinkedlist $/ struct a frame *prev; double time; 30 double flexion,abduction, extrotation;/ *clinicaljt angs at hipSf sIruct a_trans alltrans [NTRANS];/* phi,theta, and pressure */ float fplvert, fp2_vert; /*Scaled FP Y forces $/ } transa; /* If using femoral view: no need to duplicatephi and theta $/ typedef struct f frame{ struct f frame *next; /* For creating a linked list */ struct f frame *prev; 40o double mpa [NTRANS]; } trans_f; /* trans_a_huge*aentry; /* anchorfor aframe list t/ / * transf _huge*f entry; /* anchorfor fframe list */ 365 femoral ang *f ang; typedefstruct kineinfo { char name[12]; char descr[40]; 50so / File name / / *Description*/ char side; /* Right or Left */ int nseg; / Number of segments collected int frames; / * frames of kinematic data taken */ int synchframes; / / * # of synchedframes (w/pressure)*/ int nfp; / * # of forceplates used$/ float wgt; double freq; / * frequency of kinematic data */ double prosth to_femoralrot [NTRANS][3];/ * Rot matriz - transducer*/ / * 60 position in femoral coordinates */ double pelvistoacet_rot [3][3];/* Rot matriz -pelvis to acet. $/ float seg_vec[MAXSEG][3]; / Segment vectorsfrom kine header*/ float seg_rot [MAXSEG][3][3]; /* Segment rot. matriz from T4header*/ float arraypos [2][3]; float array rot [2][3][3]; }; typedef struct pzeros { float offset[16]; 70 float gain[16]; float tempcorr[16]; float temp; }; / * Headerfile for use with programsthat accessprosthesis */ /*data files */ Jan. 17, 1990 366 #define GLOBAL * #define SEMIGLOBALstatic #define IMPORT extern / /* used to define a semiglobalvariable*/ /* used to refer to a globalor semiglobalvar*/ referenced elsewhere */ #define SHORTSIZE 9 #define PATHSIZE 80 #define PROSTH IDSIZE 3 #define DESCR_SIZE 32 #define DIRNAMESIZE 50 #define NAMESIZE 30 10 struct datainfo { 20 char name[9]; char id[3]; int samp; int adchan; int mult; int trig; char time[5][12]; char descr[32]; int startoff; int frames; 30 int alarmch; int synchch; double freq; int ntrans; / number of transducers $/ int date[3]; char hip; int synchframes; / $ Number of frames TSYNCH active $/ int binary; 40 367 SEMIGLOBAL char short dataname [SHORTSIZE] = ""; SEMIGLOBAL char prosth id [PROSTH_IDSIZE] = ""; * SEMIGLOBAL char description[DESCRSIZE] = ""; SEMIGLOBAL char namdir[DIRNAMESIZE] = ""; / function prototypes */ float floatflt( char *); void write stat (int ); void error(char *); void get_3ds(struct kineinfo *, FILE *); fpos t *get dat (struct kineinfo *, FILE *); int read dat (struct kineinfo*, FILE *,fpost *, int, int); void read fpd (struct kineinfo , FILE *, int, trans a *, fpost , int); int bread prs (struct kineinfo *, struct datainfo *, FILE *, 10 struct pzeros*, int, int, trans_a*, fpost *); int aread-prs(struct kineinfo*,struct datainfo*,FILE*, struct pzeros*, int, int, trans a *, fpos_t*); void write_tmp(structkineinfo*, struct datainfo*, FILE *, trans a *, fpos t *); void raw_tompa (int *, double *, struct datainfo*,float *, float *, float *, float); float zero33 (float *, float *, float *, struct datainfo *); femoralang *flocate (struct datainfo *); 20 void read_tmp(struct kineinfo , struct datainfo *, FILE *, transa , fpos_t*); void mgh ang (float *, transa *, char *); void multmatrices(float *, float *, float *, it, int, int); void calcjta (struct kineinfo*, struct datainfo*, trans_a*); void calc xfm (struct kineinfo *, struct datainfo *, trans_a *); void calc matrices(struct kineinfo , struct datainfo *, femoral_ang*); 368 30 void awritetec(struct kineinfo*, struct datainfo *, trans_a*, char *, fpos_t*, fpos_t*, fpost *, FILE , FILE *, FILE *, int); KINE33.C / *************** /*$ *** ************ $****** ********/ * kineSS3 /* Program to determine transducer locations and pressures /* for prosthesis 33 data. $/ */ $ /' * 2/24/93 K.C. / *******************************************************************/ #include <stdio.h> #include <stdlib.h> #include #include #include #include <sys\types.h> <sys\stat.h> <string.h> <errno.h> 10 #in clude "pf ile. h" #include "kinemat.h" #include "nc.h" int write count = 0; int read count = 0; 20 void main( int argc, char *argvo) char paramfile[80],filename[80],prsname[80],datname[80]; char fpdname[80],name3ds[80],angname[80],fpname[80]; char pformat[2]; struct datainfo pdata; struct datainfo *pinfo; 30 369 struct kineinfo kdata; struct kineinfo *kinfo; struct pzeros zeros; struct pzeros *pzero; int i, curframe, next, err, frames, kframe, knext; trans a dataframe, *thisframe; fpos_t *fpos,*fapos,*ffpos, *fopos; float time; 40 FILE *parfile = NULL; FILE *pfile= NULL; FILE *dfile= NULL; FILE *fflle= NULL; FILE *file3= NULL; FILE *tmpfile= NULL; FILE *outfile,*angfile, *fpfile; if (argc < 2){ printf("Enter the name of the file with processing parameters: "); 50 scanf("%s ",argv[1]); } strcpy (paramfile, argv[ll]); parfile = fopen(paramfile, "r"); pinfo = &pdata; kinfo = &kdata; pzero = &zeros; /* Get filenames / so80 fscanf(parfile,"%s ",filename); fscanf(parfile,"%s" ,pformat); fscanf(parfile,"%d d %d",&pinfo->date[O],&pinfo->date[1], &pinfo->date[2]); fclose(parfile); 370 strcpy (prsname,filename); strcpy (datname,filename); strcpy (fpdname,filename); strcpy (name3ds, filename); 70 strcpy (angname, filename); strcpy (fpname, filename); strcat (prsname,".prs"); strcat (datname,".dat"); strcat (fpdname, ".fpd"); strcat (name3ds, ".3ds"); strcat (angname, ".ang"); strcat (fpname," .fp"); /$ Read .3DS file */ 80 if( NULL != (file3= fopen (name3ds, "rb"))) ( get_3ds (kinfo, file3); fclose (file3); } else { printf("\n file %s could not be opened",name3ds); } /$ Read eader to .DAT file */ if( NULL != (dfile = fopen (datname, "rb"))) { 90 fpos = getdiat (kinfo, dfile); else { printf("\n file %s could not be opened",datname); } / * thisframe= (transa ) calloc(l,sizeof(trans_a)); */ thisframe = &data frame; 100 / $ Frames loop, for all kinematic frames */ 371 if( NULL != (ffile = fopen (fpdname, "rb"))){ if (pformat[O] == 'b'){ pfile = fopen (prsname,"rb"); fseek ( pfile, 0, SEEK_SET); fseek (ffile, 0, SEEK_SET); } else { pfile = fopen (prsname,"r"); 110 f£eek (pfile, 0, SEEK SET); fseek (ffile, 0, SEEK _SET); else { printf("\n file %s could not be opened",fpdname); } if(NULL == pfile) printf("\n could not open file %s ",prsname); 120 if( NULL == (tmpfile = fopen("temp.dat","vb"))) { printf("\n file temp.dat could not be opened "); } fseek (tmpfile, 0, SEEK_SET); if (kinfo->freq > 254.0){ time = (kinfo- >frames)/(kinfo->freq); frames = (int) (254 * time); } else frames = kinfo->frames; curframe = 0; 130 kframe = 0; for (i=O;i<frames;i++){ write stat (1); fseek (dfile, 0, SEEK_CUR); err = fgetpos(dfile, fpos); knext = readdat(kinfo, dfile,fpos, kframe, i); write_stat (2); 372 fseek (ffile, 0, SEEK_CUR); err = fgetpos(ffile, fpos); 140 read_fpd(kinfo, ffile, i, thisframe,fpos, kframe); write stat(3); == 'b'){ if (pformat[O] fseek (pfile,O, SEEKCUR); err = fgetpos (pfile, fpos); next = bread_prs(kinfo, pinfo, pfile, pzero, i, curframe, thisframe,fpos); write stat(4); else { 150 fseek ( pfile, 0, SEEK_CUR); err = fgetpos (pfile, fpos); next = aread prs(kinfo, pinfo, pfile, pzero, i, curframe, thisframe, fpos); fseek (tmpfile, 0, SEEK-CUR); err = fgetpos (tmpfile, fpos); writetmp(kinfo, pinfo, tmpfile, thisframe,fpos); write stat(5); 180 curframe = next; kframe = knext; fclose (tmpfile); fclose (dfile); fclose (pfile); fclose (ffile); printf(" Donewith read loop \n"); /$ Open the files that will be read by TECPLOT $/ if( NULL== (outfile= fopen("a.out","w"))) printf("\n file a.out could not be opened "); if( NULL == (angfile = fopen(angname,"w"))) 373 170 printf("\n file angname could not be opened "); if( NULL == (fpfile = fopen(fpnante,"W"))) printf("\n file temp.dat could not be opened "); fseek (outfile, 0, SEEK SET); fseek (angfile, 0, SEEK_SET); 180 fseek (fpfile, 0, SEEKSET); /* Having trouble with program, try closing all files /* and reopening,eachframe */ * fclose(outfile); fclose(angfile); fclose(fpfile); /* Get the transducer locationsfrom 33.ang file, used in transfm */ ftang = f locate(pinfo); /* 190o Calculatethe transformation matrices which remain constant #/ calcmatrices( kinfo, pinfo, f ang); *fpos = 0; for (i=0;i<frames;i++){ if( NULL == (tmpfile = fopen("temp.dat","rb"))) printf("\n file { temp.dat could not be opened "); } 200 if (0!=(err = fseek (tmpfile, *fpos, SEEK_SET))){ printf("\n temp.dat file pointer not set correctly"); fclose(tmpfile); exit(l); err = fgetpos(tmpfile,fpos); readtmp(kinfo, pinfo, tmpfile, thisframe, fpos); err = fgetpos (tmpfile,fpos); fclose(tmpfile); calcjta(kinfo, pinfo, thisframe); 210 374 calcxfm(kinfo, pinfo, thisframe); if( NULL == (outfile = fopen("a.out","a"))) printf("\n file a.out could not be opened "); if( NULL == (angfile = fopen(angname,"a"))) printf("\n file angname could not be opened "); if( NULL == (fpfile = fopen(fpname,"a"))) printf("\n file temp.dat could not be opened "); err = fgetpos ( outfile, fopos); err = fgetpos (angfile, fapos); err = fgetpos (fpfile, ffpos); awritetec(kinfo, 220 pinfo, thisframe, filename, fopos, fapos, ffpos,\ outfile, angfile, fpfile, i); fclose(outfile); fclose(angfile); fclose(fpfile); } } FLOATFLT.C / *************************************************************** /* floatflt.c /$ function to read 4 byte reals written in PDP 11 /* binary and figure out what the number is. /$ Feb. 19, 1993 K.C. */ $/ $/ / ******************************************************* #include <stdio.h> #include <math.h> 10o #include "kinemat.h" #include "fnc.h" float floatfit(char *dat) 375 { short int i, hi, h2, exp; char data[4]; int h3; unsigned long int frac, div; 20 float sign, fout; float *fpo; / * printf('\n insidefloatflt");*/ fpo = &fout; data[O]= *dat; data[1]= *(dat+l); data[2] = *(dat+2); 30 data[3] = *(dat+3); /* byte order swapped */ h3 = (((short int) data[1]) << 8); hi = h3 I (((short int) data[O])& OxOOff); h3 = (((short int) data[3]) << 8); h2 = h3 I ( ((short int) data[2] ) & OxOOff); /$ get the ezponent from bits 14-6 in the first WORD */ 40 exp = ((Ox7f80& hl ) >> 7) -128; il(exp== -128) exp = 0; /* convert the high bytes by shifting 16 bits and add to the low bytes $/ /* set the leading bit to 1 using 0z00800000since is implied 24-bit # */ frac = (0x00800000 I ((long) (h2 & Ox0080FFFF))) (((long) hi & 0x007f)<< 16) ; 376 I 5o div = OxOOffff; /* make the fraction fout from the fraction integer */ fout = ((float) frac)/ ((float) div); /$ printf("\n ezponent 4 fraction calculated "); / if( (fout >1.0 ) (fout <0.5)){ printf("\n fraction not normalized in floatflt-->%f",fout); printf("\n frac = %lx, data--> %x %x %x 60 .x ", frac,(int)data[] ,(int)data[l],(int)data[2],(int)data[3]); error("\n exiting"); } if( (exp < -127 ) 11(exp>127)) { printf("\n exponent out of range in floatflt -- >%d",exp); error("\n exiting"); } /* set the sign bit $/ 70 if ((hl & 0x8000) != xO0000){ fout = -1. * fout * pow((double) 2, (double) exp); } else{ fout = fout * pow((double) 2, (double) exp); } / * printf("\nezitingfloatfit,%f,",fout);*/ return(fout); 80 I GET_3DS.C /***************** $******************$$$*$$$$$$**$***** 377 ** / /* get3ds.c -- * /* function to read the .3ds file */ /* from old MGH data /* Feb17, 1993 K.C. */ #include <stdio.h> 10 #include <malloc.h> #include "kinemat.h" #include "fnc.h" void get 3ds(struct kineinfo *kinfo, FILE *data3) { char iscal,leg; float *pdum; char *pchar; int ij,k; char pchar_array[130]; 20 pchar = &(pchar_array[O]); /* pchar = (char *)calloc(128, sizeof(char)); */ fread(pchar, sizeof(char), 128, data3); iscal = *pchar; pchar++; leg = *pchar; pchar--; /* Each recordis 128 bytes long. Header is 12 lines */ 30 for (i=O;i<12;i++){ fread(pchar,sizeof(char),128,data3); } /* Nezt siZlines are segment position vectors, each seg on a line 3''8 $/ for (i=O;i<6;i++){ pchar = &(pchar array[O]); fread(pchar,sizeof(char),128,data3); 40 for 0=O;j<3j++){ kinfo->seg-vec[i]j] = (floatfit (pchar)); == 3 if(i 11i == 4) printf("%! " k in f o - , >seg_vec[i][j]); } pchar+=4; } 50 /* Nezt 4 recordsare segment rotation matrices. Read in with $/ /* first indez (besides the segment indez) incrementing first */ /* Is really the transpose I think - doing to match MGH procedure */ /* in angplot_sub.F,easier to transposenow than add a step I guess */ for (i=O;i<4;i++){ pchar = &(pchararray[O]); fread(pchar,sizeof(char),128,data3); for j=Oj<3j++){ for (k=O;k<3;k++){ kinfo->segrot[i][k][j] 60 = floatflt (pchar) if (i==3 1 i== 4){ printf("%f ",kinfo->segrot[i] [k] L]); } pchar+=4; } * printf ("\n"); / 70 free(pchar); */ return; } 379 GETDAT.C / ************* *****************************/ /* getdat --- */ function to get the .Dat file. /* /* yet what to read or how..... /* */ */ ,/ /* / Not sure Feb. 16, 1993 K.C. */ ******$*$**********$$**************************$/ #include <stdio.h> #include <stdlib.h> 10 #include <string.h> #include <malloc.h> #include <math.h> #include <errno.h> #include "pfile .h" #include "kinemat .h" #include "fnc.h" 20 fpos_t *get_dat( struct kineinfo *kinfo, FILE *finl) f char *pchar; char pchar array[260]; float *dat; fpos t *fpos; int i, retval, err; int nseg_l; int nframe; int nfp; / 30 Read the first "record" - discard. Get info from 2nd*/ pchar = &pchar array[O]; /*pchar = (char *) calloc(256,sizeof(char)); */ 380 for (i=O;i<2;i++){ retval = fread(pchar,sizeof(char), 256, finl); err = fgetpos(finl, fpos); } pchar+=4; nframe = (int) floatflt(pchar) ; 40 pchar+=4; kinfo->freq = (double) floatflt(pchar); pchar +=4; nsegl = (int) floatflt(pchar); pchar+=12; nfp = (int) floatflt(pchar); kinfo->nseg = nseg l; kinfo->nfp = nfp; so kinfo->frames = nframe; kinfo->wgt = 150.; pchar = &pchar array[O]; strcpy(kinfo->side, "R"); Read the rest of header / /* for (i=0;i<8;i++){ retval = fread(pchar, sizeof(char), 256, finl); err = fgetpos(finl, fpos); } so60 / * free(pchar); free(dat); $/ return(fpos); READDAT.C / ******* / / read_dat * ********* ***************/ */ file to just read a frame at a time of */ 381 /* /* .DAT file and save info 2/24/93 */ K.C. *********/ #include <stdio.h>************ #include <stdio.h> #include <stdlib.h> #include <malloc.h> 1o #include <math.h> #include <errno.h> #include "kinemat.h" #include "pfile. h" #include "fnc.h" int read_dat(struct kineinfo *kinfo, FILE *dfile, fpos_t *fdpos, int kframe,\ int itime) { char *pchar,*dum; 20 char pchar_array[260]; int i, j, k, 1, retval; int err, knext, frame; float *data; float dat; double time, rem; double *intptr; /* Sometimes is skipping these - I have no idea why! / 30 for j=O0;i<2;j++){ printf("/d"j); for (k=O;k<3;k++){ for (1=0;1<3;1++){ kinfo->array_ot][k][] = 0.0; } kinfo->arraypos [j][k] = 0.0; } } 382 40 /* Now eztract the array position and rotation matrices*/ / from the stored data. 16 numbers per segment per frame */ * /* Order- arrayposition,4 unidentified# 's, arrayrot.*/ pchar = &pchararray[O]; err = fsetpos (dfile, fdpos); if (kinfo->freq > 254.){ time = ((double) itime)/254.; rem = modf ((time * (kinfo->freq)), intptr); 50 frame = (int) floor(*intptr); if (rem > 0.5) frame++; } else frame = kframe; for (k=O;k<(frame-kframe+ 1);k++){ if ((retval = (fread(pchar,siseof(char),256, dfile))) != 256 ){ printf("Not reading in readdat.c\n"); scanf( "%c",dum); } 60 err = fgetpos (dfile, fdpos); for (i=0;i<64;i++){ dat = floatflt(pchar); pchar+=4; } pchar=&pchararray[0]; pchar += 16*2*4;/* Increment pointer to femoral array(seg3)*/ for (j=O;j<2;j++){ /* Segment loop $/ for (k=O;k<3;k++){ kinfo->arraypos[j][k] = floatflt(pchar); /* printf("%f ",kinfo->arraypos[j][k]);*/ pchar+=4; } 383 70 pchar+=(4*4); /* Pass the 4 unidentified numbers */ for (k=O;k<3;k++){ for (1=0;1<3;1++){ kinfo->array rotj] [k][1]= floatflt(pchar); printf("%f ",kinfo->array_rot[j][k[l]);*/ /* so pchar+=4; $/ } } printf(" \n"); /' free(pchar); return(frame++); READFPD.C /***t***********~******************** *'/ /* readfpd */ !/* File to read FPD files (in binary) */ /$ single frame at a time */ /* /* ./ K.C. 2/24/93 /************************************** $/ #include <stdio.h> #include <stdlib.h> 10 #include <malloc.h> #include <math.h> #include <errno.h> #include "pfile.h" #include "kinemat.h" #include "fnc.h" void readfpd (struct kineinfo *kinfo, FILE *fdata, int itime, trans_a *thisframe, fpos_t *ffpos, int kframe) { 20 384 char *pchar; int i, j, k, 1, nseg, err, retval, knext,frame; float *fpd; float wgtnt; char pchararray[50]; double time, rem; double *intptr; /* printf('\n enteringreadfpd");*/ 30 I if (NULL == (pchar = (char *) calloc (48, sizeof(char)))){ error('\n null pointerin readfpd"); } *1 if (itime== O){ for (i=O;i<10;i++){ write_stat (21); pchar = &pchararray[O]; err = fsetpos(fdata, ffpos); retval = fread(pchar,sizeof(char),6*8,fdata); 40 err = fgetpos(fdata, ffpos); wgtnt } = info->wgt * 9.8/2.2; t. in Ibs-> / t. in Newtons write stat(22); pchar = &pchararray[O]; err = fsetpos(fdata, ffpos); if (kinfo->freq > 254.){ time = ((double) itime)/254.; rem = modf ((time * (kinfo->freq)), intptr); frame = (int)floor(*intptr); if (remn> 0.5) frame++; } else frame = kframe; for (k=O;k<(frame-kframe+1);k++){ retval = fread(pchar,siseof(char),6*8,fdata); 385 50 } err = fgetpos(fdata, ffpos); /* Scale the FP data by 100/body wt in Newtons (as at MGH) */ so pchar+=4; write stat(23); writestat(24); / thisframe->fpl_vert = -1.0 * (floatflt(pchar)) * 100. / wgtnt; pchar+=(6*4); thisframe->fp2_vert = -1.O*(floatflt(pchar))*100./wgtnt; /* free(pchar); write stat(25); 1/* printf('\n eziting readfpd");*/ 70 return; / * BREADPR.C bread prs */ /$ subroutine to read binary .PRS files $/ /* a frame at a time. /* made it change to MPA too */ */ /* 21/4193 #include K.C. '1 <stdio.h> 10o #include <string.h> #include <math.h> #include <errno.h> #include "pfile .h" #include "kinemat.h" #include "fnc.h" 386 int bread prs (struct kineinfo *kinfo, struct datainfo *pinfo, FILE *prsfile, struct pseros *pzero, int itime, int curframe, transa *thisframe, fpos t *fppos) 20 int i, j, k, ib[16], pframe; int dum[38], retval, err; int *pdum; float offset[14], gain[14], tempcorr[14], temp; float *poff, *pgain, *ptcorr; double data[16], time, rem; int *pjb; double *p-data; double pf, *intptr; 30 pib = &ib[O]; pdata = &data[O]; poff = &offset[O]; pgain = &gain[O]; ptcorr = &tempcorr[O]; intptr = &pf; pdum = &dum[O]; /* Read the data then turn into pressures */ /* Only have to deal with prosthesis 33 $/ /* First time through, find zeros, read header 40 $/ if (itime == ){ write stat(11); temp = sero33 (poff, pgain, ptcorr, pinfo); write_stat(12); pzero->temp = temp; for (i=0;i<14;i++){ pzero->offset[i] = *poff; pzero->gain[i] = *pgain; pzero->tempcorr[i] = *ptcorr; poff++; 387 50 pgain++; ptcorr++; } poff-=14; pgain-=14; ptcorr-=14; for (i=O;i<ll;i++){ 60 pdum = &dum[O]; err = fsetpos(prsfile, fppos); retval = fread(pdum,siseof(int),38,prsfile); err = fgetpos(prsfile, fppos); pinfo->freq = 254.; strcpy(pinfo- >id,"33"); pinfo->ntrans=13; else{ 70 for (i=O;i<14;i++){ offset[i]= pzero->offset[i]; gain[i] = pzero->gain[i]; tempcorr[i] = pzero->tempcorr[i]; } temp = pzero->temp; } if (kinfo->freq <=254.){ time = ((double)itime)/ (kinfo->freq); rem = modf ((time * pinfo->freq), intptr); pframe = (int) floor(*intptr); if (rem > 0.5) pframe++; } else { pframe = curframe; } for (k=curframe; k<pframe; k++){ pdum = &dum[O]; err = fsetpos (prsfile, fppos); 388 80 fread(pdum,sizeof(int),38,prsfile); 90 err = fgetpos (prsfile, fppos); } pdum = &dum[O]; err = fsetpos (prsfile, fppos); retval = fread(pdum,siseof(int),38,prsfile); err = fgetpos(prsfile, fppos); for (j=l; j<17; j++){ ibj-1] = dumlj]; 10o pframe++; write stat(13); raw to mpa(pjb, p data, pinfo, poff, pgain, ptcorr, temp); for (j=2; j<15; j++){ if (j!=5&&j!=7&&j!=9){ thisframe->alltransbj-2].mpa = data[j-2]; else { thisframe->alltranslj-2].mpa= 0.0; 110 thisframe->time = time; return(pframe); / * areadprs /* */ subroutineto readASCII .PRS files /*$a $/ */ frameat a time. made it change to MPA too /* /* AREAD-PR.C $/ 2/ */ /* 2/24/9s K.C. /$*********************z$******************************/ 389 #include <stdio.h> 1o #include <string.h> #include <math.h> #include <errno.h> #include "pfile.h" #include "kinemat.h" #include "fnc.h" int aread-prs (struct kineinfo *kinfo, struct datainfo *pinfo, FILE *prsfile, struct pzeros *pzero, int itime, int curframe, trans a *thisframe, fpost *fppos) 20 int i, j, k, ib[16], pframe; jut dum[38], pfreq, retval, err; int *pdum; float offset[14], gain[14], tempcorr[14], temp; float *poff, *pgain, *ptcorr; double data[16], time, rem; int *p ib; double *p_data; so30 double pf, *intptr; pjb = &ib[O]; p_data = &data[O]; poff = &offset[O]; pgain = &gain[O]; ptcorr = &tempcorr[O]; intptr = &pf; pdum = &dum[O]; 40 /$ Read the data then turn into pressures / Only have to deal with prosthesis 33 * /* First time through, find zeros, read header if (itime == 0)( 390 */ */ temp = zero33 (poff, pgain, ptcorr, pinfo); pzero->temp = temp; for (i=O;i<14;i++){ pzero->offset[i] = *poff; pzero->gain[i] = *pgain; 50 pzero->tempcorr[i] = *ptcorr; poff++; pgain++; ptcorr++; } poff-=14; pgain-=14; ptcorr-=14; err = fsetpos(prsfile, fppos); fscanf (prsfile, "%d %d",&pinfo->frames,&pfreq); 60 fscanf (prsfile, "%d %d %2d/,*d",&pinfo->date[O], &pinfo->date[1], &pinfo->date[2]); err = fgetpos(prsfile, fppos); strcpy (pinfo->id,"33"); pinfo->freq = (double)pfreq; pinfo->ntrans = 13; } else{ for (i=O;i<14;i++){ offset[i] = pzero->offset[i]; 70 gain[i] = pz.ero->gain[i]; tempcorr[i] = pzero->tempcorr[i]; } temp = pzero->temp; } if (kinfo->freq <= 254.){ time = ((double)itime)/ (kinfo->freq); rem = modf ((time * pinfo->freq), intptr); pframe = floor(*intptr); if (rem > 0.5) pframe++; so I 391 else { pframe = curframe; } err = fsetpos(prsfile, fppos); for (k=curframe; k<pframe; k++){ for (j=0j<37;j++){ fscanf(prsfile,".*d"); } ~~~~~~~~~~~~} ~~90 for (j=O;j<37; j++){ if j>=1 &&j<=16) fscanf(prsfile,"%d" ,&ibU-1]); else fscanf (prsfile,"%*d"); } err = fgetpos(prsfile, fppos); pframe++; rawto_mpa(p_ib, pdata, pinfo, poff, pgain, ptcorr, temp); for (j=2; j<15; j++){ 100 if (j!=5&&j!=7&&j!=9){ thisframe->alltransj-2].mpa = dataU-2]; } else{ thisframe->alltrans[j-2].mpa = 0.0; thisframe->time = time; return(pframe); WRITETM.C / write_tmp * /* Writes a temporaryfile containing info /* for eachframe of data /* */ */ */ 392 /* FORMAT: allfloats */ /* time, pressures (13, in MPA, 0 if bad), fplvert, */ /* fp2_vert,arraypo[2][3],arrayrot[2][S][3] */ /* /* */ 2/21/93 K.C. */ / ***************************************************** 10 ***** #include <stdio.h> #include <errno.h> #include "kinemat.h" #include "pfile.h" #include "nc.h" void write tmp(struct kineinfo *kinfo, struct datainfo *pinfo, FILE *tmpfile, transa *thisframe, fpost *ftpos) { 20 int ij,k, err; float temp[45]; float *ptemp; extern iat write count; /* printf('\n enteringwrite_temp");*/ ptemp = &temp[O]; temp[0] = (float) (thisframe->time); writestat(29); for (i=O;i<NTRANS;i++){ /* 30 printf('"\n i = d, val = %lf",i, (thisjrame->alltrana[i.mpa); ,/ temp[i+l] = (float) (thisframe->alltrans[i].mpa); } temp[14]= thisframe->fplvert; temp[15] = thisframe->fp2_vert; write stat(31); for (i=O;i<2;i++)( for (j=Oji<3j++)( temp[i*3+j+16] = kinfo->array.pos[i][j]; ) 393 40 write stat(32); for (i=O;i<2;i++){ for (j=O;j<3;j++){ for (k=O;k<3;k++){ temp[i*9+j*3+k+22] = kinfo->array rot[i]Lj][k]; } / 50 printf'("\n starting write int writetmp ");*/ err = fsetpos(tmpfile, ftpos); fwrite (ptemp, sizeof(float), 40, tmpfile); err = fgetpos(tmpfile, ftpos); printf ("\n %d",write_count); */ /* /* for (i=O;i<40;i++){ printf("%f ",temp[i]); printf('n"); */ 60 ++write-count; return; RAWTO.M.C /* rawtompa /* */ function to get pressure in MPa at each */ /* transducer (for 33SS only) from raw values collected /* at MGH. (Well - could have been collectedelsewhere) /$ ,/ /* Dec. 9, 1992 K '. #include */ */ */ <stdio.h> o10 #include <math.h> 394 #include "pfile.h" #include "kinemat.h' #deflne VTOMV 1000.0 #define PSITOMPA 0.0068948 void raw to mpa ( int *praw, double *pmpa, struct datainfo *ppinfo, 20o float *poff, float *pgain, float *ptcorr, float temp) int i, j, cal, sero, level, diff, data; double cmv; /* Eztractthe scalinginformation*/ /* If analog value is > 3*(cal-zero)*/ / then the part above that level has */ $ /* been compressed by a factor of 4 */ so cal = *praw; praw++; zero = *praw; praw++; level = 3*(cal-zero); /* Need to check if Temperatureshould be difference */ /* between normal" and actual or just actual #ifdef _MGH_PRINT printf("praw */ 40 = Ud",*praw); #endif for (i=O;i<ppinfo->ntrans; i++){ data = *praw; if (i!=3 && =5 && i!=7){ if (*praw > level){ 395 diff = *praw- level; diff = diff*4; *praw = level + diff; 60 data = *praw; cmv = ((double)(data-sero))/((double)(cal-zero)) * ((double) VTOMV); *pmpa = (cmv - (double) ( (*ptcorr)*(temp--37.0) + (*poff)) ) / ((double) (*pgain) ); *pmpa = (*pmpa) * ((double) PSITOMPA); } else { cmv = 0.0; 60 *pmpa = 0.0; } #ifdef _MGHPRINT printf("pmpa = %li, praw = %d\n",*pmpa, *praw); #endif pmpa++; praw++; poff++; pgain++; ptcorr++; 70 } return; I ZERO33.C / *********$**$$*$************$$$$$$**$$$$**********************/ /$ /* *1/ zero33 --function to get offsets and ga:ns and temp /* adjustment and temperaturefor a data set taken /* from prosthesis 33. Reads 33.Dat file, or same format 396 *1 *1 /* Dec. 9, 1992 K.C, */ / ****************************oo****** #include <stdio.h> .***/ 10 #include "pftile.h" #include "kinemat.h" float sero33 (float *poff, float *pgain, float *ptcort, struct datainfo *pinfo) int i, date[3]; char zname[30]; float temp; FILE *zfile; 20 file = fopen ("33.dat","r"); for (i=O;i<16;i++){ fscanf (file,"%f ",pgain); if (i>=2) pgain++; } for (i=O;i<16;i++){ fscanf (file, "%f ",ptcorr); if (i>=2) ptcorr++; 30 do { for (i=O;k16;16;i++){ fscanf (file, "%f", poff); if (i>=2) poff++; } fscanf (zfile,"%d",&date[O]); if (date[O] != 13){ fscanf (file, "%:'", &date[']); fscanf (file, ".d", &date[2]); fscanf (zfile, "%i", &temp); 397 40o if (date[O]== pinfo->date[0]&& date[l] == pinfo->date[1]&& date[2] == pinfo->date[2]){ fclose (zfile); return(temp); } while (date[O] !=EOF ); so fclose(zfile); printf("Zeros not found for this date\n"); temp = 37.0; / * May want to changedefault to 8 / return(temp); READTMP.C / ****************************************************** /* read tmp $/ /* */ Should at some point put a header on temp file */ /* FORMAT: all floats /* Reads temp.dat file createdby writetmp.c $/ /* time, pressures .13, in MPA, 0 if bad), fpl_vert, */ /* fp2 vert, arraypos[2][3],array rot[2][3][3]*/ /* 2/241/93 K.C. 10 #include <stdlib.h> #include <stdio.h> #include "kinemat.h" #include "pfile .h" #include "fnc.h" void readtmp(struct kineinfo *kinfo, struct datainfo *pinfo, FILE *tmpfile, trans a *thisframe, fpos.t *fpos) { 20 398 int ij,k, retval; foat temp[45]; float *ptemp; extern int readcount; printf("\n entering readtmp"); ptemp = &temp[O]; /* Read a frame from temp.dat file (40 floats)*/ /* so printf(\n startingreadin readtmp "); */ if (40 != (retval = fread(ptemp, iseof(float), 40, tmpfile))){ printf(" \n Didn't read in readtmp retval = %d",retval); fclose(tmpfile); exit(l); /* printf("\n %odf %f f ",read_count,temp[O],temp[14],temp[l]);*/ /* Copyfirst numberto thisframe->time */ thisframe->time = (double) temp[O]; 40 / * Copy nezt NTRANS numbers to thisframe->alltrans[i].mpa */ for (i=0O;i<NTRANS;i++){ thisframe->alltrans[i].mpa = (double) temp[i+l]; /* Copy nezt two numbers to thisframe->fpl._ert thisframe->fplvert fp2tvert */ so = temp[14]; thisframe->fp2_vert = temp[15]; /* Nezt 6 numbers are kinfo->array pos[seg][S], array position vectors, */ /* only for 3rd (femur) and 4th (pelvis) segments, which are */ /* locallynumbered0 and I */ 399 for (i=0;i<2;i++){ for (j=O;i<3j++){ kinfo->arraypos[i][j] = temp[i*3+j+16]; } 60 /* Nezt 18 numbers are kinfo->array_rot[seg][3][S],array rotation / /* matricesfor femur andpelvis */ for (i=O;i<2;i++){ for (j=0;j<3j++){ for (k=O;k<3;k++){ kinfo->array_rot[i]L][k]= temp[i*9+j*3k+22]; } 70 ++read-count; return; CALCJTA.C /* *1 calcjta $/ Calculatejoint angles, callsmgh_ang.c /$ */ / * which uses Pierrinowsky and Tupling / $ Only works on one frame at a time - called /* from kine33.c */ /* #include / */ lo <stdio.h> #include <stdlib.h> #include <malloc.h> #include <math.h> 400 #include <string.h> #include "pf ile. h" #include "kinemat.h" #include "fnc.h" void calcjta (struct kineinfo *kinfo, 20 struct datainfo *pinfo, trans a *thisframe) char *side; int num; int i, j, k, 1, nframe, iside, ijoint, nseg, nsynch; float smt[2][4][4]; float smt2[2][3][3]; float seg_rot [2][3][3];/ Store only for the two */ float arrayrot [2][3][3]; double bad; 80o float *psmt2, *psegrot, *parrayrot, *psmt; bad = -1000.0; nsynch = 0; strcpy(side,"R"); if (*side == 'L') iside = 2; else iside = 1; ijoint = 3; /* Hope this is the right answer! Want the hip joint*/ nseg = kinfo->nseg; 40 /$ Set all of smt to 0.0 $/ for i(=0ji<2j++)( for (k=O;k<4;k++)( for (1=0;<4;1++){ smt[j][k]p] = 0.0; } 401 650 /* Fill the segment vector and rotation matrices */ /* from kineinfo structure. /* Assume the segments of interest (femur, pelvis) */ /* are segments and 4 */ /* Also, fill array_rotfrom kinfo->array rot, just so */ /* don't have to change mult mat.c */ for (k=2;k<4;k+4){ /* Segment loop $/ for (i=O;i<3;i++){ for (j=Oj<3j++){ 6o seg_rot [k- 2] [i] [j] =kinfoarrayrot[k-2] /* /* >seg_rot [i] [j]=kinfo- [k] [i] [j]; >arrayjot[k-2] [i] Lj]; printf ("in calcjta, beforesegment loop\n");*/ Now do the calculations, already have the data, and are only $/ /* doing a frame at a time. Still need to checkfor bad data */ /* Multiply the array orientation matriz into body segment coord.*/ for (j=O0j<2j++){ 70 /* Segment loop */ psmt2 = &smt2[j][0][0]; psegrot = &seg_rotlj][O][O]; parrayrot = &arrayrotj][O[0[0]; if ((kinfo->arrayposLj][O])!=bad && (kinfo- >arrayposj] [1])!=bad && (kinfo->array-posLj][2])!=bad){ /* printf("in calcjta, goingto multmat\n");*/ mult_matrices(psegrot,parrayrot,psmt2,3,3,3); for (k=O;k<3;k++){ for (1=0;1<3;1++){ smt ] [k] [1]=smt2[j] 402 [k] [1]; 80 mti][k][3] = 0.0; for (1=0;1<3;1++){ smtj][3][] = 0.0; } 90 smtQ][3][3]= 1.0; /* Good data */ else{ smtU][3][3]= 0.0; /* Bad data / } /* Do angle calculation elsewhere / psmt = &smt[01[0][0]; /* 1oo printf("in calcjta, goingto mgh_ang\n");*/ mghang( psmt, thisframe, side); return; CALCXFM.C / ******************************************************** /* I* /* calczfm.c - basedon hip_zform --function to transform transducer $/ /* locations into acetabular locations. $/ /* Clinical joint angles are obtained earlier */ /* and are storedfor each frame in the trans_a */ /* structure. Joint anglesarefrom Grood Suntay defn's. /* /* /* / */ */ Bulk of the programfrom TRANS(in FORTAN*/ /$ by Bob Fijan and me - but may be significant */ /* alterationsfor use with left as well as right */ /* hips and becauseam workingfrom notes made $/ 403 10 /* a couple years ago - reworked TRANS and found */ /* some bugs/better ways to do things. */ /* /* */ Dec. 10, 1992 K.C. */ /**********************************$****/ 20 #include <stdio.h> #include <math.h> #include <string.h> #include <errno.h> #include "pfile.h" #include "kinemat.h" #define PI 3.1415927 30 void calcxfm (struct kineinfo *kinfo, struct datainfo *pinfo, transa *thisframe) char hip[3],reply[4]; double flex, abd, rot; double u[3],c[3][3],rad,theta, factor, alter; double f[3],a[3],c2[3][3]; int ij; 40 strcpy(hip,"R"); flex = (thisframe->flexion); rot = (thisframe->extrotation); abd = (thisframe->abduction); for (i=O;i<3;i++){ for (j=O;<3ji++){ c[i][j] = 0.0; c2[i][j] = 0.0; u[i] = 0.0; 50 404 f[i] = 0.0; a[i] = 0.0; * } /* Calculatethe rotation matriz first 7/ /* Worked this out for a right leg in 2/90...is also different */ / from HTRANS. */ c[o][0] = cos(rot)*cos(flex); c[0][1] = cos(rot)*sin(flex) + sin(rot)*sin(abd); 60 c[0][2]= sin(rot)*cos(abd); if (hip[O]== L') c[0][2]= -c[0][2]; c[1][0] = -cos(abd)*sin(flex); c[1][1] = cos(abd)*cos(flex); c[1][2]= -sin(abd)*cos(flex); if (hip[O]== 'L') c[1][2]= -c[l][2]; c[2][0]= -sin(rot)*cos(flex); c[2][1] =-sin(flex)*sin(rot) + cos(rot)*sin(abd); 70 c[2][2] = cos(rot)*cos(abd); if (hip[O]== 'L'){ c[2][0] = -c[2][0]; c[2][1]= sin(flex)*sin(rot) - cos(rot)*sin(abd); } /* Now get c2 (pelvistoacet_rotation matriz) from kineinfo */ for (j=0j<3ji++){ for (i=O;i<3;i++){ 80 c2b][i]= kinfo->pelvistoacet_rot][i]; /* Now rotate for each transducer */ 405 for (j=O;j<pinfo->ntrans;j++){ for (i=O;i<3;i++){ f[i] = kinfo->prosth /* to femoral rot[j][i]; if (j==2) printf("f[%d] -- %l\n",i,f[i]);*/ /* Now need to go into pelvis coord using the clinical */ /* joint angles. Assume angles in radians. go */ u[O]= c[O][O]*f[0] + c[l][0] * f[1] + c[2][0] * 42]; u[ll = c[0][1] * f0o] + c[l][l] * f[l] + c[2][1] * 42]; u[2] = c[0][2] * f[0] + c[1][2] * 4[1] + c[2][2] * f[2]; 100 / * Now change to acetabularcoordinates*/ /* Use the rotation matriz calculatedin calcmatrices and stored / /* in pelvistoacet_rotin structurekineinfo */ /* Transposedrelative to the previous matriz */ a[O] = c2[0][0] * u[O] + c2[0][1] * u[l] + c2[0][2]* u[2]; a[1] = c2[1][0] * u[O] + c2[1][1] * u[l] + c2[1][2]* u[2]; a[2] = c2[2][0] * u[o] + c2[2][1] * u[l] + c2[2][2] * u[2]; /$ Now change [a]into an acetabularphi and theta and store as degrees*/ /* For a left hip, phi measuredfrom pos Za azis -if (hip[O]== 'L') a[2] 110 so change sign there*/ -a[2]; factor = -a[2]; thisframe->alltransl].ang.phi = (acos(factor)) * 180./PI; rad = sqrt((a[O]*a[0]+ a[1l]*a[l])); theta = acos((a[0]/rad)) * 180./PI; if (a[1]< 0) theta = -theta; thisframe->alltransi].ang.theta = theta; $/* if (a[O] > o.0){ thisframe- > alltrans[j].ang.theta = 406 120 atan2(a[1],a[2])*180./PI; } else { thisframe- > alltrans[j].ang.theta = atan2( a[O],a[l]) * 180./P; } */ thisframe->flexion = flex * 180./PI; 130 thisframe->abduction = abd * 180./PI; thisframe->extrotation = rot * 180./PI; return; E.3.3 Programs for data taken after 1986 from prosthesis 33 READDAT.C /********* /* ****************** readdat ********/ / ]/* file to just read a frame at a time of */ /* .DAT file and save info */ /* 2/241/93 K.C. C. ******t******************************* ************ #include <stdio.h> #include <stdlib.h> #include <malloc.h> 10 #indude <errno.h> #include "kinemat.h" #include "pfile.h" #include "fnc.h" void readdat(struct kineinfo *kinfo, FILE *dfile, fpos_t *fdpos) ( 407 char *pchar,*dum; char pchararray[260]; int i, j, k, 1, nseg, retval, err; 20 float *data; float dat; nseg = kinfo->nseg; / * pchar= (char *) calloc(16*16,sizeof(char)); */ for (=Oj<2a;j++){ 30 for (k=O;k<3;k++){ for (1=0;1<3;1++){ kinfo->array_rotj][k][] = 0.0; kinfo->array..pos [j][k] = 0.0; /* Now eztract the array position and rotation matrices*/ t/* from the stored data. 16 numbers per segment per frame / Order - array position, 4 unidentified #'s, array rot. */ $ 40 */ pchar = &pchar_ar:ay[O]; err = fsetpos (dfile, fdpos); if ((retval = (fread(pchar,sizeof(char),256, dfile))) != 256 ){ printf("Notreading in readdat.c\n"); scanf( "%c",dum); } err = fgetpos (dfile, fdpos); 50 for (i=0;i<64;i++){ dat = floatflt(pchar); pchar+=4; 408 } pchar=&pchararray[0]; pchar += 16*2*4;/* Increment pointer to femoral array(segs)*/ for Uj=0Oj<2j++){ /* Segment loop */ for (k=O;k<3;k++){ kinfo->arrayjoslj][k] = floatflt(pchar); /* printf("f ",kinfo->arraypos[j][k]);*/ o60 pchar+=4; pchar+=(4*4); /* Pass the 4 unidentified numbers */ for (k=O;k<3;k++){ for (1=0;1<3;1++){ kinfo->arrayrot] /* [k][1]= floatflt(pchar); printf("%f ",kinfo->array_rotfj][f][l]);*/ pchar+=4; 70 } printf(" \n"); /* free(pchar); '/ return; READFPD.C /************************************************************* /* readJpd */ /* File to readFPD files (in binary) $/ /* single frame at a time */ /* 2/24/9S * K. C. #include <stdio.h> #include <stdlib.h> 1o #include <malloc.h> 409 #include <math.h> #include <errno.h> #include "pfile.h" #include "kinemat.h" #include "nc.h" void read_fpd (struct kineinfo *kinfo, FILE *fdata, int itime, transa *thisframe, fpost *ffpos,int kframe) { 20 char *pchar; int i, j, k, , nseg, err, retval, knext,frame; float *fpd; float v!gtnt; char pchararray[50]; double time, rem; double *intptr; /* printf('J\n enteringreadfpd");*/ 30 /* if (NULL == (pchar= (char ) calloc(48, sizeof(char)))){ error('"\n null pointer in readfpd"); (itme == if (itime == 0){ for (i=O;i<10;i++){ writestat (21); pchar = &pchararray[O]; err = fsetpos(fdata, ffpos); retval = fread(pchar,siseof(char),6*8,fdata); err = fgetpos(fdata, ffpos); wgtnt } = info->wgt * 9.8/2.2; / t. in lb -> tt. in Newtons write stat(22); pchar = &pchar array[O]; err = fsetpos(fdata, ffpos); 410 40 if (kinfo->freq > 254.){ time = ((double) itime)/254.; rem = modf ((time * (kinfo->freq)), intptr); so frame = (int)floor(*intptr); if (rem > 0.5) frame++; } else frame = kframe; for (k=O;k<(frame-kframe+1);k++){ retval = fread(pchar,siseof(char),6*8,fdata); err = fgetpos(fdata, ffpos); /* Scale the FP data by 100/body wt in Newtons (as at MGH) */ 60 pchar+=4; write stat(23); write stat(24); thisframe->fpl_vert= -1.0 * (floatflt(pchar))* 100. / wgtnt; pchar+=(6*4); thisframe->fp2vert = -1.O*(floatflt(pchar))*100./wgtnt; /* free(pchar); */ write stat(25); /* printf("\n eziting readfpd");*/ 70 return; BREADPR.C /* * breadprs /* subroutine to read binary .PRS files /* a frame at a time. /* made it change to MPA too /* /* */ */ */ * 2/24/93 K.C. */ 411 #include 10 <stdio.h> #include <string.h> #include <math.h> #include <errno.h> #include "pfi1e.h" #Lnclude "kinemat.h" #include "fnc.h" int breadprs (struct kineinfo *Icinfo, struct datainfo *pinfo, FILE *prsfile, struct pzeros *pzero, int itime, int curframe, trans a *thisframe, fpos-t *fppos) 20 int i, j, k, ib[16], pframe, iheader; int dum[64], retval, err; int *pdum; float offset[14], gain[14], tempcorr[14], temp; float *poff, *pgain, *ptcorr; double data[16], time, rem; int *pib; double *p_data; double pf, *intptr; 30 fpos_t *fpos; p_ib = &ib[O]; p_data = &data[O]; poff = &offset[O]; pgain = &gain[O]; ptcorr = &tempcorr[O]; intptr = &pf; pdum = &dum[O]; fpos = fppos; 40 /* Read the data then turn into pressures /* Only have to deal with prosthesis 33 /* First time through, find zeros, read header 412 * */ if (itime== 0)( writestat(ll); temp = sero33 (poff, pgain, ptcorr, pinfo); writestat(12); psero->temp = temp; so for (i=O;i<14;i++){ pzero->offset[i] = *poff; pzero->gain[i] = *pgain; pzero->tempcorr[i] = *ptcorr; poff++; pgain++; ptcorr++; } poff-=14; pgain-=14; 60 ptcorr-=14; iheader=8; if ( pinfo->date[2]!=86)iheader=11; for (i=O;i<iheader;i++){ pdum = &dum[O]; err = fsetpos(prsfile, fpos); retval = fread(pdum,siseof(int),64,prsfile); err = fgetpos(prsfile, fpos); 70 pinfo->freq = 254.; strcpy(pinfo->id,"33"); pinfo->ntrans=13; else{ for (i=O;i<14;i++){ offset[i] = pzero->offset[i]; gain[i] = pzero->gain[i]; tempcorr[i] = pzero->tempcorr[i]; so80 } 413 temp = pzero->temp; } time = ((double)itime)/ (kinfo->freq); rem = modf ((time * pinfo->freq), intptr); pframe = (int) floor(*intptr); if (rem > 0.5) pframe++; for (k=curframe; k<pframe; k++){ pdum = &dum[O]; err = fsetpos (prsfile, fpos); fread(pdum,sizeof(int),64,prsfile); 90 err = fgetpos (prsfile, fpos); } pdum = &dum[O]; err = fsetpos (prsfile, fpos); retval = fread(pdum,sizeof(int),64,prsfile); err = fgetpos(prsfile, fpos); for (j=l; j<17; j++)( iblj-1] = dumlj]; loo100 pframe++; write stat(13); raw to mpa(pib, p_data, pinfo, poff, pgain, ptcorr, temp); for j=2; j<15; j++){ if (j!=5&&j!=7&&j!=9){ thisframe->alltransUj-2].mpa = data[j-2]; } else { thisframe->alltrans[j-2].mpa = 0.0; 110 thisframe->time = time; return(pframe); AREADPR.C 414 / ************************************* /* aread'ra ********/ *'1 /* subroutine to read ASCII .PRS files */ /* a frame at a time. */ /* made it change to MPA too */ /* 2/21/93 */ K.C. /**********$ **************$*********/ #include <stdio.h> #include <string.h> #include <math.h> #include <errno.h> #include "pf ile .h" #include "kinemat .h" #include "inc .h" 10 int aread-prs (struct kineinfo *kinfo, struct datainfo *pinfo. FILE *prsfile, struct peros *pzero,int itime, int curframe, transa *thisframe, fpost *fppos) 20 int i, j, k, ib[16], pframe; int dum[38], pfreq, retval, err; int *pdum; float offset[14], gain[14], tempcorr[14], temp; float *poff, *pgain, *ptcorr; double data[16], time, rem; int *pib; double *p_data; 30 double pf, *intptr; pib = &ib[O]; p_data = &data[O]; poff = &offset[O]; pgain = &gain[O]; 415 ptcorr = &tempcorr[O]; intptr = &pf; pdum = &dum[O]; 40 /* Read the data then turn into pressures */ /* Only have to deal with prosthesis 33 */ /* First time through,find zeros, read header */ if (itime == 0){ temp = sero33 (poff, pgain, ptcorr, pinfo); pzero->temp = temp; for (i=O;i<14;i++){ pzero->offset[i] = *poff; pzero->gain[i] = *pgain; so pzero->tempcorr[i] = *ptcorr; poff++; pgain++; ptcorr++; poff-=14; pgain-=14; ptcorr-=14; err = fsetpos(prsfile, fppos); fscanf (prsfile, "%d %d",&pinfo->frames,&pfreq); eo0 fscanf (prsfile, "%d %d %2d%*d",&pinfo->date[O], &pinfo->date[], &pinfo->date[2]); err = fgetpos(prsfile, fppos); strcpy (pinfo->id,"33"); pinfo->freq = (double)pfreq; pinfo->ntrans = 13; } else{ for (i=O;i<14;i++){ offset[i] = pzero->offset[i]; gain[i] = psero->gain[i]; tempcorr[i] = psero->tempcorr[i]; 416 70 } temp = pzero->temp; } time = ((double)itime)/ (kinfo->freq); rem = modf ((time * pinfo->freq), intptr); pframe = (int) fioor(*intptr); if (rem > 0.5) pframe++; s80 err = fsetpos(prsfile, fppos); for (k=curframe; k<pframe; k++){ for Uj=Oj<37j++){ fscanf(prsfile,"%*d"); for (j=O;j<37; j++){ if (j>=1 &&j<=16) fscanf(prsfile,"%d",&ib[j-1]); else fscanf (prsfile,"%*d"); } so err = fgetpos(prsfile, fppos); pframe++; rawto_mpa(p_ib, p_data, pinfo, poff, pgain, ptcorr, temp}; for (j=2; j<15; j++){ if (j!=5&&j!=7&&j!=9){ thisframe->alltrans[j-2].mpa = data[j-2]; thisframe->time = time; loo return(pframe); E.4 Programs for acetabular regional information LOC3STA.C 417 / ************$ /* /* *$*** ******************************$*/ locstat.c Program to take a file written by "locate.eze" that */ /* contains pressure data and phi and theta and to calc. */ /* some basic statistics for small regions- like maz p */ /* in that regionfor that file, min p, avg p, rms pressure*/ Jan 18, 1993 */ K.C. 10 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <errno.h> float pmax[36] [36],pmin[36] [36],pavg[36][36],prms[36] [36]; int pnpts[36][36]; 20 void cartcalc(float, float, float, float *, float *, float *, char); void main (int argc, char *argvO) { char inname[40], outname[40], batname[40]; char title[40], side[3]; int ij,k,nframe, ntrans, skip, npts,nphi, ntheta; int ii, jj, retval; float phi, theta, x[2], y[2], z[2], time; float p, trans, ht, wt; 30 float normalize, scale, dum; float *px, *py, *pz; FILE *infile; FILE *outfile; FILE *batfile; fpost *start; 418 if (argc < 2) printf("Supplythe batch file nameto process.\n"); 40 scanf("X1s",argv[1]); /* Automate the file accessing,numbering somewhat*/ /* Assume that input is a batchfile with files that*/ /* Want to process. /* Assume input file names are "name".tec; Output will*/ /* be "name".stat and maybe "name"s.tec */ */ strcpy(batname,argv[1]); batfile = fopen(batname,"r"); so if (batfile == NULL){ printf("Couldn't open batch file\n"); abort; } njphi = 36; n theta = 36; while ( (fscanf(batfile,"%s",inname))!= EOF ){ strcpy(outname,inname); strcat(inname,". tec'"); so strcat(outname,"stat3. tec"); printf("Processing %s\n",inname); dum = 0.0; ntrans = 13; /* /* Just set it for now. */ Initializethe arrays */ for (i=O;i<n_phi;i++){ for (j=O;i<ntheta++){ pmax[i]] = 0.0; pmin[i]U] = 0.0; pavg[i[i] = 0.0; 70 prms[i]U] = 0.0; pnpts[i][j] = 0.0; 419 now, don't }For normalize, but may ant to eventually fscanf (batfile,".f ",&ht); fscanf (batfile,"U.f", &wt); 80 fscanf (batfile,"/,s",side); /* side = '' or 'R '*/ px = &x[O]; py = &y[0]; pz = &z[0]; infile = fopen(inname,"r"); outfile = fopen(outname,"w"); fscanf(infile,"%*s %*s %s",title); fscanf(infile,"%*s /* %*s %*s %*s %*s %*s %*s"); Calculatenumber of points to do for each line fscanf(infile,"Y,*s 90 */ %*s %*s %d, %*s %*s",&nframe); npts = nframe; retval = fgetpos(infile,start); for (j=O;j<ntrans;j++){ printf("Transducer %d\n"j); for (i=O;i<nframe;i++){ fscanf(infile,"%i . .1", &time, &trans, .f % %i &phi, &theta, &p); if (theta < -115. && theta > -180.) theta=theta+360.; ii = (int)(((phi-30.)/80.)*n_phi - 0.5); jj = (int)(((theta+65.)/310.)*n_theta - 0.5); if ((ii >= 0 && ii <= 35)&&(jj>=O&&j<=35)){ if (pmax[ii]j] < p) pmax[ii]jj] = p; if (pmin[ii][j] > p) pmin[ii]ijj] = p; pnpts[ii] j]++; 420 100 pavg[i[iW]+=p; } 110 } fscanf(infile,"'i,* %*s %*s %*d, %.* %*s"); } for (ii=O;ii<n_phi;ii++){ for(jj=Ojj<n_thetaWjj++){ if (pnpts[ii]jj] != 0){ pavg[ii][j] = pavg[ii]j]/pnpts[ii]Dj]; } 120 retval = fsetpos(infile,start); for =O;ij<ntrans;ij++){ for (i=O;i<nframe;i++){ fscanf(infile,"%f% %f %f %f", &time, &trans, &phi, &theta, &p); if (theta < -115. && theta > -180.) theta=theta+360.; ii = (int)(((phi-30.)/80.)*nphi- 0.5); ii = (int)(((theta+65)/310)*n_theta- 0.5); 180 if ((ii >= 0 && ii <= 35)&&(jj>=0&&jj<=35)){ prms[ii][j] += (pow((p-pavg[ii]U]),2)); fscanf(infi1e,"%*s %*s %*s %*d, %*s %*s"); /* Not sure I'm calculatingprns correctly--- CHECK */ for (ii=O;ii<n_phi;ii++){ 140 for(jj=Oj;j<n_thetajj++){ if (pnpts[ii]ji] != 0){ prms[ii]ij] = prms[ii]ijj]/pnpts[ii][jj]; prms[ii]Lj] =(float)sqrt((double)prms[ii] 421 j]); fclose(infile); P = 0.0; /* /* 150 side[O]= 'L';*/ / Just set it for now */ Write the output file: for now do as phi,theta + stats */ fprintf(outfile,"TITLE=""stat%a""\n",outname); fprintf(outfile,"VARIABLES = x, y, z, pmax, pmin, pavg, pnpts, prms\n"); fprintf(outfile,"ZONE T=acet, I=%d, J=%d, F=POINT\n",nphi,n_theta); for (jj=O;j<n thetajj++){ theta = ((((float)jj+ 0.5)*310./n phi)-65.); for (ii=O;ii<n_phi;ii++){ phi = ((((float)ii+ 0.5)* 80/n.phi)+30.); cartcalc(phi,theta,p,px,py,pz,side[O]); fprintf(outfile,"%f % 10eo f %f%f %f %f %fIf", \ x[],y[O],[O],\ pmax[ii] Uj[i],pmin[ii]ij],pavg[ii][j],\ ((float)pnpts[ii] ij]),prms[ii] Uj]); fclose(outfile); CARTCALC.C / ********************************************** /* ********* cartcalc.c /* ********/ */ Just gets Cartesiancoordinates for phi, theta, P /* For representingpressure in acetabularor femoral /* coordinatesas a line, length proportional to P. */ */ ~s/ / / */ Jan 2, 1993 K.C. $$$**********tt*********** ***t*t**t**t*tt*****t****/ 422 10 #include <stdio.h> #include <string.h> #include <math.h> #define PI 3.14159 void cartcalc (float phi, float theta, float p, float *px, float *py,float *pz, char *side) { int i; double dtr; 20 dtr = PI/180.0; *px = (float) sin(phi*dtr)*cos(theta*dtr); *py = (float) sin(phi*dtr)*sin(theta*dtr); *p, = - (float)(cos(phi*dtr)); if (side[O]== 'L') printf("L\n"); *p = (float) cos(phi*dtr); } 30 px++; PY++; pz++; *px = (float) (p+l)*sin(phi*dtr)*cos(theta*dtr); *py = (float) (p+l)*sin(phi*dtr)*sin(theta*dtr); *ps = - (oat) ((p+1)*cos(phi*dtr)); if (side[O]== 'L') *pz = (float) ((p+l)*cos(phi*dtr)); 4o px--; py--; pz--; return; 423 } ___ 424 Bibliography [1] Eric K. Antonsson. A Three-DimensionalKinematic Acquisition and Intersegmental Dynamic Analysis System for Human Motion. PhD thesis, Massachusetts Institute of Technology, 1982. [2] G. Bergmann, F. Graichen, and A. Rohlmann. Five month in vivo measurement of hip joint forces. In XII Int'l Congress of Biomechanics, 1989. [3] G. Bergmann, F. Graichen, and A. Rohlmann. Instrumentation of a hip joint prosthesis. In Implantable Telemetry in Orthopaedics,1990. [4] R.H. Brown, A.H. Burstein, and V.H. Frankel. Telemetering in vivo loads from nail plate implants. J. Biomech, 15, 1982. [5] R.G. Burgess and R.W. Mann. A precision pam-fm multichannel implantable patient-monitor telemetry system. In Proc., IEEE 9th Ann. Conf. of the Eng. in Med and Biol. Soc., volume 3, pages 1501-1502, Nov 1987. [6] Charles E. Carlson. An Instrumented Prosthesis for Measuring the Cartilage Surface Pressure Distribution in the Human Hip. PhD thesis, Massachusetts Institute of Technology, June 1972. [7] Charles E. Carlson, R.W. Mann, and Harris W.H. A radio telemetry device for monitoring cartilage surface pressures in the human hip. IEEE Transactions on Biomedical Eng., BME-21:4,July 1974. [8] Kjirste Carlson. Programs for processing pressure data. Interoffice document, 1993. 425 [9] Kjirste L. Carlson. Local pressures in the human hip joint in vivo; correlated with motion kinematics and external forces. Master's thesis, Massachusetts Institute of Technology, 1986. [10] Tatiana Carvajal. In Vivo pressure distribution data from the human hip joint. Master's thesis, M.I.T., 1985. [11] M.C. Clayton, K.L. Carlson, W.A. Hodge, and R.W. Mann. Postmortem cartilage changes due to in vivo hip pressures. In 8th Annual Meeting, Orthopedic Research Society, 1992. [12] Frank C. Conati. Real-time measurement of three-dimensional multiple rigid body motion. Master's thesis, M.I.T., June 1977. [13] T.A. English and M. Kilvington. In Vivo records of hip loads using a femoral implant with telemetric output ( a preliminaryreport). J. Biomed. Eng., 1, April 1979. [14] A.C. Hall, J.P.G. Urban, and K.A. Gehl. The effects of hydrostatic pressure on matrix synthesis in articular cartilage. Journal of OrthopaedicResearch,1991. [15] W.H. Harris and C.B. Sledge. Total hip and total knee replacement (part 1). New England Journal of Medicine, 323, Sept. 1990. [16] N.J. Hogan. Adaptive control of natural joint stiffness by antagonist muscles. IEEE Trans. on Automatic Control,1981. [17] Patrick J. Lord. Real-time analysis and display of human movement. Master's thesis, Massachusetts Institute of Technology, 1989. [18] Robert W. Mann. Understanding synovial joint mechanics. [19] Peter K. Mansfield. A Large Volume Close-Range Photogrammetric System. PhD thesis, Massachusetts Institute of Technology, June 1990. [20] J.P. Paul. Forces at the Human Hip Joint. PhD thesis, University of Glasgow, Scotland, 1967. 426 [21] Paul D. Rushfeldt. Human Hip Joint Geometry and the Resulting Pressure Distributions. PhD thesis, Massachusetts Institute of Technology, 1978. [22] N.W. Rydell. Forces acting on the femoral head prosthesis. 1966. [23] Avram K. Tetewsky. Implementing a real-time computation and display algorithm for the selspot system. Master's thesis, M.I.T., May 1983. [24] Tupling and Pierrynowski. Use of cardian angles to locate rigid bodies in threedimensional space. Med. and Biol. Eng. and Computing, 25:527-532, 1987. [25] Inc Voluntary Hospitals of America. Examining hip and knee implants, 1992. [26] J. Wolff. Uber die bedeutung der architektur der spongiosen substanz. Zentralblatt fur die medizinische Wisseschaft, 1869. [27] Quiang Xue. Characterizationof the Interarticular Gap in the Loaded Human Hip Joint. PhD thesis, Massachusetts Institiute of Technology, January 1991. 427