open-standards/aac/aac-rs/tools/pagesets/DESIGN-motor.md
2026-10-05 16:06:48 -04:00

347 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Fixed Paths — design
A motor-plan vocabulary: every word has one place to be reached from, by the
same 1, 2 or 3 movements every time, starting from Home. It is designed from
first principles — frequency times motor cost — and is ours: it does not
reproduce LAMP Words for Life's, Speak for Yourself's or Unity's layout,
category scheme or names, and it uses no multi-meaning icon sequences.
- Source: `data/fixed-paths.yaml` (the words, the page each belongs to, the
groups pages fall back on), `data/fixed-paths.layout.yaml` (where
everything sits, solved once and reviewed), `data/lexicon.en.yaml`.
- Output: `fixed-paths-{30,60,84}.obz`, and each with the starter filter;
built by `catalog.py` wherever they are served, never committed (see
DESIGN-core.md for the catalogue, `aac-rs/data/pagesets/index.json`).
- Check: `python3 tools/pagesets/build.py --check`,
`python3 tools/pagesets/catalog.py --check` and
`cargo test -p aac-core --test pagesets`.
- Rebuild: `python3 tools/pagesets/build.py` and `catalog.py --write` (Python
3.11+ and PyYAML, no network). Re-solve the layout:
`python3 tools/pagesets/solve.py motor`, which reproduces the committed one
byte for byte; any change to the design means re-solving, reviewing the
grids, and committing the layout and the catalogue with it.
Tables between `<!-- table:… -->` markers are written by `build.py`.
## 1. Rules
1. **One meaning per location.** A location says one word, or opens one page.
Every button shows the word it says or the name of the page it opens.
2. **One path per word**, at each size: Home → word (1 hit), Home → page →
word (2), or Home → page → group → word (3). The test walks every package
and fails on a word reachable twice or in more than three hits.
3. **Every selection returns Home.** The app has this as the person's setting
("go back to Home after a word", `access.return_home`); SPEC §5.6 item 6
makes it the person's choice, never the board's. So the set does not turn
it on: its manifest says it is made for it
(`ext_aurasense_pageset.recommends.return_home_after_word`), and the
chooser asks when the set is added.
4. **The place that opened a page closes it.** On a page, the cell in the
place of the key that opened it is **Back**, to the board that key is on
(from a group, its page; from a page, Home). A wrong page is undone by
pressing the same place again — the most automatic movement there is — at
no cost of a separate location, and it is the same rule on every page and
group at every size. It is labelled Back, not Home, with the app's arrow and
the control's word in each language: the Places page has the word *home*,
and two buttons reading alike must never mean two things on one page (a
build check; it is also why the body part *back* is not in the set).
5. **The same 472 words at every size**: 30, 60 and 84 locations differ only
in how many words are one hit away.
### The patent constraint
Three PRC patents on multi-meaning symbol sequences are listed as active to
about 2033–34 (US 9,202,298; 9,183,655; 9,239,824). Fixed Paths has no
multi-meaning icons and no icon sequences:
- No picture stands for different words depending on what was pressed before
it. A word's button shows that word; a page key shows the page's name.
- A page key's picture is an exemplar of the words behind it (Family shows
"mom"), as folders do in every grid app; no two keys share a picture, and a
key's label is never a word on the page it sits on (build check).
- A location's meaning never depends on a previous selection: on Home it means
one thing; on a page, that page's cell means one thing.
This is the ordinary navigation of every dynamic-display AAC app (pages of
words), not semantic compaction. It is a design statement, not legal advice;
a freedom-to-operate review is still the founder's call before anything like
icon sequences is ever added.
### Not LAMP, not Speak for Yourself
- **LAMP and Unity** reach words by sequences of multi-meaning icons on one
fixed keyboard. Fixed Paths has none: two-hit words sit on pages of explicit
words.
- **Speak for Yourself** gives each core word its own secondary page of
related words. Fixed Paths groups by meaning (twelve pages: Social, People,
Actions, Describe, Little words, Feelings, Food, Places, Things, Body, Time,
Word forms), and which words are on Home is computed from frequency, not
chosen as a set of keys.
- **TD Snap Motor Plan** is taxonomic too; its layouts and words are not used.
Its published averages (2.3 hits on 30 locations, 2.0 on 66) are a
reference point: Fixed Paths averages 2.36 on 30, 2.00 on 60, 1.86 on 84
(unweighted, §5).
- Every position comes from the optimiser below and the committed layout; the
page and group names are plain English.
## 2. Frequency × motor cost
### Weight of a word
A word's weight is how often it is likely to be chosen: its spoken frequency
(FrequencyWords 2018, OpenSubtitles dialogue, CC BY-SA 4.0), times 4
(`aac_boost` 3) if it is in Universal Core or Banajee et al. (2003). Pure
adult spoken frequency would put "the", "of" and "to" ahead of "want", "more"
and "help"; the boost is the evidence that early communicators need the
latter, from the two open lists made for them. A message (a phrase) weighs a
quarter of its proxy word ("I'm not finished" → "finished"). The metrics show
both weights.
**Home at 30 locations is for a person starting out** (decision of
2026-10-05): its 18 words are the ones that carry a message on their own, from
Universal Core and Banajee et al. (2003) — I, you, it, that, what, want, more,
go, help, stop, not, like, all done, yes, no, my, look, do — and the most
frequent function words ("the", "a", "to", "is", "in", "on") are one page away
(Little words). **At 60 and 84** Home keeps those 18 where they are and adds
the heaviest of the rest by weight, to 48 and 72. The sets nest: a word on
Home at 30 is on Home at 60 and 84.
What the beginners' Home costs, measured on the 30-location set (by spoken
frequency; § 5): a spoken word takes 1.84 hits on average instead of 1.67
with the heaviest words on Home, and 9 of the 25 most-spoken words are one hit
instead of 16 — the words a fluent speaker uses most, for the words a person
starting out needs most. At 60 and 84 the difference is under 2% (the
beginners' words are among the heaviest there anyway).
### What "easy" means
Each model is scaled 0–1 over the grid and blended per size
(`pslib/costs.py`); none is a measurement of a person.
- **Touch**: Fitts' index of difficulty, log2(1 + D/W), from a hand resting
at the bottom centre below the board to the cell, W the cell's smaller side,
on a 10.2-inch tablet in landscape. Easy: low and central.
- **Scanning**: row-column steps from the top left (rows highlighted until the
row, then cells until the cell, both presses counted). Easy: the top left.
The app's opt-in adaptive scan order (SPEC §5.4) can put heavy rows first
without moving a cell, so position matters less here than for touch.
- **Gaze**: distance from the centre of the board, 0 at the centre, 1 at a
corner. A webcam's gaze estimate is least accurate towards the edges, and a
target at the edge has nowhere to put an overshoot. Easy: central, large.
They disagree: touch wants the bottom centre, scanning the top left, gaze the
middle. Blends: **30 locations** (the gaze size) gaze 0.5, touch 0.25, scan
0.25; **60 and 84** touch 0.5, scan 0.25, gaze 0.25.
### Placement
Home items live at points, like the Growing Core's words (DESIGN-core.md §1),
on the ladder 5×6 → 6×10 → 7×12, so an item on Home at 30 stays in the same
region at 60 and 84 and a person moving up keeps their Home motor plan. The
solver (`pslib/solve.py`) minimises Σ weight × blended cost over the three
sizes; a page key weighs the sum of the words behind it at that size. Pages
are then laid out per size: heaviest words in the cheapest cells, the Back
cell where the key was.
**Groups.** When a page has more words than places (always at 30), it frees
places one at a time at the least weight: opening a group moves that group's
two lightest words behind its key (two words out, one key in), and an open
group takes its next lightest. So the heaviest words stay on the page whatever
their group, the lightest of a meaning (Family, Moving, Colors, …) go behind
its key, and no key ever stands for a single word. The Social page keeps its
*repairs* on the page at every size, however full: *wait*, *I'm not finished*,
*that's not what I meant*, *say it again*, *I don't know*.
<!-- table:motor-pages -->
| Page | Words | Groups (by meaning) | Groups in use, by size |
|---|---|---|---|
| Social | 41 | Answers, Manners, Greetings, Turn taking, Likes, Pauses, Exclamations | 30: Exclamations, Greetings, Pauses, Turn taking; 60: none; 84: none |
| People | 43 | Pronouns, Owners, Family, Helpers, Others | 30: Family, Helpers; 60: none; 84: none |
| Actions | 101 | Wanting, Doing, Trying, Moving, Thinking, Talking, Daily | 30: Daily, Doing, Moving, Talking, Thinking, Trying, Wanting; 60: Daily, Doing, Moving, Talking, Thinking, Trying; 84: Daily, Moving |
| Describe | 72 | Amount, Opinions, Size and feel, Colors, Numbers | 30: Colors, Numbers, Opinions, Size and feel; 60: Colors, Size and feel; 84: none |
| Little words | 51 | Questions, Joining, Linking, Position, Negatives | 30: Joining, Linking, Negatives, Position; 60: none; 84: none |
| Feelings | 24 | – | 30: none; 60: none; 84: none |
| Food | 26 | Flavors | 30: none; 60: none; 84: none |
| Places | 17 | – | 30: none; 60: none; 84: none |
| Things | 45 | Play things, Home things, Clothes, Animals, Outside things | 30: Animals, Clothes, Home things, Outside things, Play things; 60: none; 84: none |
| Body | 14 | – | 30: none; 60: none; 84: none |
| Time | 25 | – | 30: none; 60: none; 84: none |
| Word forms | 21 | – | 30: none; 60: none; 84: none |
<!-- /table -->
Home at each size (▸ opens a page):
<!-- table:motor-grids -->
**30 (5x6)**
```
| help | Time▸ | yes | Things▸ | stop | Body▸ |
| more | my | People▸ | Word forms▸ | like | Feelings▸ |
| not | Describe▸ | Little wor~ | Actions▸ | Social▸ | Places▸ |
| go | what | you | I | no | all done |
| look | do | that | it | want | Food▸ |
```
**60 (6x10)**
```
| help | have | this | we | yes | up | Things▸ | stop | was | Body▸ |
| more | good | Time▸ | my | here | Word forms▸ | like | when | your | Feelings▸ |
| why | she | can | People▸ | in | Actions▸ | Social▸ | and | for | Places▸ |
| out | not | Describe▸ | what | Little wor~ | I | on | get | who | be |
| of | go | all | is | you | a | he | no | where | all done |
| me | look | do | that | the | it | to | want | some | Food▸ |
```
**84 (7x12)**
```
| help | have | now | this | we | yes | him | one | stop | got | her | Body▸ |
| more | good | Time▸ | there | off | just | up | Things▸ | when | was | your | Feelings▸ |
| why | they | she | my | People▸ | here | with | Word forms▸ | like | at | come | Places▸ |
| out | not | Describe▸ | can | don't | in | Actions▸ | know | Social▸ | and | for | well |
| of | go | all | what | are | Little wor~ | I | on | get | who | where | be |
| right | look | but | do | is | you | a | he | no | if | put | all done |
| oh | me | so | make | that | the | it | to | want | about | some | Food▸ |
```
<!-- /table -->
Stability of Home across sizes:
<!-- table:motor-stability -->
Home items present at two sizes: 120 pairs; mean shift 0.072 of the board; largest 0.79 cells of the smaller board (`Things`, 6x10 → 7x12); every item's buttons share a point: yes.
<!-- /table -->
### The trade-offs, measured
Each size, laid out four more ways — the blend alone (this size only, no tie to
the other sizes), and each access method alone — then every layout measured
under every method (design-weighted mean per word; hits are the same for all,
since which words are on Home does not depend on where):
<!-- table:motor-tradeoffs -->
| Locations | Layout | Hits | Scan steps | Touch (bits) | Gaze |
|---|---|---|---|---|---|
| 30 | chosen | 1.614 | 10.488 | 3.208 | 0.502 |
| 30 | blend alone | 1.614 | 10.272 | 3.292 | 0.483 |
| 30 | touch only | 1.614 | 12.351 | 2.646 | 0.798 |
| 30 | scan only | 1.614 | 6.314 | 4.152 | 0.997 |
| 30 | gaze only | 1.614 | 10.498 | 3.324 | 0.478 |
| 60 | chosen | 1.178 | 11.149 | 2.371 | 0.486 |
| 60 | blend alone | 1.178 | 11.203 | 2.312 | 0.512 |
| 60 | touch only | 1.178 | 12.314 | 2.225 | 0.597 |
| 60 | scan only | 1.178 | 6.555 | 3.228 | 0.717 |
| 60 | gaze only | 1.178 | 10.543 | 2.739 | 0.383 |
| 84 | chosen | 1.113 | 12.455 | 2.383 | 0.486 |
| 84 | blend alone | 1.113 | 12.604 | 2.298 | 0.49 |
| 84 | touch only | 1.113 | 13.699 | 2.21 | 0.576 |
| 84 | scan only | 1.113 | 6.692 | 3.33 | 0.704 |
| 84 | gaze only | 1.113 | 11.687 | 2.796 | 0.331 |
<!-- /table -->
What it shows:
- A **scan-only** layout needs 40–46% fewer scan steps than the chosen one
(6.3–6.7 against 10.5–12.5) and is the worst for touch and gaze.
- A **touch-only** layout is 6–18% cheaper to touch and the worst to scan.
- **Gaze-only** is within 5% of the chosen layout at 30 locations, where gaze
weighs most; at 60 and 84 it would be 21–32% better for gaze and 16–17%
worse for touch.
- **Tying the three sizes together** (chosen against the blend alone) costs at
most 4% on one measure (gaze at 30, touch at 84) and is better on others.
**One layout for every access method** (decision of 2026-10-05): the layout is
the motor plan, and stays; a person who scans can opt into the app's adaptive
scan order (SPEC §5.4), which puts the rows they use first without moving a
cell.
## 3. Vocabulary filter, and "show everything for now"
A filter shows only its words, each in its place; every other word is hidden
in place (OBF `hidden: true`, the app's `Cell.hidden`). A page or group key shows while any word behind it shows; Back
cells always show. Positions never change (test). The
**starter** filter is Universal Core ∪ Banajee et al. (2003): 45 words for a
person starting out. Filters are lists in `fixed-paths.yaml`, so a team can
write its own; the chooser could also build one from the words a person used
(the app's usage counts), never by moving anything.
"Show everything for now" (Babble, in other apps' words) is Track B's "Show
hidden words for now", in the partner menu and the edit bar, and scanned
(decision of 2026-10-05): it shows every hidden word in its place until it is
turned off, and changes nothing on the board. A word hidden because it has no
word in the person's language stays hidden (DESIGN-core.md §4).
## 4. How the app offers it
As for the Growing Core (DESIGN-core.md §5): at setup and in Settings → Words
and boards, downloaded once, checked, kept on the device, and added as one
undoable change. Then:
1. Choose **30** places (the largest targets, for eye gaze and head pointers),
**60** or **84**; when a size's targets come under 10 mm on this screen, the
chooser says so with the measured size.
2. "Start with the 45 first words" picks the starter package (the filter's
hidden flags are in it: `fixed-paths-<n>-starter.obz`).
3. Its Home **becomes the person's home board** (going back to Home goes
there), and the app **asks once**, in words: "Fixed Paths is made to go
back to Home after each word … Turn that on?" — at setup as part of the
choice, in Settings after the set is added; `access.return_home` is set
only on yes, and the question is not asked again (SPEC §5.6 item 6).
## 5. Metrics
<!-- table:motor-reach -->
| Locations | Grid | Words on Home | Pages | Groups | Words | 1 hit | 2 hits | 3 hits | Mean hits | Hits per word, spoken weight | Hits, design weight | Top 25 in 1 hit | Top 100 in 1 hit | Top 100 in reach | Top 200 in reach | Spoken tokens covered |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 30 | 5x6 | 18 | 12 | 26 | 473 | 18 | 268 | 187 | 2.357 | 1.837 | 1.614 | 9/25 | 14/100 | 99/100 | 156/200 | 73% |
| 60 | 6x10 | 48 | 12 | 8 | 473 | 48 | 377 | 48 | 2.0 | 1.397 | 1.178 | 25/25 | 44/100 | 99/100 | 156/200 | 73% |
| 84 | 7x12 | 72 | 12 | 2 | 473 | 72 | 395 | 6 | 1.86 | 1.259 | 1.113 | 25/25 | 65/100 | 99/100 | 156/200 | 73% |
<!-- /table -->
"Top 100 in reach" counts words the set holds as words: 99 of the 100.
"Going" is "go" and the -ing ending. Beyond the top 100,
`metrics.json` lists every size's coverage of the top 25 to 400.
Spoken-weighted cost per word, by method:
<!-- table:motor-costs -->
| Locations | Hits per word | Row-column scan steps | Touch (Fitts ID, bits) | Gaze (eccentricity) |
|---|---|---|---|---|
| 30 | 1.837 | 11.636 | 3.78 | 0.605 |
| 60 | 1.397 | 12.961 | 2.936 | 0.566 |
| 84 | 1.259 | 13.826 | 2.862 | 0.548 |
<!-- /table -->
Target sizes (mm, width × height), against the app's minimums (touch 10, switch
15, head 18, gaze 20):
<!-- table:motor-targets -->
| Locations | Grid | 10.2" tablet, landscape (mm) | tablet, portrait | 6.1" phone, portrait | phone, landscape | Meets on the tablet (landscape) | Meets on the phone (portrait) |
|---|---|---|---|---|---|---|---|
| 30 | 5x6 | 34×24 | 25×34 | 10×19 | 20×6 | touch, switch, head, gaze | none |
| 60 | 6x10 | 20×20 | 15×28 | 6×16 | 12×5 | touch, switch, head | none |
| 84 | 7x12 | 16×17 | 12×24 | 5×13 | 10×4 | touch, switch | none |
<!-- /table -->
30 locations meets the app's 20 mm gaze minimum on a 10.2-inch tablet in
landscape; 60 and 84 do not. No size meets touch's 10 mm on a 6.1-inch phone
held upright (30 locations misses by a fraction of a millimetre): Fixed Paths
is a tablet set.
## 6. Decisions (2026-10-05)
Taken by the coordinator for the founder, and reversible:
1. **Home at 30 is for beginners** (§2), with the frequency × 4 weighting kept
for 60 and 84.
2. **One layout for every access method**, with the adaptive scan order for
scanners (§2).
3. **"Show everything for now" is Track B's "Show hidden words for now"** (§3).
4. **"Back", the word, has its place** (Little words → Position at 30, Little
words at 60 and 84, by its weight): the Back control is drawn as its arrow,
so the two never read alike. Its glosses are the body part, so it is English only and
hidden in place in other languages (DESIGN-core.md §2).
Still open: irregular forms sit on the Word forms page as words until the
UniMorph plan (DESIGN-core.md §3) gives a Word Forms page that re-inflects;
until then "went" is two hits and "goed" is what the ending says.