Data Human Hip Joint Mechanics Replacements using

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