Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
963211c
save data for partial rocket launch games
K-Meech May 12, 2026
19d3738
add game number, session number and headMovementPlane
K-Meech May 13, 2026
852d310
remove additional adaptiveDifficulty multiplication
K-Meech May 13, 2026
5b21025
add draft of rocket launch save data docs
K-Meech May 13, 2026
0a5da0e
add gaze tolerance and minimum head speed
K-Meech May 13, 2026
b5ed5f7
record overall game duration
K-Meech May 13, 2026
c6e2fc8
add explanation of game duration seconds
K-Meech May 13, 2026
02e512e
use TotalSeconds to capture full duration
K-Meech May 13, 2026
58ee079
reduce gaze tolerance so it doesn't cover full field
K-Meech May 13, 2026
21762ba
merge upstream changes
K-Meech May 14, 2026
ad2ebf4
use world coordinates for mouse point
K-Meech May 14, 2026
7116656
merge upstream changes
K-Meech May 15, 2026
3e2861f
track when the player goes out of range
K-Meech May 15, 2026
a1715ae
add sampled head speed measurements
K-Meech May 15, 2026
01b9331
Merge branch 'main' of github.com:UCL/AstroBalance into km/rocket-lau…
K-Meech May 18, 2026
9cac367
add percent time above 40 degrees per sec
K-Meech May 18, 2026
e42f83d
add time in adaptation windows
K-Meech May 18, 2026
eac0551
add percent time gaze on target
K-Meech May 18, 2026
57c3a16
expand rocket launch save data docs
K-Meech May 18, 2026
865f177
expand docs and docstrings
K-Meech May 18, 2026
6d6cfe7
only record head speeds when gaze is on target
K-Meech May 19, 2026
33294a5
add option to save sampled speeds to a text file
K-Meech May 19, 2026
c90dc0d
explain new min n items variables in docs
K-Meech May 19, 2026
3163e72
add docstring for gaze steady
K-Meech May 19, 2026
640d4b4
clarify when gameDurationSeconds is more or less than launchTimeSeconds
K-Meech May 20, 2026
ce37b19
rename player out of range function
K-Meech May 20, 2026
d37f152
don't mark player as out of range when using the mouse
K-Meech May 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion docs/rocket-launch.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,28 @@ then a timer decrements until launch time is achieved.
- **Head Movement Variables**: Determine the amount of head movement required to decrement the timer.
- Head Pose Buffer Capacity (n) and speed time (s): head speed is measured as the average change in pitch or yaw over the time period speed time. The buffer will need to be sufficiently large to support the time based on game frame rate.
- Minimum head speed (pitch or yaw) required to reduce the launch timer. The yaw speed is set higher than pitch, because it is possible (for me at least) to shake my head quicker than I can nod.
- Minimum n items: the minimum number of head pose readings used to calculate a head speed

- **Steady Gaze Variables**: Determine how steady the gave must be to decrement the timer.
- Timer Duration: How long (in seconds) the player must maintain a steady gaze to increment the count down code display.
- Gaze Pose Buffer Capacity (n) and gaze time (s), gaze steadiness is measured as the standard deviation of gaze over gaze time seconds. The buffer will need to be sufficiently large to support the time based on game frame rate.
- Gaze Tolerance - the allowable gaze standard deviation to be steady. Smaller number will require steadier gaze. This may be reduced by the adaptive difficulty settings below.
- Minimum n items: the minimum number of gaze points used to calculate steadiness.
- Target Object - if this is set you are required to look at that object, if not gaze can be anywhere on screen but must be steady. The size of the target object will be matched to the gaze tolerance.

- **Adaptive difficulty variables**
- Max previous games: The maximum number of previous games to retrieve to determine experience based difficulty
- Adaptive difficulty: integer describing level of adaptive difficulty - higher numbers are more difficult.

- **Save data variables**
- Sampling interval: the interval in seconds between samples for the save data.
- Write sampled speed: whether to write sampled speeds for this game to a text file (rocket-speeds.txt)

- **User Interface Items**:
- Count down sprites: A list of sprites to use for the count down code display.
- Instructions Text: A text box to place the instruction text.
- Win Screen: Screen to show a successful launch.

- **Launch Speed Variables**: Control rocket behaviour at launch.
- acceleration: The acceleration of the rocket when it launches.

Expand All @@ -40,7 +48,6 @@ then a timer decrements until launch time is achieved.
- **SmokeController**: Attached to ground left/right emitter.
- Smoke Emission Scale: A larger value will increase the amount of smoke emitted for a given head speed.


## Adaptive difficulty

Difficulty is increased between games by reducing the gaze tolerance, and increasing the overall launch time (explained below). Note: all parameters mentioned below can be adjusted on `LaunchControl`.
Expand All @@ -52,3 +59,44 @@ At the start of each game, a scaling factor is calculated as:
`nGames` is the total number of rocket launch games completed by the player so far (up to a maximum of `maxPreviousGames`). The scaling factor is then applied:
- the gaze tolerance (i.e. the tolerance in unity coordinates that gaze needs to stay within) is divided by the scaling factor. This will also scale the gaze target (the box displaying the launch code numbers) to match. This means the player must keep their gaze closer to the target after more games have been played.
- the launch time is multiplied by the scaling factor. This means the player must move their head while looking at the target for longer to launch the rocket.

