Skip to content

Commit 8ad8d79

Browse files
authored
Update StepCounter.java
Add JavaDoc Style Comments
1 parent 03cd04b commit 8ad8d79

File tree

1 file changed

+103
-39
lines changed

1 file changed

+103
-39
lines changed

src/StepCounter.java

+103-39
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
11
import java.util.Arrays;
22

33
public class StepCounter {
4-
private static final int WINDOW_LENGTH = 5;
5-
private static final double DEVIATION_SCALAR= 0.8;
4+
private static final int WINDOW_LENGTH = 5; //"range" for noise smoothing
5+
private static final double DEVIATION_SCALAR= 0.8; //constant that is multiplied with (mean+standard deviation) to get threshold value for naive algorithm
66
private static final int THRESHOLD_MULTIPLE=5; //multiplication factor for threshold to ensure it is above the magnitudes of invalid steps
7+
private static final double MEAN_SCALAR= 0.54; //scalar applied to mean value of data to calculate minimum reasonable data value (anything smaller in mag. cannot be a step)
8+
private static final double MEAN_SHIFT=0.72; //value to shift mean value of data from to calculate minimum reasonable data value (anything smaller in mag. cannot be a step)
9+
private static final double PERCENT_ACCEPTANCE_POTENTIAL_STEP_ACTIVITY=0.8;
710
public static void main(String[] args) {
8-
String[] columnNames={"time", "gyro-x", "gyro-y", "gyro-z"};
11+
String[] columnNames={"time", "accel-x", "accel-y", "accel-z"};
912
CSVData test = new CSVData("data/50StepWalkFemale(2).csv", columnNames, 1);
1013
test.correctTime(test);
1114
System.out.println("Improved Algorithm:"+countSteps(test.getColumn(0),test.getRows(1,test.getNumRows()-1), 10));
1215
System.out.println("Old Algorithm:"+countSteps(test.getColumn(0),test.getRows(1,test.getNumRows()-1)));
1316
}
14-
//improved algorithm
17+
/***
18+
* NOTE: IMPROVED ALGORITHM
19+
* Counts the number of steps with an adaptive threshold that is calculated for each sensorData value.
20+
* If the resultant of all 3 components of acceleration (from sensorData) is above the adaptive threshold for that point
21+
* and greater in magnitude than its two adjacent points, it is considered a step.
22+
* @param times array of times corresponding to each resultant magnitude from the 3 components of acceleration from sensorData
23+
* @param sensorData 2-D array of sensor data including times(ms) and the three acceleration components (x,y,z)
24+
* @param windowLength length of window adjacent to each resultant acceleration that the thresholds are calculated from
25+
* Ex: windowLength=3 at times=5 means thresholds will be calculated from resultant accelerations corresponding to times
26+
* [2,8]
27+
* @return number of steps counted from sensorData
28+
*/
1529
private static int countSteps(double[] times, double[][] sensorData, int windowLength) {
1630
int stepCount = 0;
1731
double[] arr = new double[times.length];
1832
arr = calculateMagnitudes(sensorData);
1933
double mean = calculateMean(arr);
2034
double minLimit = calculateMinLimit(mean); //minimum magnitude to be a reasonable step
2135
// arr = NoiseSmoothing.generalRunningAverage(arr, 10);
22-
double[] thresholds = calculateWindow(arr, windowLength, minLimit);
36+
double[] thresholds = calculateAdaptiveThreshold(arr, windowLength, minLimit);
2337
for(int i = 1; i < arr.length-1; i++) {
2438
if (arr[i] > arr[i-1] && arr[i] > arr[i+1]) {
2539
if(arr[i] > thresholds[i]) {
@@ -30,7 +44,14 @@ private static int countSteps(double[] times, double[][] sensorData, int windowL
3044
}
3145
return stepCount;
3246
}
33-
//old algorithm
47+
/**
48+
* NOTE: OLD NAIVE ALGORITHM
49+
* Counts the number of steps with a static threshold that is calculated by adding the mean of sensorData resultant acceleration
50+
* vector with the standard deviation of sensorData resultant acceleration vector and multiplied by DEVIATION_SCALAR
51+
* @param times array of times corresponding to each resultant magnitude from the 3 components of acceleration from sensorData
52+
* @param sensorData 2-D array of sensor data including times(ms) and the three acceleration components (x,y,z)
53+
* @return number of steps counted from sensorData
54+
*/
3455
private static int countSteps(double[] times, double[][] sensorData) {
3556
int stepCount = 0;
3657
double[] arr = new double[times.length];
@@ -49,43 +70,48 @@ private static int countSteps(double[] times, double[][] sensorData) {
4970

5071
return stepCount;
5172
}
52-
73+
/**
74+
* Returns minimum magnitude of acceleration resultant vector to be a reasonable step.
75+
* MEAN_SCALAR and MEAN_SHIFT derived from trial-and-error of testing for the best minLimit for different step situations,
76+
* and finding the best linear fit for the data
77+
* @param mean the average from the array of acceleration resultant vectors
78+
* @return minimum magnitude of acceleraiton resultant vecotr to be a reasonable step
79+
*/
5380
public static double calculateMinLimit(double mean){
54-
return 0.54*mean+0.72;
81+
return MEAN_SCALAR*mean+MEAN_SHIFT;
5582
}
56-
/***
83+
/**
5784
* Returns array of threshold values for input window size away from each arr value. If magnitude is unreasonably
5885
* low(not a step), threshold will be set to an extreme high value to avoid counting peaks in no-step noise areas.
5986
* @param arr array of magnitudes to calculate thresholds from
6087
* @param windowLength length of "range" of values next to each magnitude value to calculate threshold from
6188
* @return array of threshold values for every magnitude value calculated with int windowLength values to the left/right of
6289
* magnitude value
6390
*/
64-
public static double[] calculateWindow(double[] arr, int windowLength, double minLimit) {
91+
public static double[] calculateAdaptiveThreshold(double[] arr, int windowLength, double minLimit) {
6592
double[] result=new double[arr.length];
6693
for (int i = 0; i < arr.length; i++){
67-
if(i+windowLength < arr.length) {
68-
if(i-windowLength >= 0) {
94+
if(i+windowLength < arr.length) { //check if in right-hand range
95+
if(i-windowLength >= 0) { //check if in left-hand range
6996
double meanForInterval = calculateMeanInInterval(arr, i-windowLength, i+windowLength);
7097
double deviationForInterval = calculateStandardDeviationInInterval(arr, meanForInterval, i-windowLength, i+windowLength);
71-
if(magnitudeIsUnreasonblySmall(arr, WINDOW_LENGTH, i, minLimit)){
98+
if(isMagnitudeUnreasonablySmall(arr, WINDOW_LENGTH, i, minLimit))
7299
result[i]=((meanForInterval+deviationForInterval))*THRESHOLD_MULTIPLE;
73-
}else{
100+
else
74101
result[i] = (meanForInterval+deviationForInterval);
75-
}
76-
} else {
102+
} else { //if index is within windowLength from the left-hand end of array
77103
double meanForInterval = calculateMeanInInterval(arr, 0, i+windowLength);
78104
double deviationForInterval = calculateStandardDeviationInInterval(arr, meanForInterval, 0, i+windowLength);
79-
if(magnitudeIsUnreasonblySmall(arr, WINDOW_LENGTH, i+WINDOW_LENGTH, minLimit)){
105+
if(isMagnitudeUnreasonablySmall(arr, WINDOW_LENGTH, i+WINDOW_LENGTH, minLimit)){
80106
result[i]=((meanForInterval+deviationForInterval))*THRESHOLD_MULTIPLE;
81107
}else{
82108
result[i] = (meanForInterval+deviationForInterval);
83109
}
84110
}
85-
} else {
111+
} else {//if index is within windowLength from the right-hand end of array
86112
double meanForInterval = calculateMeanInInterval(arr, i-windowLength, arr.length);
87113
double deviationForInterval = calculateStandardDeviationInInterval(arr, meanForInterval, i-windowLength, arr.length);
88-
if(magnitudeIsUnreasonblySmall(arr, WINDOW_LENGTH, i-WINDOW_LENGTH, minLimit)){
114+
if(isMagnitudeUnreasonablySmall(arr, WINDOW_LENGTH, i-WINDOW_LENGTH, minLimit)){
89115
result[i]=((meanForInterval+deviationForInterval))*THRESHOLD_MULTIPLE;
90116
}else{
91117
result[i] = (meanForInterval+deviationForInterval);
@@ -124,31 +150,47 @@ public static double[] calculateWindow(double[] arr, int windowLength, double mi
124150
* @param windowLength range from the arr value
125151
* @param index arr index value to check magnitudes from
126152
* @param threshold threshold for reasonable magnitudes (anything under is considered too small to count as possible steps)
127-
* @return true if >80% of values are under the threshold
153+
* @return true if >80% of values are under the threshold (aka too small to be considered any significant step activity)
154+
* false if <80% of values are under the threshold (aka of enough significance to be considered for potential step activity)
128155
*/
129-
private static boolean magnitudeIsUnreasonblySmall(double[] arr, int windowLength, int index, double threshold) {
130-
int underThresholdCounter = 0;
131-
int totalIterations = 0;
156+
private static boolean isMagnitudeUnreasonablySmall(double[] arr, int windowLength, int index, double threshold) {
157+
int underThresholdCounter = 0, totalIterations=0;
132158
for(int i = index-windowLength; i < index+windowLength; i++) {
133-
if(arr[i] < threshold) {
159+
if(arr[i] < threshold)
134160
underThresholdCounter++;
135-
}
136161
totalIterations++;
137162
}
138-
if((double)underThresholdCounter/(double)totalIterations > 0.8) return true;
163+
if((double)underThresholdCounter/(double)totalIterations > PERCENT_ACCEPTANCE_POTENTIAL_STEP_ACTIVITY)
164+
return true;
139165
return false;
140166
}
141-
142-
public static double[] noiseSmoothing(double[] magnitudes, int averageLength) {
143-
double[] result = new double[magnitudes.length-averageLength];
144-
result = NoiseSmoothing.generalRunningAverage(magnitudes, averageLength);
145-
return result;
146-
}
147-
167+
// /**
168+
// *
169+
// * @param magnitudes
170+
// * @param averageLength
171+
// * @return
172+
// */
173+
// public static double[] noiseSmoothing(double[] magnitudes, int averageLength) {
174+
// double[] result = new double[magnitudes.length-averageLength];
175+
// result = NoiseSmoothing.generalRunningAverage(magnitudes, averageLength);
176+
// return result;
177+
// }
178+
/**
179+
* Returns the magnitude of the resultant vector of three input magnitudes of vectors
180+
* @param x magnitude of x-component vector
181+
* @param y magnitude of y-component vector
182+
* @param z magnitude of z-component vector
183+
* @return magnitude of the resultant vector from three input component vectors
184+
*/
148185
public static double calculateMagnitude(double x, double y, double z) {
149186
return Math.sqrt(x*x + y*y + z*z);
150187
}
151-
188+
/**
189+
* Returns a 1D array with magnitudes of the resultant vectors of three vector components for multiple rows
190+
* Calculates the magnitude of each row of three vector components for multiple rows of sensorData
191+
* @param sensorData 2-D array of sensor data including times(ms) and the three acceleration components (x,y,z)
192+
* @return 1D array with magnitudes of the resultant vectors of three vector components for multiple rows
193+
*/
152194
private static double[] calculateMagnitudes(double[][] sensorData) {
153195
double[] result = new double[sensorData.length];
154196
for(int i = 0; i < sensorData.length; i++) {
@@ -159,36 +201,58 @@ private static double[] calculateMagnitudes(double[][] sensorData) {
159201
}
160202
return result;
161203
}
162-
204+
/**
205+
* Returns standard deviation of a 1D array of values
206+
* @param arr 1D array of values to calculate standard deviation from
207+
* @param mean average of the 1D array
208+
* @return standard deviation of arr
209+
*/
163210
private static double calculateStandardDeviation(double[] arr, double mean) {
164211
double sum = 0;
165212
for (int i = 0; i < arr.length; i++) {
166213
sum += (arr[i] - mean)*(arr[i] - mean);
167214
}
168215
return Math.sqrt(sum/(arr.length-1));
169216
}
170-
217+
/**
218+
* Returns standard deviation of a 1D array in a select interval
219+
* @param arr 1D array of values to calculate standard deviation from
220+
* @param mean average of the 1D array
221+
* @param startInterval starting index of interval
222+
* @param endInterval ending index of interval (non-inclusive)
223+
* @return standard deviation of arr in interval
224+
*/
171225
private static double calculateStandardDeviationInInterval(double[] arr, double mean, int startInterval, int endInterval) {
172226
double sum = 0;
173227
for (int i = startInterval; i < endInterval; i++) {
174228
sum += (arr[i] - mean)*(arr[i] - mean);
175229
}
176230
return Math.sqrt(sum/(double)(endInterval-startInterval));
177231
}
178-
232+
/**
233+
* Returns average from 1D array of values
234+
* @param arr 1D array of values
235+
* @return average of 1D array
236+
*/
179237
private static double calculateMean(double[] arr) {
180238
double sum = 0;
181239
for(int i = 0; i < arr.length; i++) {
182240
sum += arr[i];
183241
}
184242
return sum/arr.length;
185243
}
186-
244+
/**
245+
* Returns average of 1D array in a select interval
246+
* @param arr 1D array of values
247+
* @param startIndex starting index of interval
248+
* @param endIndex ending index of interval (non-inclusive)
249+
* @return average of 1D array
250+
*/
187251
private static double calculateMeanInInterval(double[] arr, int startIndex, int endIndex) {
188252
double sum = 0;
189253
for(int i = startIndex; i < endIndex; i++) {
190254
sum += arr[i];
191255
}
192256
return sum/(double)(endIndex-startIndex);
193257
}
194-
}
258+
}

0 commit comments

Comments
 (0)