6 * NASA-TLX is a subjective workload assessment tool.
8 * NASA-TLX allows users to perform subjective workload assessments on
9 * operator(s) working with various human-machine systems. NASA-TLX is a
10 * multi-dimensional rating procedure that derives an overall workload score
11 * based on a weighted average of ratings on six subscales.
13 * These subscales include Mental Demands, Physical Demands, Temporal Demands,
14 * Own Performance, Effort and Frustration. It can be used to assess workload
15 * in various human-machine environments such as aircraft cockpits, command,
16 * control, and communication (C3) workstations; supervisory and process
17 * control environments; simulations and laboratory tests.
19 * http://humansystems.arc.nasa.gov/groups/TLX/downloads/NASA-TLXChapter.pdf
21 * Hart, S.G. & Staveland, L.E. (1988). Development of NASA-TLX
22 * (Task Load Index): Results of empirical and theoretical research. In
23 * P.A. Hancock & N. Meshkati (Eds.), Human Mental Workload (pp. 239-250).
24 * Amsterdam: North Holland Press.
27 * @author Ryan M. Hope <rmh3093@gmail.com>
31 package ryanhope
.us
.nasatlx
;
33 import java
.awt
.Dimension
;
34 import java
.awt
.FlowLayout
;
35 import java
.awt
.GridLayout
;
36 import java
.awt
.event
.ActionEvent
;
37 import java
.awt
.event
.ActionListener
;
38 import java
.util
.Collections
;
39 import java
.util
.TreeMap
;
40 import java
.util
.TreeSet
;
41 import java
.util
.Vector
;
43 import javax
.swing
.JButton
;
44 import javax
.swing
.JFrame
;
45 import javax
.swing
.JPanel
;
47 import ryanhope
.us
.util
.CombinationGenerator
;
49 import jargs
.gnu
.CmdLineParser
;
51 public class NASA_TLX
{
53 static String
[] default_subscales
= {
63 boolean verbose
= false;
65 Integer
[][] subscale_pairs
;
66 TreeMap
<String
, Integer
> biasTally
;
67 TreeMap
<String
, Integer
>[] taskRatings
;
69 public void printBiasTally() {
70 for (String s
: subscales
)
71 System
.out
.println(s
+ " = " + biasTally
.get(s
));
74 private Integer
[][] generateComparisons(String
[] elements
) {
76 Vector
<Integer
[]> pairs
= new Vector
<Integer
[]>();
77 CombinationGenerator cg
=
78 new CombinationGenerator(elements
.length
, 2);
79 while (cg
.hasMore()) {
80 indices
= cg
.getNext();
81 Integer
[] pair
= {indices
[0],indices
[1]};
84 Integer
[][] subscale_pairs
= new Integer
[pairs
.size()][];
85 for (int i
=0; i
<pairs
.size(); i
++) {
86 Integer
[] p
= pairs
.get(i
);
87 subscale_pairs
[i
] = p
;
89 return subscale_pairs
;
92 @SuppressWarnings("serial")
93 public class PairWiseComparison
94 extends JFrame
implements ActionListener
{
99 private class PWCPanel
extends JPanel
{
103 public PWCPanel(String subscale1
, String subscale2
, ActionListener al
) {
104 setLayout(new GridLayout(2,1,15,15));
105 b1
= new JButton(subscale1
);
106 b1
.setActionCommand(subscale1
);
107 b1
.addActionListener(al
);
108 b1
.setPreferredSize(new Dimension(150,40));
109 b1
.setFocusable(false);
110 b2
= new JButton(subscale2
);
111 b2
.setActionCommand(subscale2
);
112 b2
.addActionListener(al
);
113 b2
.setPreferredSize(new Dimension(200,40));
114 b2
.setFocusable(false);
123 * Participant selects the member of each pair that provides the most
124 * significant source of workload variation in the tasks
126 * @param verbose If true the results will be printed to stdout.
128 public PairWiseComparison () {
129 subscale_pairs
= generateComparisons(subscales
);
130 biasTally
= new TreeMap
<String
, Integer
>();
131 for (String s
: subscales
) biasTally
.put(s
, 0);
132 setTitle("Pair-wise Comparison");
133 setLocationRelativeTo(null);
135 setPreferredSize(new Dimension(250,90));
136 setLayout(new FlowLayout(FlowLayout
.CENTER
,10,10));
137 panels
= new PWCPanel
[subscale_pairs
.length
];
138 for (int i
=0; i
<subscale_pairs
.length
; i
++) {
139 panels
[i
] = new PWCPanel(subscales
[subscale_pairs
[i
][0]],
140 subscales
[subscale_pairs
[i
][1]],this);
143 panels
[pair
].setVisible(true);
149 public void actionPerformed(ActionEvent e
) {
150 int oldval
= biasTally
.get(e
.getActionCommand());
151 biasTally
.put(e
.getActionCommand(), oldval
+1);
152 panels
[pair
].setVisible(false);
154 if (pair
<subscale_pairs
.length
)
155 panels
[pair
].setVisible(true);
157 if (verbose
) printBiasTally();
163 private void printUsage() {
164 System
.err
.println("Usage: NASA_TLX [OPTIONS]\n");
165 System
.err
.println("Option\t\tGNU long option\t\tMeaning");
166 System
.err
.println("-v\t\t--verbose\t\tEnable verbose output");
167 System
.err
.println("-t\t\t--tasks number\t\tThe number of subtasks");
168 System
.err
.println("-d\t\t--disable subscale\tDisable a subscale");
169 System
.err
.println("\nAvailable subscales:");
170 for (int i
=0; i
<default_subscales
.length
; i
++)
171 System
.err
.println(" " + (i
+1) + ". " + default_subscales
[i
]);
174 public NASA_TLX(String
[] args
) {
176 CmdLineParser parser
= new CmdLineParser();
177 CmdLineParser
.Option tasks
= parser
.addIntegerOption('t', "tasks");
178 CmdLineParser
.Option disable
= parser
.addIntegerOption('d', "disable");
179 CmdLineParser
.Option verbose
= parser
.addBooleanOption('v', "verbose");
180 CmdLineParser
.Option help
= parser
.addBooleanOption('h', "help");
185 catch ( CmdLineParser
.OptionException e
) {
186 System
.err
.println(e
.getMessage());
191 if ((Boolean
)parser
.getOptionValue(help
, false)) {
195 this.tasks
= (Integer
)parser
.getOptionValue(tasks
, 1);
196 this.verbose
= (Boolean
)parser
.getOptionValue(verbose
, false);
197 Vector
<Integer
> disabled_subscales
= parser
.getOptionValues(disable
);
198 if (disabled_subscales
.isEmpty())
199 subscales
= default_subscales
;
202 new String
[default_subscales
.length
-disabled_subscales
.size()];
205 for (int i
=0; i
<default_subscales
.length
; i
++) {
208 while (!found
&& idx
<disabled_subscales
.size()) {
209 if ((disabled_subscales
.get(idx
)-1)==i
) found
= true;
213 subscales
[index
] = default_subscales
[i
];
218 subscale_pairs
= generateComparisons(subscales
);
219 new PairWiseComparison();
225 public static void main(String
[] args
) {