## Save data

Data is saved to `RocketLaunchScores.csv`, with one row per played game. Values are:

- `gameNumber`: a unique id per played rocket launch game
- `sessionNumber`: the session this game was played in (corresponds to sessionNumber in [`SessionSummary.csv`](./session-summary.md))
- `date`: the date of the game session in format YYYY-MM-DD
- `startTime`: the game start time in format HH:MM:ss. This is the local time (e.g. if your computer is set to UK time - this is UK time).
- `endTime`: the game end time in format HH:MM:ss (local time - see startTime description)
- `gameCompleted`: whether this game was completed. If they exited early, this will be false.
- `headMovementPlane`: the direction of head movement - either 'pitch' (up-down movement) or 'yaw' (left-right movement).
- `launchTimeSeconds`: the number of seconds the player had to keep their eyes steady on the target while moving their head at the required speed to launch the rocket. Rounded to 2 decimal places.
- `gameDurationSeconds`: how long the game was played (rounded to the nearest second). If the player exited before the game finished, this may be less than launchTimeSeconds; if they played the game through to completion it may be longer than launchTimeSeconds (as this includes time when the player wasn't looking at the target / wasn't moving their head fast enough etc.)
- `minimumHeadSpeed`: the minimum head speed required (while looking at the target) to reduce the launch timer.
- `gazeTolerance`: the maximum number of unity units the gaze can be from the centre of the target, and still be counted as 'on target'. Rounded to 2 decimal places.

**Note**: all measures below are calculated as follows. Every `samplingIntervalSeconds` (a configurable parameter in `LaunchControl`), a gaze steady sample is taken:

- Gaze steady: a boolean value (either true or false). It will be true if gaze positions in the time period are (on average) less than `gazeTolerance` from the centre of the target.

If `gaze steady = true`, a head speed sample is also taken:

- Head speed: the absolute differences of head angle between consecutive readings in the time period are summed together and divided by the total difference in time to give a speed in degrees per second.

If the player goes out of range at any point in those `samplingIntervalSeconds` (i.e. the tracker can no longer detect them), then all samples for that time period are discarded.

At the end of the game, all samples are used to calculate the summary statistics below:

- `headSpeedDegPerSecMean`: Mean head rotation speed while the gaze is on target, measured in degrees per second. Rounded to 2 decimal places.
- `headSpeedDegPerSecPeak`: Peak head head rotation speed while the gaze is on target, measured in degrees per second. Rounded to 2 decimal places.
- `headSpeedDegPerSecMedian`: Median head rotation speed while the gaze is on target, measured in degrees per second. Rounded to 2 decimal places.
- `headSpeedDegPerSecSD`: Standard deviation of head rotation speed while the gaze is on target, measured in degrees per second. Rounded to 2 decimal places.
- `percentTimeAbove40DegPerSec` - the % of on-target time, that the head speed was over 40 degrees per second. (this is the % of speed samples that were >40 - speed samples are _only_ taken when the gaze is on target). Rounded to 2 decimal places.
- `percentTimeGazeOnTarget` - the % of time with gaze on target (this is the % of samples with `gaze steady = true` as described above). Rounded to 2 decimal places.

For the adaptation window values below, this is calculated as the number of speed samples in the given range multiplied by the sampling interval in seconds:
- `timeInAdaptationWindow1` - number of seconds with `60 <= head speed < 90` degrees per second and gaze on target. Rounded to 2 decimal places.
- `timeInAdaptationWindow2` - number of seconds with `90 <= head speed < 130` degrees per second and gaze on target. Rounded to 2 decimal places.
- `timeInAdaptationWindow3` - number of seconds with `130 <= head speed < 180` degrees per second and gaze on target. Rounded to 2 decimal places.
- `timeInAdaptationWindow4` - number of seconds with `head speed > 180` degrees per second and gaze on target. Rounded to 2 decimal places.
4 changes: 4 additions & 0 deletions projects/AstroBalance/Assets/Scenes/RocketLaunch.unity
Original file line number Diff line number Diff line change
Expand Up @@ -21570,6 +21570,10 @@ PrefabInstance:
propertyPath: useMouseForTracker
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8902890511493098178, guid: 00c1b36d25d21214eb8e6df02c079dea, type: 3}
propertyPath: writeSampledSpeeds
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8902890511493098178, guid: 00c1b36d25d21214eb8e6df02c079dea, type: 3}
propertyPath: headPoseBufferCapacity
value: 100
Expand Down
17 changes: 17 additions & 0 deletions projects/AstroBalance/Assets/Scripts/MathsUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,21 @@ public static float StandardDeviation(List<float> numbers)
float average = numbers.Average();
return Mathf.Sqrt(numbers.Average(v => Mathf.Pow(v - average, 2)));
}

public static float Median(List<float> numbers)
{
List<float> sortedList = new List<float>(numbers);
sortedList.Sort();

int size = sortedList.Count();
int midPoint = size / 2;

// Take middle value, or average of the two middle values if there's an even number of items
float median =
(size % 2 != 0)
? sortedList[midPoint]
: (sortedList[midPoint] + sortedList[midPoint - 1]) / 2;

return median;
}
}
Loading