~vcs-imports/openintents/trunk

« back to all changes in this revision

Viewing changes to sensorsimulator/SensorSimulator/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
 
}