~vcs-imports/openintents/trunk

« back to all changes in this revision

Viewing changes to sensorsimulator/SensorSimulatorSWT/src/org/openintents/tools/sensorsimulator/swt/MobileComposite.java

  • Committer: peli0101
  • Date: 2011-01-04 16:15:57 UTC
  • Revision ID: peli0101-20110104161557-gna7g36lbfdklfp0
SensorSimulator: Split SensorSimulator into a Swing part and a SWT part.
The SWT part requires the Swing part as an Eclipse project to be open.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 *
 
3
 */
 
4
package org.openintents.tools.sensorsimulator.swt;
 
5
 
 
6
import java.io.BufferedReader;
 
7
import java.io.FileReader;
 
8
import java.io.IOException;
 
9
import java.util.Random;
 
10
 
 
11
import org.eclipse.swt.SWT;
 
12
import org.eclipse.swt.events.MouseAdapter;
 
13
import org.eclipse.swt.events.MouseEvent;
 
14
import org.eclipse.swt.events.MouseMoveListener;
 
15
import org.eclipse.swt.events.PaintEvent;
 
16
import org.eclipse.swt.events.PaintListener;
 
17
import org.eclipse.swt.graphics.GC;
 
18
import org.eclipse.swt.widgets.Composite;
 
19
import org.openintents.tools.sensorsimulator.IMobilePanel;
 
20
import org.openintents.tools.sensorsimulator.ISensorSimulator;
 
21
import org.openintents.tools.sensorsimulator.Vector;
 
22
 
 
23
/**
 
24
 * Displays a mobile phone in a panel and calculates sensor physics.
 
25
 * 
 
26
 * @author Peli
 
27
 * @author Josip Balic
 
28
 * @author Lee Sanghoon
 
29
 *
 
30
 */
 
