/** * Updates user settings by reading out the widgets. This is done after some duration set by * user_settings_duration. */ public void updateUserSettings() { long currentTime = System.currentTimeMillis(); double rate; // From time to time we get the user settings: if (currentTime >= user_settings_next_update) { // Do update user_settings_next_update += user_settings_duration; if (user_settings_next_update < currentTime) { // Skip time if we are already behind: user_settings_next_update = System.currentTimeMillis(); } average_accel = mSensorSimulator.updateAverageAccelerometer(); rate = mSensorSimulator.getCurrentUpdateRateAccelerometer(); if (rate != 0) { accel_update_duration = (long) (1000. / rate); } else { accel_update_duration = 0; } average_compass = mSensorSimulator.updateAverageCompass(); rate = mSensorSimulator.getCurrentUpdateRateCompass(); if (rate != 0) { compass_update_duration = (long) (1000. / rate); } else { compass_update_duration = 0; } average_orientation = mSensorSimulator.updateAverageOrientation(); rate = mSensorSimulator.getCurrentUpdateRateOrientation(); if (rate != 0) { orientation_update_duration = (long) (1000. / rate); } else { orientation_update_duration = 0; } average_temperature = mSensorSimulator.updateAverageThermometer(); rate = mSensorSimulator.getCurrentUpdateRateThermometer(); if (rate != 0) { temperature_update_duration = (long) (1000. / rate); } else { temperature_update_duration = 0; } } }
/** * Draws the phone. * * @param graphics */ protected void paintComponent(Graphics graphics) { super.paintComponent(graphics); // g.drawString("This is my custom Panel!",(int)yawDegree,(int)pitch); Graphics2D g2 = (Graphics2D) graphics; // draw Line2D.Double double centerx = 100; double centery = 100; double centerz = -150; for (int i = 0; i < phone.length; i += 2) { if (i == 0) g2.setColor(Color.RED); if (i == 24) g2.setColor(Color.BLUE); Vector v1 = new Vector(phone[i]); Vector v2 = new Vector(phone[i + 1]); v1.rollpitchyaw(rollDegree, pitchDegree, yawDegree); v2.rollpitchyaw(rollDegree, pitchDegree, yawDegree); g2.draw( new Line2D.Double( centerx + (v1.x + movex) * centerz / (centerz - v1.y), centery - (v1.z + movez) * centerz / (centerz - v1.y), centerx + (v2.x + movex) * centerz / (centerz - v2.y), centery - (v2.z + movez) * centerz / (centerz - v2.y))); } if (mSensorSimulator.isShowAcceleration()) { // Now we also draw the acceleration: g2.setColor(Color.GREEN); Vector v1 = new Vector(0, 0, 0); Vector v2 = new Vector(accelx, accely, accelz); v2.scale(20 * ginverse); // Vector v2 = new Vector(1, 0, 0); v1.rollpitchyaw(rollDegree, pitchDegree, yawDegree); v2.rollpitchyaw(rollDegree, pitchDegree, yawDegree); g2.draw( new Line2D.Double( centerx + (v1.x + movex) * centerz / (centerz - v1.y), centery - (v1.z + movez) * centerz / (centerz - v1.y), centerx + (v2.x + movex) * centerz / (centerz - v2.y), centery - (v2.z + movez) * centerz / (centerz - v2.y))); } }
/** * Updates physical model of all sensors by minimum time-step. * * <p>This internal update provides the close-to-continuum description of the sensors. It does not * yet provide the values that are read out by the Sensors class (which are obtained by further * time-selection or averaging). */ public void updateSensorPhysics() { Vector vec; double random; // Update the timer if necessary: double newdelay; newdelay = mSensorSimulator.getUpdateSensors(); if (newdelay > 0) { mSensorSimulator.setDelay((int) newdelay); } dt = 0.001 * mSensorSimulator.getDelay(); // from ms to s g = mSensorSimulator.getGravityConstant(); if (g != 0) { ginverse = 1 / g; } meterperpixel = 1 / mSensorSimulator.getPixelsPerMeter(); k = mSensorSimulator.getSpringConstant(); gamma = mSensorSimulator.getDampingConstant(); /* // Calculate velocity induced by mouse: double f = meterperpixel / g; vx = f * ((double) (movex - oldx)) / dt; vz = f * ((double) (movez - oldz)) / dt; // Calculate acceleration induced by mouse: ax = (vx - oldvx) / dt; az = (vz - oldvz) / dt; */ // New physical model of acceleration: // Have accelerometer be steered by string. // We will treat this 2D only, as the rest is a linear // transformation, and we assume all three accelerometer // directions behave the same. // F = m * a // F = - k * x // First calculate the force acting on the // sensor test particle, assuming that // the accelerometer is mounted by a string: // F = - k * x Fx = +k * (movex - accx); Fz = +k * (movez - accz); // a = F / m ax = Fx / m; az = Fz / m; // Calculate velocity by integrating // the current acceleration. // Take into account damping // by damping constant gamma. // integrate dv/dt = a - v*gamma // vx += (ax - vx * gamma) * dt; // vz += (az - vz * gamma) * dt; vx += (ax) * dt; vz += (az) * dt; // Now this is the force that tries to adjust // the accelerometer back // integrate dx/dt = v; accx += vx * dt; accz += vz * dt; // We put damping here: We don't want to damp for // zero motion with respect to the background, // but with respect to the mobile phone: accx += gamma * (movex - accx) * dt; accz += gamma * (movez - accz) * dt; /* // Old values: oldx = movex; oldz = movez; oldvx = vx; oldvz = vz; */ // Calculate acceleration by gravity: double gravityax; double gravityay; double gravityaz; gravityax = mSensorSimulator.getGravityX(); gravityay = mSensorSimulator.getGravityY(); gravityaz = mSensorSimulator.getGravityZ(); //// // Now calculate this into mobile phone acceleration: // ! Mobile phone's acceleration is just opposite to // lab frame acceleration ! vec = new Vector(-ax * meterperpixel + gravityax, gravityay, -az * meterperpixel + gravityaz); // we reverse roll, pitch, and yawDegree, // as this is how the mobile phone sees the coordinate system. vec.reverserollpitchyaw(rollDegree, pitchDegree, yawDegree); if (mSensorSimulator.isEnabledAccelerometer()) { if (mSensorSimulator.useRealDeviceWiimtoe()) { accelx = mSensorSimulator.getWiiMoteData().getX() * g; accely = mSensorSimulator.getWiiMoteData().getY() * g; accelz = mSensorSimulator.getWiiMoteData().getZ() * g; } else { accelx = vec.x; accely = vec.y; accelz = vec.z; if (mSensorSimulator.useRealDeviceThinkpad()) { // We will use data directly from sensor instead: // Read data from file String line = ""; try { // FileReader always assumes default encoding is OK! BufferedReader input = new BufferedReader(new FileReader(mSensorSimulator.getRealDevicePath())); try { line = input.readLine(); } finally { input.close(); // mSensorSimulator.mRealDeviceThinkpadOutputLabel.setBackground(Color.WHITE); } } catch (IOException ex) { ex.printStackTrace(); // mSensorSimulator.mRealDeviceThinkpadOutputLabel.setBackground(Color.RED); line = "Error reading file!"; } // Show the line content: mSensorSimulator.setRealDeviceOutput(line); // Assign values // Create z-component (optional) } // Add random component: random = mSensorSimulator.getRandomAccelerometer(); if (random > 0) { accelx += getRandom(random); accely += getRandom(random); accelz += getRandom(random); } // Add accelerometer limit: double limit = g * mSensorSimulator.getAccelerometerLimit(); if (limit > 0) { // limit on each component separately, as each is // a separate sensor. if (accelx > limit) accelx = limit; if (accelx < -limit) accelx = -limit; if (accely > limit) accely = limit; if (accely < -limit) accely = -limit; if (accelz > limit) accelz = limit; if (accelz < -limit) accelz = -limit; } } } else { accelx = 0; accely = 0; accelz = 0; } // Calculate magnetic field: // Calculate acceleration by gravity: double magneticnorth; double magneticeast; double magneticvertical; if (mSensorSimulator.isEnabledMagneticField()) { magneticnorth = mSensorSimulator.getMagneticFieldNorth(); magneticeast = mSensorSimulator.getMagneticFieldEast(); magneticvertical = mSensorSimulator.getMagneticFieldVertical(); // Add random component: random = mSensorSimulator.getRandomMagneticField(); if (random > 0) { magneticnorth += getRandom(random); magneticeast += getRandom(random); magneticvertical += getRandom(random); } // Magnetic vector in phone coordinates: vec = new Vector(magneticeast, magneticnorth, -magneticvertical); vec.scale(0.001); // convert from nT (nano-Tesla) to �T (micro-Tesla) // we reverse roll, pitch, and yawDegree, // as this is how the mobile phone sees the coordinate system. vec.reverserollpitchyaw(rollDegree, pitchDegree, yawDegree); compassx = vec.x; compassy = vec.y; compassz = vec.z; } else { compassx = 0; compassy = 0; compassz = 0; } // Orientation is currently not affected: if (mSensorSimulator.isEnabledOrientation()) { // yaw = Math.toRadians(yawDegree); // pitch = Math.toRadians(pitchDegree); // roll = Math.toRadians(rollDegree); // Since OpenGL uses degree as input, // and it seems also more user-friendly, // let us stick to degree. // (it seems, professional sensors also use // degree output.) yaw = yawDegree; pitch = pitchDegree; roll = rollDegree; // Add random component: random = mSensorSimulator.getRandomOrientation(); if (random > 0) { yaw += getRandom(random); pitch += getRandom(random); roll += getRandom(random); } } else { yaw = 0; pitch = 0; roll = 0; } // Thermometer if (mSensorSimulator.isEnabledTemperature()) { temperature = mSensorSimulator.getTemperature(); // Add random component: random = mSensorSimulator.getRandomTemperature(); if (random > 0) { temperature += getRandom(random); } } else { temperature = 0; } // Barcode if (mSensorSimulator.isEnabledBarcodeReader()) { barcode = mSensorSimulator.getBarcode(); } if (mSensorSimulator.isShowAcceleration()) { // We only have to repaint if we show the acceleration, // otherwise the phone does not change as long as there is // no user interaction. repaint(); } ; }