Skip to content

Commit d00a773

Browse files
Fixes to figures.
1 parent 6e1cdf2 commit d00a773

3 files changed

Lines changed: 32 additions & 50 deletions

File tree

pedometer/pedometer.markdown

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ An accelerometer returns a *signal* in 3-dimensional space. A signal is a set of
2525

2626
\aosafigref{500l.pedometer.accelerationtotal} shows an example acceleration signal from an accelerometer with the three time series.
2727

28-
\aosafigure{pedometer-images/acceleration-total.png}{Example acceleration signal}{500l.pedometer.accelerationtotal}
28+
\aosafigure[333pt]{pedometer-images/acceleration-total.png}{Example acceleration signal}{500l.pedometer.accelerationtotal}
2929

3030
The *sampling rate* of the accelerometer, which can often be calibrated, determines the number of measurements per second. For instance, an accelerometer with a sampling rate of 100 returns 100 data points for each $x$, $y$, and $z$ time series every second.
3131

@@ -57,15 +57,15 @@ The force of gravity causes an acceleration in the direction of gravity, which w
5757

5858
Suppose a smartphone is lying on a table screen-side up. In this orientation, our coordinate system is such that the negative $z$ direction is the one that gravity is acting on. Gravity will pull our phone in the negative $z$ direction, so our accelerometer, *even when perfectly still*, will record an acceleration of 9.8 $m/s^2$ in the negative $z$ direction. Accelerometer data from our phone in this orientation is shown in \aosafigref{500l.pedometer.accelerationtotalphonestill}.
5959

60-
\aosafigure{pedometer-images/acceleration-total-phone-still.png}{Example accelerometer data at rest}{500l.pedometer.accelerationtotalphonestill}
60+
\aosafigure[333pt]{pedometer-images/acceleration-total-phone-still.png}{Example accelerometer data at rest}{500l.pedometer.accelerationtotalphonestill}
6161

6262
Note that $x(t)$ and $y(t)$ remain constant at 0, while $z(t)$ is constant at -1 *g*. Our accelerometer records all acceleration, including gravitational acceleration.
6363

6464
Each time series measures the *total acceleration* in that direction. Total acceleration is the sum of *user acceleration* and *gravitational acceleration*.
6565

6666
User acceleration is the acceleration of the device due to the movement of the user, and is constant at 0 when the phone is perfectly still. However, when the user is moving with the device, user acceleration is rarely constant, since it's difficult for a person to move with a constant acceleration.
6767

68-
\aosafigure{pedometer-images/component-signals-2.png}{Component signals}{500l.pedometer.componentsignals}
68+
\aosafigure[240pt]{pedometer-images/component-signals-2.png}{Component signals}{500l.pedometer.componentsignals}
6969

7070
To count steps, we're interested in the bounces created by the user in the direction of gravity. That means we're interested in isolating the 1-dimensional time series which describes **user acceleration in the direction of gravity** from our 3-dimensional acceleration signal (\aosafigref{500l.pedometer.componentsignals}).
7171

@@ -81,7 +81,7 @@ What if a person carries the phone in a bag on their shoulder, with the phone in
8181

8282
Yikes. Now all three of our components have a non-zero gravitational acceleration, so the user acceleration in the direction of gravity is now split amongst all three time series. To determine user acceleration in the direction of gravity, we first have to determine which direction gravity is acting in. To do this, we have to split total acceleration in each of the three time series into a user acceleration time series and a gravitational acceleration time series (\aosafigref{500l.pedometer.component3}).
8383

84-
\aosafigure{pedometer-images/component-signals-3.png}{More complicated component signals}{500l.pedometer.component3}
84+
\aosafigure[240pt]{pedometer-images/component-signals-3.png}{More complicated component signals}{500l.pedometer.component3}
8585

8686
Then we can isolate the portion of user acceleration in each component that is in the direction of gravity, resulting in just the user acceleration in the direction of gravity time series.
8787