31
public class MobileComposite extends Composite implements IMobilePanel, PaintListener {
 
32
 
 
33
        /**
 
34
         * Reference to SensorSimulator for accessing widgets.
 
35
         */
 
36
        private ISensorSimulator mSensorSimulator;
 
37
 
 
38
        /**
 
39
         * Current read-out value of accelerometer x-component.
 
40
         *
 
41
         * This value is updated only at the desired
 
42
         * updateSensorRate().
 
43
         */
 
44
        private double read_accelx;
 
45
        /** Current read-out value of accelerometer y-component. */
 
46
        private double read_accely;
 
47
        /** Current read-out value of accelerometer z-component. */
 
48
        private double read_accelz;
 
49
 
 
50
        /** Current read-out value of compass x-component. */
 
51
        private double read_compassx;
 
52
        /** Current read-out value of compass y-component. */
 
53
        private double read_compassy;
 
54
        /** Current read-out value of compass z-component. */
 
55
        private double read_compassz;
 
56
 
 
57
        /** Current read-out value of orientation yaw. */
 
58
        private double read_yaw;
 
59
        /** Current read-out value of orientation pitch. */
 
60
        private double read_pitch;
 
61
        /** Current read-out value of orientation roll. */
 
62
        private double read_roll;
 
63
 
 
64
        /** Current read-out value of temperature. */
 
65
        private double read_temperature;
 
66
 
 
67
        /**Current read-out value of barcode. */
 
68
        private String barcode_reader;
 
69
 
 
70
        /** Duration (in milliseconds) between two updates.
 
71
         * This is the inverse of the update rate.
 
72
         */
 
73
        private long accel_update_duration;
 
74
 
 
75
        /** Time of next update required.
 
76
         * The time is compared to System.currentTimeMillis().
 
77
         */
 
78
        private long accel_next_update;
 
79
 
 
80
        /** Duration (in milliseconds) between two updates.
 
81
         * This is the inverse of the update rate.
 
82
         */
 
83
        private long compass_update_duration;
 
84
 
 
85
        /** Time of next update required.
 
86
         * The time is compared to System.currentTimeMillis().
 
87
         */
 
88
        private long compass_next_update;
 
89
 
 
90
        /** Duration (in milliseconds) between two updates.
 
91
         * This is the inverse of the update rate.
 
92
         */
 
93
        private long orientation_update_duration;
 
94
 
 
95
        /** Time of next update required.
 
96
         * The time is compared to System.currentTimeMillis().
 
97
         */
 
98
        private long orientation_next_update;
 
99
 
 
100
        /** Duration (in milliseconds) between two updates.
 
101
         * This is the inverse of the update rate.
 
102
         */
 
103
        private long temperature_update_duration;
 
104
 
 
105
        /** Time of next update required.
 
106
         * The time is compared to System.currentTimeMillis().
 
107
         */
 
108
        private long temperature_next_update;
 
109
 
 
110
        /** Duration in milliseconds until user setting
 
111
         * changes are read out.
 
112
         */
 
113
        private long user_settings_duration;
 
114
 
 
115
        /** Time of next update for reading user settings from widgets.
 
116
         * The time is compared to System.currentTimeMillis().
 
117
         */
 
118
        private long user_settings_next_update;
 
119
 
 
120
        /**
 
121
         * Partial read-out value of accelerometer x-component.
 
122
         *
 
123
         * This partial value is used to calculate the
 
124
         * sensor average.
 
125
         */
 
126
        private double partial_accelx;
 
127
        /** Partial read-out value of accelerometer y-component. */
 
128
        private double partial_accely;
 
129
        /** Partial read-out value of accelerometer z-component. */
 
130
        private double partial_accelz;
 
131
        /** Number of summands in partial sum for accelerometer. */
 
132
        private int partial_accel_n;
 
133
        /** Whether to form the average over the last duration when reading out sensors.
 
134
         * Alternative is to just take the current value.
 
135
         */
 
136
        private boolean average_accel;
 
137
 
 
138
        /** Partial read-out value of compass x-component. */
 
139
        private double partial_compassx;
 
140
        /** Partial read-out value of compass y-component. */
 
141
        private double partial_compassy;
 
142
        /** Partial read-out value of compass z-component. */
 
143
        private double partial_compassz;
 
144
        /** Number of summands in partial sum for compass. */
 
145
        private int partial_compass_n;
 
146
        /** Whether to form the average over the last duration when reading out sensors.
 
147
         * Alternative is to just take the current value.
 
148
         */
 
149
        private boolean average_compass;
 
150
 
 
151
        /** Partial read-out value of orientation yaw. */
 
152
        private double partial_yaw;
 
153
        /** Partial read-out value of orientation pitch. */
 
154
        private double partial_pitch;
 
155
        /** Partial read-out value of orientation roll. */
 
156
        private double partial_roll;
 
157
        /** Number of summands in partial sum for orientation. */
 
158
        private int partial_orientation_n;
 
159
        /** Whether to form the average over the last duration when reading out sensors.
 
160
         * Alternative is to just take the current value.
 
161
         */
 
162
        private boolean average_orientation;
 
163
 
 
164
        /** Partial read-out value of temperature. */
 
165
        private double partial_temperature;
 
166
        /** Number of summands in partial sum for temperature. */
 
167
        private int partial_temperature_n;
 
168
        /** Whether to form the average over the last duration when reading out sensors.
 
169
         * Alternative is to just take the current value.
 
170
         */
 
171
        private boolean average_temperature;
 
172
 
 
173
 
 
174
        /** Internal state value of accelerometer x-component.
 
175
         *
 
176
         * This value is updated regularly by updateSensorPhysics().
 
177
         */
 
178
        private double accelx;
 
179
        /** Internal state value of accelerometer x-component. */
 
180
        private double accely;
 
181
        /** Internal state value of accelerometer x-component. */
 
182
        private double accelz;
 
183
 
 
184
        /** Internal state value of compass x-component. */
 
185
        private double compassx;
 
186
        /** Internal state value of compass y-component. */
 
187
        private double compassy;
 
188
        /** Internal state value of compass z-component. */
 
189
        private double compassz;
 
190
 
 
191
        // orientation (in degree)
 
192
        private double yaw;
 
193
        private double pitch;
 
194
        private double roll;
 
195
 
 
196
        // thermometer
 
197
        private double temperature;
 
198
 
 
199
        //barcode
 
200
        private String barcode;
 
201
 
 
202
        // orientation sensor raw data (in degree)
 
203
        private double yawDegree;
 
204
        private double pitchDegree;
 
205
        private double rollDegree;
 
206
 
 
207
        /** Current position on screen. */
 
208
        private int movex;
 
209
        /** Current position on screen. */
 
210
        private int movez;
 
211
 
 
212
        private int oldx;
 
213
        private int oldz;
 
214
        private double vx; // velocity
 
215
        private double vz;
 
216
        private double oldvx;
 
217
        private double oldvz;
 
218
        private double ax; // acceleration
 
219
        private double az;
 
220
 
 
221
        private double Fx; // force
 
222
        private double Fz; // force
 
223
        private double accx; // accelerometer position x on screen
 
224
        private double accz; // (DONT confuse with acceleration a!)
 
225
 
 
226
        /** Spring constant. */
 
227
        private double k; // spring constant
 
228
 
 
229
        /** Mass of accelerometer test particle.
 
230
         *
 
231
         *  This is set to 1, as only the ratio
 
232
         *  k/m enters the simulation. */
 
233
        private double m; // mass of accelerometer test particle
 
234
 
 
235
        /** Damping constant. */
 
236
        private double gamma; // damping of spring
 
237
 
 
238
        private double dt; // time step size
 
239
 
 
240
        /** Inverse of screen pixel per meter */
 
241
        private double meterperpixel;
 
242
 
 
243
        /** Gravity constant.
 
244
         *
 
245
         * This takes the value 9.8 m/s^2.
 
246
         * */
 
247
        private double g;
 
248
 
 
249
        /** 1/g (g-inverse) */
 
250
        private double ginverse;
 
251
 
 
252
        private int mousedownx;
 
253
        private int mousedowny;
 
254
        private int mousedownyaw;
 
255
        private int mousedownpitch;
 
256
        private int mousedownroll;
 
257
        private int mousedownmovex;
 
258
        private int mousedownmovez;
 
259
 
 
260
        private Random r;
 
261
 
 
262
 
 
263
        /*
 
264
         * http://code.google.com/android/reference/android/hardware/Sensors.html
 
265
         *
 
266
         * With the device lying flat on a horizontal surface in front of the user,
 
267
         * oriented so the screen is readable by the user in the normal fashion,
 
268
         * the X axis goes from left to right, the Y axis goes from the user
 
269
         * toward the device, and the Z axis goes upwards perpendicular to the
 
270
         * surface.
 
271
         */
 
272
        // Mobile size
 
273
        private final double sx = 15; // size x
 
274
        private final double sy = 40; // size y
 
275
        private final double sz = 5; // size z
 
276
 
 
277
        // Display size
 
278
        private final double dx = 12; // size x
 
279
        private final double dy1 = 33; // size y
 
280
        private final double dy2 = -15;
 
281
 
 
282
        /** Contains the grid model of the phone. */
 
283
        private double[][] phone = {
 
284
                        // bottom shape
 
285
                        { sx, sy, -sz}, {-sx, sy, -sz},
 
286
                        {-sx, sy, -sz}, {-sx,-sy, -sz},
 
287
                        {-sx,-sy, -sz}, { sx,-sy, -sz},
 
288
                        { sx,-sy, -sz}, { sx, sy, -sz},
 
289
                        // top shape
 
290
                        { sx, sy, sz}, {-sx, sy, sz},
 
291
                        {-sx, sy, sz}, {-sx,-sy, sz},
 
292
                        {-sx,-sy, sz}, { sx,-sy, sz},
 
293
                        { sx,-sy, sz}, { sx, sy, sz},
 
294
                        // connectint top and bottom
 
295
                        { sx, sy, -sz}, { sx, sy, sz},
 
296
                        {-sx, sy, -sz}, {-sx, sy, sz},
 
297
                        {-sx,-sy, -sz}, {-sx,-sy, sz},
 
298
                        { sx,-sy, -sz}, { sx,-sy, sz},
 
299
                        // display
 
300
                        { dx, dy1, sz}, {-dx, dy1, sz},
 
301
                        {-dx, dy1, sz}, {-dx, dy2, sz},
 
302
                        {-dx, dy2, sz}, { dx, dy2, sz},
 
303
                        { dx, dy2, sz}, { dx, dy1, sz},
 
304
                };
 
305
 
 
306
        private boolean mouseDragging = false;
 
307
 
 
308
        /**
 
309
         * @param parent
 
310
         * @param style
 
311
         */
 
312
        public MobileComposite(Composite parent, ISensorSimulator newSensorSimulator) {
 
313
                super(parent, SWT.BORDER);
 
314
                setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
 
315
 
 
316
                mSensorSimulator = newSensorSimulator;
 
317
 
 
318
                yawDegree = 0;
 
319
                pitchDegree = 0;
 
320
                rollDegree = 0;
 
321
 
 
322
                movex = 0;
 
323
                movez = 0;
 
324
                oldx = 0;
 
325
                oldz = 0;
 
326
                oldvx = 0;
 
327
                oldvz = 0;
 
328
 
 
329
                Fx = 0;
 
330
                Fz = 0;
 
331
                accx = 0;
 
332
                accz = 0;
 
333
                k = 500; // spring constant
 
334
                m = 1; // mass
 
335
                gamma = 50; // damping
 
336
 
 
337
                dt = 0.1;
 
338
                meterperpixel = 1/3000.; // meter per pixel
 
339
                g = 9.80665; // meter per second^2
 
340
                ginverse = 1 / g;
 
341
 
 
342
                user_settings_duration = 500;  // Update every half second. This should be enough.
 
343
                user_settings_next_update = System.currentTimeMillis(); // First update is now.
 
344
 
 
345
 
 
346
                r = new Random();
 
347
 
 
348
 
 
349
                // Add all listeners
 
350
                addMouseListener(new MouseAdapter() {
 
351
                        public void mouseDown(MouseEvent e) {
 
352
                        mousedownx = e.x;
 
353
                        mousedowny = e.y;
 
354
                        mousedownyaw = mSensorSimulator.getYaw();
 
355
                        mousedownpitch = mSensorSimulator.getPitch();
 
356
                        mousedownroll = mSensorSimulator.getRoll();
 
357
                        mousedownmovex = movex;
 
358
                        mousedownmovez = movez;
 
359
 
 
360
                        mouseDragging = true;
 
361
                        }
 
362
 
 
363
                        /* (non-Javadoc)
 
364
                         * @see org.eclipse.swt.events.MouseAdapter#mouseUp(org.eclipse.swt.events.MouseEvent)
 
365
                         */
 
366
                        @Override
 
367
                        public void mouseUp(MouseEvent e) {
 
368
                                mouseDragging = false;
 
369
                        }
 
370
                });
 
371
 
 
372
                addMouseMoveListener(new MouseMoveListener() {
 
373
                        public void mouseMove(MouseEvent e) {
 
374
                                if (!mouseDragging) {
 
375
                                        return;
 
376
                                }
 
377
 
 
378
                        if (mSensorSimulator.getMouseMode()
 
379
                                        == ISensorSimulator.mouseYawPitch) {
 
380
                                // Control yawDegree
 
381
                                int newyaw = mousedownyaw - (e.x - mousedownx);
 
382
                                while (newyaw > 180) newyaw -= 360;
 
383
                                while (newyaw < -180) newyaw += 360;
 
384
                                mSensorSimulator.setYaw(newyaw);
 
385
                                yawDegree = newyaw;
 
386
 
 
387
                                // Control pitch
 
388
                                int newpitch = mousedownpitch - (e.y - mousedowny);
 
389
                                while (newpitch > 180) newpitch -= 360;
 
390
                                while (newpitch < -180) newpitch += 360;
 
391
                                mSensorSimulator.setPitch(newpitch);
 
392
                                pitchDegree = newpitch;
 
393
                        } else if (mSensorSimulator.getMouseMode()
 
394
                                        == ISensorSimulator.mouseRollPitch) {
 
395
                                // Control roll
 
396
                                int newroll = mousedownroll + (e.x - mousedownx);
 
397
                                while (newroll > 180) newroll -= 360;
 
398
                                while (newroll < -180) newroll += 360;
 
399
                                mSensorSimulator.setRoll(newroll);
 
400
                                rollDegree = newroll;
 
401
 
 
402
                                // Control pitch
 
403
                                int newpitch = mousedownpitch - (e.y - mousedowny);
 
404
                                while (newpitch > 180) newpitch -= 360;
 
405
                                while (newpitch < -180) newpitch += 360;
 
406
                                mSensorSimulator.setPitch(newpitch);
 
407
                                pitchDegree = newpitch;
 
408
                        } else if (mSensorSimulator.getMouseMode()
 
409
                                        == ISensorSimulator.mouseMove) {
 
410
                                // Control roll
 
411
                                int newmovex = mousedownmovex + (e.x - mousedownx);
 
412
                                movex = newmovex;
 
413
 
 
414
                                // Control pitch
 
415
                                int newmovez = mousedownmovez - (e.y - mousedowny);
 
416
                                movez = newmovez;
 
417
                        }
 
418
 
 
419
                        doRepaint();
 
420
                        }
 
421
                });
 
422
 
 
423
                addPaintListener(this);
 
424
        }
 
425
 
 
426
        /**
 
427
         * Updates physical model of all sensors by minimum time-step.
 
428
         *
 
429
         * This internal update provides the close-to-continuum
 
430
         * description of the sensors.
 
431
         * It does not yet provide the values that
 
432
         * are read out by the Sensors class (which are
 
433
         * obtained by further time-selection or averaging).
 
434
         */
 
435
        public void updateSensorPhysics() {
 
436
                Vector vec;
 
437
                double random;
 
438
 
 
439
                // Update the timer if necessary:
 
440
                double newdelay;
 
441
                newdelay = mSensorSimulator.getUpdateSensors();
 
442
                if (newdelay > 0) {
 
443
                        mSensorSimulator.setDelay((int) newdelay);
 
444
                }
 
445
 
 
446
                dt = 0.001 * mSensorSimulator.getDelay(); // from ms to s
 
447
                g = mSensorSimulator.getGravityConstant();
 
448
                if (g != 0) {
 
449
                        ginverse = 1 / g;
 
450
                }
 
451
                meterperpixel = 1 / mSensorSimulator.getPixelsPerMeter();
 
452
                k = mSensorSimulator.getSpringConstant();
 
453
                gamma = mSensorSimulator.getDampingConstant();
 
454
 
 
455
        /*
 
456
                // Calculate velocity induced by mouse:
 
457
                double f = meterperpixel / g;
 
458
                vx = f * ((double) (movex - oldx)) / dt;
 
459
                vz = f * ((double) (movez - oldz)) / dt;
 
460
 
 
461
                // Calculate acceleration induced by mouse:
 
462
                ax = (vx - oldvx) / dt;
 
463
                az = (vz - oldvz) / dt;
 
464
*/
 
465
                // New physical model of acceleration:
 
466
                // Have accelerometer be steered by string.
 
467
                // We will treat this 2D only, as the rest is a linear
 
468
                // transformation, and we assume all three accelerometer
 
469
                // directions behave the same.
 
470
 
 
471
                // F = m * a
 
472
                // F = - k * x
 
473
 
 
474
                // First calculate the force acting on the
 
475
                // sensor test particle, assuming that
 
476
                // the accelerometer is mounted by a string:
 
477
                // F = - k * x
 
478
                Fx = + k * (movex - accx);
 
479
                Fz = + k * (movez - accz);
 
480
 
 
481
                // a = F / m
 
482
                ax = Fx / m;
 
483
                az = Fz / m;
 
484
 
 
485
                // Calculate velocity by integrating
 
486
                // the current acceleration.
 
487
                // Take into account damping
 
488
                // by damping constant gamma.
 
489
                // integrate dv/dt = a - v*gamma
 
490
                //vx += (ax - vx * gamma) * dt;
 
491
                //vz += (az - vz * gamma) * dt;
 
492
 
 
493
                vx += (ax) * dt;
 
494
                vz += (az) * dt;
 
495
 
 
496
                // Now this is the force that tries to adjust
 
497
                // the accelerometer back
 
498
                // integrate dx/dt = v;
 
499
                accx += vx * dt;
 
500
                accz += vz * dt;
 
501
 
 
502
                // We put damping here: We don't want to damp for
 
503
                // zero motion with respect to the background,
 
504
                // but with respect to the mobile phone:
 
505
                accx += gamma * (movex - accx) * dt;
 
506
                accz += gamma * (movez - accz) * dt;
 
507
 
 
508
                /*
 
509
                // Old values:
 
510
                oldx = movex;
 
511
                oldz = movez;
 
512
                oldvx = vx;
 
513
                oldvz = vz;
 
514
                */
 
515
 
 
516
                // Calculate acceleration by gravity:
 
517
                double gravityax;
 
518
                double gravityay;
 
519
                double gravityaz;
 
520
 
 
521
                gravityax = mSensorSimulator.getGravityX();
 
522
                gravityay = mSensorSimulator.getGravityY();
 
523
                gravityaz = mSensorSimulator.getGravityZ();
 
524
 
 
525
 
 
526
                ////
 
527
                // Now calculate this into mobile phone acceleration:
 
528
                // ! Mobile phone's acceleration is just opposite to
 
529
                // lab frame acceleration !
 
530
                vec = new Vector(-ax * meterperpixel + gravityax, gravityay, -az * meterperpixel + gravityaz);
 
531
 
 
532
                // we reverse roll, pitch, and yawDegree,
 
533
                // as this is how the mobile phone sees the coordinate system.
 
534
                vec.reverserollpitchyaw(rollDegree, pitchDegree, yawDegree);
 
535
 
 
536
                if (mSensorSimulator.isEnabledAccelerometer()) {
 
537
                        if (mSensorSimulator.useRealDeviceWiimtoe()) {
 
538
                                accelx = mSensorSimulator.getWiiMoteData().getX() * g;
 
539
                                accely = mSensorSimulator.getWiiMoteData().getY() * g;
 
540
                                accelz = mSensorSimulator.getWiiMoteData().getZ() * g;
 
541
                        }
 
542
                        else {
 
543
                                accelx = vec.x;
 
544
                                accely = vec.y;
 
545
                                accelz = vec.z;
 
546
 
 
547
                                if (mSensorSimulator.useRealDeviceThinkpad()) {
 
548
                                        // We will use data directly from sensor instead:
 
549
 
 
550
                                        // Read data from file
 
551
                                        String line = "";
 
552
                                        try {
 
553
                                          //FileReader always assumes default encoding is OK!
 
554
                                          BufferedReader input =  new BufferedReader(
 
555
                                                          new FileReader(mSensorSimulator.getRealDevicePath()));
 
556
                                          try {
 
557
                                                  line = input.readLine();
 
558
                                          } finally {
 
559
                                            input.close();
 
560
                                            //mSensorSimulator.mRealDeviceThinkpadOutputLabel.setBackground(Color.WHITE);
 
561
                                          }
 
562
                                        }
 
563
                                        catch (IOException ex){
 
564
                                          ex.printStackTrace();
 
565
                                          //mSensorSimulator.mRealDeviceThinkpadOutputLabel.setBackground(Color.RED);
 
566
                                          line = "Error reading file!";
 
567
                                        }
 
568
 
 
569
                                        // Show the line content:
 
570
                                        mSensorSimulator.setRealDeviceOutput(line);
 
571
 
 
572
                                        // Assign values
 
573
 
 
574
                                        // Create z-component (optional)
 
575
 
 
576
                                }
 
577
 
 
578
                                // Add random component:
 
579
                                random = mSensorSimulator.getRandomAccelerometer();
 
580
                                if (random > 0) {
 
581
                                        accelx += getRandom(random);
 
582
                                        accely += getRandom(random);
 
583
                                        accelz += getRandom(random);
 
584
                                }
 
585
 
 
586
                                // Add accelerometer limit:
 
587
                                double limit = g * mSensorSimulator.getAccelerometerLimit();
 
588
                                if (limit > 0) {
 
589
                                        // limit on each component separately, as each is
 
590
                                        // a separate sensor.
 
591
                                        if (accelx > limit) accelx = limit;
 
592
                                        if (accelx < -limit) accelx = -limit;
 
593
                                        if (accely > limit) accely = limit;
 
594
                                        if (accely < -limit) accely = -limit;
 
595
                                        if (accelz > limit) accelz = limit;
 
596
                                        if (accelz < -limit) accelz = -limit;
 
597
                                }
 
598
                        }
 
599
                } else {
 
600
                        accelx = 0;
 
601
                        accely = 0;
 
602
                        accelz = 0;
 
603
                }
 
604
 
 
605
                // Calculate magnetic field:
 
606
                // Calculate acceleration by gravity:
 
607
                double magneticnorth;
 
608
                double magneticeast;
 
609
                double magneticvertical;
 
610
 
 
611
                if (mSensorSimulator.isEnabledMagneticField()) {
 
612
                        magneticnorth = mSensorSimulator.getMagneticFieldNorth();
 
613
                        magneticeast = mSensorSimulator.getMagneticFieldEast();
 
614
                        magneticvertical = mSensorSimulator.getMagneticFieldVertical();
 
615
 
 
616
                        // Add random component:
 
617
                        random = mSensorSimulator.getRandomMagneticField();
 
618
                        if (random > 0) {
 
619
                                magneticnorth += getRandom(random);
 
620
                                magneticeast += getRandom(random);
 
621
                                magneticvertical += getRandom(random);
 
622
                        }
 
623
 
 
624
                        // Magnetic vector in phone coordinates:
 
625
                        vec = new Vector(magneticeast, magneticnorth, -magneticvertical);
 
626
                        vec.scale(0.001); // convert from nT (nano-Tesla) to �T (micro-Tesla)
 
627
 
 
628
                        // we reverse roll, pitch, and yawDegree,
 
629
                        // as this is how the mobile phone sees the coordinate system.
 
630
                        vec.reverserollpitchyaw(rollDegree, pitchDegree, yawDegree);
 
631
 
 
632
                        compassx = vec.x;
 
633
                        compassy = vec.y;
 
634
                        compassz = vec.z;
 
635
                } else {
 
636
                        compassx = 0;
 
637
                        compassy = 0;
 
638
                        compassz = 0;
 
639
                }
 
640
 
 
641
                // Orientation is currently not affected:
 
642
                if (mSensorSimulator.isEnabledOrientation()) {
 
643
                        //yaw = Math.toRadians(yawDegree);
 
644
                        //pitch = Math.toRadians(pitchDegree);
 
645
                        //roll = Math.toRadians(rollDegree);
 
646
                        // Since OpenGL uses degree as input,
 
647
                        // and it seems also more user-friendly,
 
648
                        // let us stick to degree.
 
649
                        // (it seems, professional sensors also use
 
650
                        //  degree output.)
 
651
                        yaw = yawDegree;
 
652
                        pitch = pitchDegree;
 
653
                        roll = rollDegree;
 
654
 
 
655
                        // Add random component:
 
656
                        random = mSensorSimulator.getRandomOrientation();
 
657
                        if (random > 0) {
 
658
                                yaw += getRandom(random);
 
659
                                pitch += getRandom(random);
 
660
                                roll += getRandom(random);
 
661
                        }
 
662
                } else {
 
663
                        yaw = 0;
 
664
                        pitch = 0;
 
665
                        roll = 0;
 
666
                }
 
667
 
 
668
                // Thermometer
 
669
                if (mSensorSimulator.isEnabledTemperature()) {
 
670
                        temperature = mSensorSimulator.getTemperature();
 
671
 
 
672
                        // Add random component:
 
673
                        random = mSensorSimulator.getRandomTemperature();
 
674
                        if (random > 0) {
 
675
                                temperature += getRandom(random);
 
676
                        }
 
677
                } else {
 
678
                        temperature = 0;
 
679
                }
 
680
 
 
681
                // Barcode
 
682
                if (mSensorSimulator.isEnabledBarcodeReader()) {
 
683
                        barcode = mSensorSimulator.getBarcode();
 
684
                }
 
685
 
 
686
                if (mSensorSimulator.isShowAcceleration()) {
 
687
                        // We only have to repaint if we show the acceleration,
 
688
                        // otherwise the phone does not change as long as there is
 
689
                        // no user interaction.
 
690
                        doRepaint();
 
691
                };
 
692
 
 
693
}
 
694
 
 
695
        /**
 
696
         * Updates sensor values in time intervals as specified by updateSensorRate().
 
697
         */
 
698
        public void updateSensorReadoutValues() {
 
699
                long currentTime = System.currentTimeMillis();
 
700
 
 
701
                // From time to time we
 
702
 
 
703
                if (average_accel) {
 
704
                        // Form the average
 
705
                        partial_accelx += accelx;
 
706
                        partial_accely += accely;
 
707
                        partial_accelz += accelz;
 
708
                        partial_accel_n++;
 
709
                }
 
710
 
 
711
                if (average_compass) {
 
712
                        // Form the average
 
713
                        partial_compassx += compassx;
 
714
                        partial_compassy += compassy;
 
715
                        partial_compassz += compassz;
 
716
                        partial_compass_n++;
 
717
                }
 
718
 
 
719
                if (average_orientation) {
 
720
                        // Form the average
 
721
                        partial_yaw += yaw;
 
722
                        partial_pitch += pitch;
 
723
                        partial_roll += roll;
 
724
                        partial_orientation_n++;
 
725
                }
 
726
 
 
727
                if (average_temperature) {
 
728
                        // Form the average
 
729
                        partial_temperature += temperature;
 
730
                        partial_temperature_n++;
 
731
                }
 
732
 
 
733
                if (currentTime >= accel_next_update) {
 
734
                        // Update
 
735
                        accel_next_update += accel_update_duration;
 
736
                        if (accel_next_update < currentTime) {
 
737
                                // Don't lag too much behind.
 
738
                                // If we are too slow, then we are too slow.
 
739
                                accel_next_update = currentTime;
 
740
                        }
 
741
 
 
742
                        if (average_accel) {
 
743
                                // form average
 
744
                                read_accelx = partial_accelx / partial_accel_n;
 
745
                                read_accely = partial_accely / partial_accel_n;
 
746
                                read_accelz = partial_accelz / partial_accel_n;
 
747
 
 
748
                                // reset average
 
749
                                partial_accelx = 0;
 
750
                                partial_accely = 0;
 
751
                                partial_accelz = 0;
 
752
                                partial_accel_n = 0;
 
753
 
 
754
                        } else {
 
755
                                // Only take current value
 
756
                                read_accelx = accelx;
 
757
                                read_accely = accely;
 
758
                                read_accelz = accelz;
 
759
                        }
 
760
 
 
761
                }
 
762
 
 
763
                if (currentTime >= compass_next_update) {
 
764
                        // Update
 
765
                        compass_next_update += compass_update_duration;
 
766
                        if (compass_next_update < currentTime) {
 
767
                                // Don't lag too much behind.
 
768
                                // If we are too slow, then we are too slow.
 
769
                                compass_next_update = currentTime;
 
770
                        }
 
771
 
 
772
                        if (average_compass) {
 
773
                                // form average
 
774
                                read_compassx = partial_compassx / partial_compass_n;
 
775
                                read_compassy = partial_compassy / partial_compass_n;
 
776
                                read_compassz = partial_compassz / partial_compass_n;
 
777
 
 
778
                                // reset average
 
779
                                partial_compassx = 0;
 
780
                                partial_compassy = 0;
 
781
                                partial_compassz = 0;
 
782
                                partial_compass_n = 0;
 
783
 
 
784
                        } else {
 
785
                                // Only take current value
 
786
                                read_compassx = compassx;
 
787
                                read_compassy = compassy;
 
788
                                read_compassz = compassz;
 
789
                        }
 
790
 
 
791
                }
 
792
 
 
793
                if (currentTime >= orientation_next_update) {
 
794
                        // Update
 
795
                        orientation_next_update += orientation_update_duration;
 
796
                        if (orientation_next_update < currentTime) {
 
797
                                // Don't lag too much behind.
 
798
                                // If we are too slow, then we are too slow.
 
799
                                orientation_next_update = currentTime;
 
800
                        }
 
801
 
 
802
                        if (average_orientation) {
 
803
                                // form average
 
804
                                read_yaw = partial_yaw / partial_orientation_n;
 
805
                                read_pitch = partial_pitch / partial_orientation_n;
 
806
                                read_roll = partial_roll / partial_orientation_n;
 
807
 
 
808
                                // reset average
 
809
                                partial_yaw = 0;
 
810
                                partial_pitch = 0;
 
811
                                partial_roll = 0;
 
812
                                partial_orientation_n = 0;
 
813
 
 
814
                        } else {
 
815
                                // Only take current value
 
816
                                read_yaw = yaw;
 
817
                                read_pitch = pitch;
 
818
                                read_roll = roll;
 
819
                        }
 
820
 
 
821
                        // Normalize values:
 
822
 
 
823
                        // Restrict pitch value to -90 to +90
 
824
                        if (read_pitch < -90) {
 
825
                                read_pitch = -180 - read_pitch;
 
826
                                read_yaw += 180;
 
827
                                read_roll += 180;
 
828
                        } else if (read_pitch > 90) {
 
829
                                read_pitch = 180 - read_pitch;
 
830
                                read_yaw += 180;
 
831
                                read_roll += 180;
 
832
 
 
833
                        }
 
834
 
 
835
                        // yaw from 0 to 360
 
836
                        if (read_yaw < 0) {
 
837
                                read_yaw = read_yaw + 360;
 
838
                        }
 
839
                        if (read_yaw >= 360) {
 
840
                                read_yaw -= 360;
 
841
                        }
 
842
 
 
843
                        // roll from -180 to + 180
 
844
                        if (read_roll >= 180) {
 
845
                                read_roll -= 360;
 
846
                        }
 
847
 
 
848
                }
 
849
 
 
850
                if (currentTime >= temperature_next_update) {
 
851
                        // Update
 
852
                        temperature_next_update += temperature_update_duration;
 
853
                        if (temperature_next_update < currentTime) {
 
854
                                // Don't lag too much behind.
 
855
                                // If we are too slow, then we are too slow.
 
856
                                temperature_next_update = currentTime;
 
857
                        }
 
858
 
 
859
                        if (average_temperature) {
 
860
                                // form average
 
861
                                read_temperature = partial_temperature / partial_temperature_n;
 
862
 
 
863
                                // reset average
 
864
                                partial_temperature = 0;
 
865
                                partial_temperature_n = 0;
 
866
 
 
867
                        } else {
 
868
                                // Only take current value
 
869
                                read_temperature = temperature;
 
870
                        }
 
871
 
 
872
                }
 
873
        }
 
874
 
 
875
        /**
 
876
         * Updates user settings by reading out the widgets.
 
877
         * This is done after some duration
 
878
         * set by user_settings_duration.
 
879
         */
 
880
        public void updateUserSettings() {
 
881
                long currentTime = System.currentTimeMillis();
 
882
                double rate;
 
883
 
 
884
                // From time to time we get the user settings:
 
885
                if (currentTime >= user_settings_next_update) {
 
886
                        // Do update
 
887
                        user_settings_next_update += user_settings_duration;
 
888
                        if (user_settings_next_update < currentTime) {
 
889
                                // Skip time if we are already behind:
 
890
                                user_settings_next_update = System.currentTimeMillis();
 
891
                        }
 
892
 
 
893
                        average_accel = mSensorSimulator.updateAverageAccelerometer();
 
894
                        rate = mSensorSimulator.getCurrentUpdateRateAccelerometer();
 
895
                        if (rate != 0) {
 
896
                                accel_update_duration = (long) (1000. / rate);
 
897
                        } else {
 
898
                                accel_update_duration = 0;
 
899
                        }
 
900
 
 
901
                        average_compass = mSensorSimulator.updateAverageCompass();
 
902
                        rate = mSensorSimulator.getCurrentUpdateRateCompass();
 
903
                        if (rate != 0) {
 
904
                                compass_update_duration = (long) (1000. / rate);
 
905
                        } else {
 
906
                                compass_update_duration = 0;
 
907
                        }
 
908
 
 
909
                        average_orientation = mSensorSimulator.updateAverageOrientation();
 
910
                        rate = mSensorSimulator.getCurrentUpdateRateOrientation();
 
911
                        if (rate != 0) {
 
912
                                orientation_update_duration = (long) (1000. / rate);
 
913
                        } else {
 
914
                                orientation_update_duration = 0;
 
915
                        }
 
916
 
 
917
                        average_temperature = mSensorSimulator.updateAverageThermometer();
 
918
                        rate = mSensorSimulator.getCurrentUpdateRateThermometer();
 
919
                        if (rate != 0) {
 
920
                                temperature_update_duration = (long) (1000. / rate);
 
921
                        } else {
 
922
                                temperature_update_duration = 0;
 
923
                        }
 
924
                }
 
925
        }
 
926
 
 
927
        /**
 
928
         * get a random number in the range -random to +random
 
929
         *
 
930
         * @param random range of random number
 
931
         * @return random number
 
932
         */
 
933
        private double getRandom(double random) {
 
934
                double val;
 
935
                val = r.nextDouble();
 
936
                return (2*val - 1) * random;
 
937
        }
 
938
 
 
939
        /* (non-Javadoc)
 
940
         * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
 
941
         */
 
942
        public void paintControl(PaintEvent e) {
 
943
                GC g2 = e.gc;
 
944
 
 
945
        double centerx = 100;
 
946
        double centery = 100;
 
947
        double centerz = -150;
 
948
        for (int i=0; i<phone.length; i+=2) {
 
949
                if (i==0) g2.setForeground(getDisplay().getSystemColor(SWT.COLOR_RED));
 
950
                if (i==24) g2.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLUE));
 
951
 
 
952
                Vector v1 = new Vector(phone[i]);
 
953
                Vector v2 = new Vector(phone[i+1]);
 
954
                v1.rollpitchyaw(rollDegree, pitchDegree, yawDegree);
 
955
                v2.rollpitchyaw(rollDegree, pitchDegree, yawDegree);
 
956
//            g2.draw(new Line2D.Double(
 
957
                g2.drawLine(
 
958
                        (int)(centerx + (v1.x + movex) * centerz / (centerz - v1.y)),
 
959
                        (int)(centery - (v1.z + movez) * centerz / (centerz - v1.y)),
 
960
                                (int)(centerx + (v2.x + movex) * centerz / (centerz - v2.y)),
 
961
                                        (int)(centery - (v2.z + movez) * centerz / (centerz - v2.y)));
 
962
        }
 
963
 
 
964
        if (mSensorSimulator.isShowAcceleration()) {
 
965
                // Now we also draw the acceleration:
 
966
                g2.setForeground(getDisplay().getSystemColor(SWT.COLOR_GREEN));
 
967
                Vector v1 = new Vector(0,0,0);
 
968
                Vector v2 = new Vector(accelx, accely, accelz);
 
969
                v2.scale(20 * ginverse);
 
970
                //Vector v2 = new Vector(1, 0, 0);
 
971
                v1.rollpitchyaw(rollDegree, pitchDegree, yawDegree);
 
972
                v2.rollpitchyaw(rollDegree, pitchDegree, yawDegree);
 
973
                g2.drawLine(
 
974
                                (int)(centerx + (v1.x + movex) * centerz / (centerz - v1.y)),
 
975
                                (int)(centery - (v1.z + movez) * centerz / (centerz - v1.y)),
 
976
                                (int)(centerx + (v2.x + movex) * centerz / (centerz - v2.y)),
 
977
                                (int)(centery - (v2.z + movez) * centerz / (centerz - v2.y)));
 
978
 
 
979
        }
 
980
        }
 
981
 
 
982
        /* (non-Javadoc)
 
983
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#doRepaint()
 
984
         */
 
985
        public void doRepaint() {
 
986
        getDisplay().asyncExec(new Runnable() {
 
987
                        public void run() {
 
988
                                redraw();
 
989
                        }
 
990
                });
 
991
        }
 