@@ -135,7 +135,7 @@ $$z_{g}(t) = \alpha_{0}(z(t)\beta_{0} + z(t-1)\beta_{1} + z(t-2)\beta_{2} - z_{g
135135

136136
The resulting time series after low-pass filtering are in \aosafigref{500l.pedometer.accelerationgravitational}.
137137

138-
\aosafigure{pedometer-images/acceleration-gravitational.png}{Example acceleration signal}{500l.pedometer.accelerationgravitational}
138+
\aosafigure[333pt]{pedometer-images/acceleration-gravitational.png}{Gravitational acceleration}{500l.pedometer.accelerationgravitational}
139139

140140
$x_{g}(t)$ and $z_{g}(t)$ hover around 0, and $y_{g}(t)$ very quickly drops to $-1g$. The initial 0 value in $y_{g}(t)$ is from the initialization of the formula.
141141

@@ -155,7 +155,7 @@ The result is the time series seen in
155155
\aosafigref{500l.pedometer.accelerationuser}. We've successfully split our
156156
total acceleration into user acceleration and gravitational acceleration!
157157

158-
\aosafigure{pedometer-images/acceleration-user.png}{Split acceleration}{500l.pedometer.accelerationuser}
158+
\aosafigure[333pt]{pedometer-images/acceleration-user.png}{Split acceleration}{500l.pedometer.accelerationuser}
159159

160160

161161
### 2. Isolating User Acceleration in the Direction of Gravity
@@ -170,22 +170,22 @@ When working with coordinates, you won't get very far before being introduced to
170170

171171
The dot product takes us from 3-dimensional space to 1-dimensional space (\aosafigref{500l.pedometer.dotproduct}). When we take the dot product of the two time series, user acceleration and gravitational acceleration, both of which are in 3-dimensional space, we'll be left with a single time series in 1-dimensional space representing the portion of user acceleration in the direction of gravity. We'll arbitrarily call this new time series $a(t)$, because, well, every important time series deserves a name.
172172

173-
\aosafigure{pedometer-images/dot-product-explanation.png}{The dot product}{500l.pedometer.dotproduct}
173+
\aosafigure[333pt]{pedometer-images/dot-product-explanation.png}{The dot product}{500l.pedometer.dotproduct}
174174

175175

176176
#### Implementing the Dot Product
177177

178178
We can implement the dot product for our earlier example using the formula $a(t) = x_{u}(t)x_{g}(t) + y_{u}(t)y_{g}(t) + z_{u}(t)z_{g}(t)$, leaving us with $a(t)$ in 1-dimensional space (\aosafigref{500l.pedometer.accelerationdotproduct}).
179179

180-
\aosafigure{pedometer-images/acceleration-dotproduct.png}{Implementing the dot product}{500l.pedometer.accelerationdotproduct}
180+
\aosafigure[333pt]{pedometer-images/acceleration-dotproduct.png}{Implementing the dot product}{500l.pedometer.accelerationdotproduct}
181181

182182
We can now visually pick out where the steps are in $a(t)$. The dot product is very powerful, yet beautifully simple.
183183

184184
### Solutions in the Real World
185185

186186
We saw how quickly our seemingly simple problem became more complex when we threw in the challenges of the real world and real people. However, we're getting a lot closer to counting steps, and we can see how $a(t)$ is starting to resemble our ideal sine wave. But, only "kinda, sorta" starting to. We still need to make our messy $a(t)$ time series smoother. There are four main issues (\aosafigref{500l.pedometer.problems}) with $a(t)$ in its current state. Let's examine each one.
187187

188-
\aosafigure{pedometer-images/jumpy-slow-short-bumpy.png}{Jumpy, slow, short, bumpy}{500l.pedometer.problems}
188+
\aosafigure[333pt]{pedometer-images/jumpy-slow-short-bumpy.png}{Jumpy, slow, short, bumpy}{500l.pedometer.problems}
189189

190190

191191
#### 1. Jumpy Peaks
@@ -208,7 +208,7 @@ When bumpiness occurs at our threshold, we can mistakenly count too many steps f
208208

209209
#### Peaks That Are Juuuust Right
210210

211-
\aosafigure{pedometer-images/acceleration-filtered.png}{Tweaked peaks}{500l.pedometer.accelerationfiltered}
211+
\aosafigure[333pt]{pedometer-images/acceleration-filtered.png}{Tweaked peaks}{500l.pedometer.accelerationfiltered}
212212

213213
In accounting for these four scenarios, we've managed to bring our messy $a(t)$ fairly close to our ideal sine wave (\aosafigref{500l.pedometer.accelerationfiltered}), allowing us to count steps.
214214

@@ -316,7 +316,7 @@ Dealing with multiple input formats is a common programming problem. If we want
316316

317317
The cleanest way for us to deal with this is to take our two input formats and fit them into a standard format as soon as possible, allowing the rest of the program to work with this new standard format. Our solution requires that we work with user acceleration and gravitational acceleration separately, so our standard format will need to be split into the two accelerations (\aosafigref{500l.pedometer.standardformat}).
318318

319-
\aosafigure{pedometer-images/standard-format.png}{Standard format}{500l.pedometer.standardformat}
319+
\aosafigure[240pt]{pedometer-images/standard-format.png}{Standard format}{500l.pedometer.standardformat}
320320

321321
Our standard format allows us to store a time series, as each element represents acceleration at a point in time. We've defined it as an array of arrays of arrays. Let's peel that onion.
322322

@@ -328,15 +328,15 @@ Our standard format allows us to store a time series, as each element represents
328328

329329
The input into our system will be data from an accelerometer, information on the user taking the walk (gender, stride, etc.), and information on the trial walk itself (sampling rate, actual steps taken, etc.). Our system will apply the signal processing solution, and output the number of steps calculated, the delta between the actual steps and calculated steps, the distance travelled, and the elapsed time. The entire process from input to output can be viewed as a pipeline (\aosafigref{500l.pedometer.pipeline}).
330330

331-
\aosafigure{pedometer-images/pipeline.png}{The pipeline}{500l.pedometer.pipeline}
331+
\aosafigure[240pt]{pedometer-images/pipeline.png}{The pipeline}{500l.pedometer.pipeline}
332332

333333
In the spirit of separation of concerns, we'll write the code for each distinct component of the pipeline --- parsing, processing, and analyzing --- individually.
334334

335335
### Parsing
336336

337337
Given that we want our data in the standard format as early as possible, it makes sense to write a parser that allows us to take our two known input formats and convert them to a standard output format as the first component of our pipeline. Our standard format splits out user acceleration and gravitational acceleration, which means that if our data is in the combined format, our parser will need to first pass it through a low-pass filter to convert it to the standard format.
338338

339-
\aosafigure{pedometer-images/input-data-workflow-1.png}{Initial workflow}{500l.pedometer.input1}
339+
\aosafigure[240pt]{pedometer-images/input-data-workflow-1.png}{Initial workflow}{500l.pedometer.input1}
340340

341341
In the future, if we ever have to add another input format, the only code we'll have to touch is this parser. Let's separate concerns once more, and create a `Parser` class to handle the parsing.
342342

@@ -410,7 +410,7 @@ We'll handle short and bumpy peaks by avoiding them during step counting.
410410

411411
Now that we have our data in the standard format, we can process it to get in into a state where we can analyze it to count steps (\aosafigref{500l.pedometer.input2}).
412412

413-
\aosafigure{pedometer-images/input-data-workflow-2.png}{Processing}{500l.pedometer.input2}
413+
\aosafigure[166pt]{pedometer-images/input-data-workflow-2.png}{Processing}{500l.pedometer.input2}
414414

415415
The purpose of processing is to take our data in the standard format and incrementally clean it up to get it to a state as close as possible to our ideal sine wave. Our two processing operations, taking the dot product and filtering, are quite distinct, but both are intended to process our data, so we'll create one class called a `Processor`.
416416

@@ -665,13 +665,13 @@ We're through the most labour intensive part of our program. Next, we'll build a
665665

666666
When a user first enters the app by navigating to `/uploads`, they see a table of existing data and a form to submit new data by uploading an accelerometer output file and trial and user information (\aosafigref{500l.pedometer.app1}).
667667

668-
\aosafigure{pedometer-images/app1.png}{Upload view}{500l.pedometer.app1}
668+
\aosafigure[240pt]{pedometer-images/app1.png}{Upload view}{500l.pedometer.app1}
669669

670670
Submitting the form stores the data to the file system, parses, processes, and analyzes it, and redirects back to `/uploads` with the new entry in the table.
671671

672672
Clicking the **Detail** link for an entry presents the user with the following view in \aosafigref{500l.pedometer.app3}.
673673

674-
\aosafigure{pedometer-images/app3.png}{Detail view}{500l.pedometer.app3}
674+
\aosafigure[240pt]{pedometer-images/app3.png}{Detail view}{500l.pedometer.app3}
675675

676676
The information presented includes values input by the user through the upload form, values calculated by our program, and graphs of the time series following the dot product operation, and again following filtering. The user can navigate back to `/uploads` using the *Back to Uploads* link.
677677

tex/500L.tex

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -261,24 +261,6 @@
261261

262262
\include{pedometer}
263263

264-
\include{sampler}
265-
266-
\include{spreadsheet}
267-
268-
\include{cluster}
269-
270-
\include{data-store}
271-
272-
\include{objmodel}
273-
274-
\include{ci}
275-
276-
\include{crawler}
277-
278-
\include{template-engine}
279-
280-
\include{modeller}
281-
282264

283265
\bibliographystyle{alpha}
284266

0 commit comments

Comments
 (0)