992
 
 
993
        /* (non-Javadoc)
 
994
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadAccelerometerX()
 
995
         */
 
996
        public double getReadAccelerometerX() {
 
997
                return read_accelx;
 
998
        }
 
999
 
 
1000
        /* (non-Javadoc)
 
1001
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadAccelerometerY()
 
1002
         */
 
1003
        public double getReadAccelerometerY() {
 
1004
                return read_accely;
 
1005
        }
 
1006
 
 
1007
        /* (non-Javadoc)
 
1008
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadAccelerometerZ()
 
1009
         */
 
1010
        public double getReadAccelerometerZ() {
 
1011
                return read_accelz;
 
1012
        }
 
1013
 
 
1014
        /* (non-Javadoc)
 
1015
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadCompassX()
 
1016
         */
 
1017
        public double getReadCompassX() {
 
1018
                return read_compassx;
 
1019
        }
 
1020
 
 
1021
        /* (non-Javadoc)
 
1022
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadCompassY()
 
1023
         */
 
1024
        public double getReadCompassY() {
 
1025
                return read_compassy;
 
1026
        }
 
1027
 
 
1028
        /* (non-Javadoc)
 
1029
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadCompassZ()
 
1030
         */
 
1031
        public double getReadCompassZ() {
 
1032
                return read_compassz;
 
1033
        }
 
1034
 
 
1035
        /* (non-Javadoc)
 
1036
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadYaw()
 
1037
         */
 
1038
        public double getReadYaw() {
 
1039
                return read_yaw;
 
1040
        }
 
1041
 
 
1042
        /* (non-Javadoc)
 
1043
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadPitch()
 
1044
         */
 
1045
        public double getReadPitch() {
 
1046
                return read_pitch;
 
1047
        }
 
1048
 
 
1049
        /* (non-Javadoc)
 
1050
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadRoll()
 
1051
         */
 
1052
        public double getReadRoll() {
 
1053
                return read_roll;
 
1054
        }
 
1055
 
 
1056
        /* (non-Javadoc)
 
1057
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getReadTemperature()
 
1058
         */
 
1059
        public double getReadTemperature() {
 
1060
                return read_temperature;
 
1061
        }
 
1062
 
 
1063
        /* (non-Javadoc)
 
1064
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#getBarcode()
 
1065
         */
 
1066
        public String getBarcode() {
 
1067
                return barcode;
 
1068
        }
 
1069
 
 
1070
        /* (non-Javadoc)
 
1071
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#setYawDegree(double)
 
1072
         */
 
1073
        public void setYawDegree(double yawDegree) {
 
1074
                this.yawDegree = yawDegree;
 
1075
        }
 
1076
 
 
1077
        /* (non-Javadoc)
 
1078
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#setPitchDegree(double)
 
1079
         */
 
1080
        public void setPitchDegree(double pitchDegree) {
 
1081
                this.pitchDegree = pitchDegree;
 
1082
        }
 
1083
 
 
1084
        /* (non-Javadoc)
 
1085
         * @see org.openintents.tools.sensorsimulator.IMobilePanel#setRollDegree(double)
 
1086
         */
 
1087
        public void setRollDegree(double rollDegree) {
 
1088
                this.rollDegree = rollDegree;
 
1089
        }
 
1090
 
 
1091
}