Android Open Source - RC-Devices Main Activity






From Project

Back to project page RC-Devices.

License

The source code is released under:

GNU General Public License

If you think the Android project RC-Devices listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package pl.apcode.rcdevices;
//from   w w  w .j av a  2  s .  c  om
import  pl.apcode.rcdevices.R;
import pl.apcode.rcdevices.EventLogger;
import pl.apcode.rcdevices.communication.BluetoothLinkReceiver;
import pl.apcode.rcdevices.communication.BluetoothLinkService;
import pl.apcode.rcdevices.communication.BluetoothLinkService.LocalBinder;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.BounceInterpolator;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;


public class MainActivity extends Activity implements OnSeekBarChangeListener, OnCheckedChangeListener, SensorEventListener, OnTouchListener {

  public static final String tag = MainActivity.class.getSimpleName();
   
    BluetoothLinkService mService;
    boolean mBound = false;

  
  private SeekBar servoAngleBar,lowPassFilterBar,throttleBar, servoRateBar, throttleRateBar;
  private TextView angleValueText;
  private TextView lowFilterPassValueText;
  private TextView throttleValueText; 
  private TextView xRot, yRot, zRot;
  private TextView servoRateValueText, throttleRateValueText;
  
  private Button breaksButon, setRotRef; 
  
  private int angleMin = 0;
  private int angleMax = 180;
  private int angleCenter = 90;
  private int throttleDeadZone = 20;
  private double servoRate = 3.5;
  private double throttleRate = 3.5;
  
  
  private SensorManager mSensorManager;
    private Sensor mAccelerometer;

    private boolean mInitAccelerometer = true;
    private boolean mDriving = false;
    private boolean mFullStop = true;
    private double[] mAccVector = new double[3]; //gravity
    private double[] mAccAngle = new double[3];
    private double[] mAccAngleRef = new double[3];
    private double[] mAccAngleFiltered = new double[3];

  private volatile float filterSensivity = 0.2f;
  private BTReceiver myBTReceiver;


  private class BTReceiver extends BroadcastReceiver {

    private void handleCmd(String cmd) {
      try {
      String[] cmdParts = cmd.split("#");

      if(cmdParts.length > 1 && cmdParts[0].equals("bat"))
        setBatVoltage(Float.valueOf(cmdParts[1]));
      } catch (Exception ex) {
        EventLogger.e(tag, "BrodcastReceiver handle command failed!", ex);
      }
    }
    
    @Override
    public void onReceive(Context ctx, Intent intent) {
      
      String cmd = intent.getStringExtra("ReceiverData");
      handleCmd(cmd);
    }
    
  }
    
  
  protected void setBatVoltage(float voltage) {
    setTitle(getResources().getString(R.string.app_name) +  String.format(" | %.2f V", voltage) );
  }
  

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    
    PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
    
    setContentView(R.layout.activity_main);      
    
    angleValueText = (TextView)findViewById(R.id.servoValueText);
    lowFilterPassValueText = (TextView)findViewById(R.id.lowPassFilterValueText);
    lowFilterPassValueText.setText(String.format("%.2f", filterSensivity ));
    throttleValueText = (TextView)findViewById(R.id.textViewThrottleValue);
    
    servoRateValueText = (TextView)findViewById(R.id.servoRateValueText);
    throttleRateValueText = (TextView)findViewById(R.id.throttleRateValueText);
    
    servoAngleBar = (SeekBar)findViewById(R.id.servoAngleBar);
    servoAngleBar.setOnSeekBarChangeListener(this);
    
    lowPassFilterBar = (SeekBar)findViewById(R.id.lowPassFilterBar);
    lowPassFilterBar.setOnSeekBarChangeListener(this);
    lowPassFilterBar.setProgress(  (int)(filterSensivity * 100) );
    
    throttleBar = (SeekBar)findViewById(R.id.throttleBar);
    throttleBar.setOnSeekBarChangeListener(this);
    
    throttleRateBar = (SeekBar)findViewById(R.id.throttleRateSeekBar);
    throttleRateBar.setOnSeekBarChangeListener(this);
    
    servoRateBar = (SeekBar)findViewById(R.id.servoRateSeekBar);
    servoRateBar.setOnSeekBarChangeListener(this);
    
    breaksButon = (Button)findViewById(R.id.breaksButton);
    breaksButon.setOnTouchListener(this);
    
    setRotRef = (Button)findViewById(R.id.driveButton);
    setRotRef.setOnTouchListener(this);
          
      mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        
        xRot = (TextView)findViewById(R.id.xTextView);
        yRot = (TextView)findViewById(R.id.yTextView);
        zRot = (TextView)findViewById(R.id.zTextView);
        
        myBTReceiver = new BTReceiver();
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, data);
  }
    
    
  @Override
  protected void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
    SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    angleMin = Integer.parseInt(sharedPrefs.getString("servo-min", String.valueOf(angleMin)));
    angleMax = Integer.parseInt(sharedPrefs.getString("servo-max",  String.valueOf(angleMax)));
    throttleDeadZone = Integer.parseInt(sharedPrefs.getString("throttle-dead-zone", String.valueOf(throttleDeadZone)));
    filterSensivity = Float.parseFloat(sharedPrefs.getString("low-pass-filter", String.valueOf(filterSensivity)));
    throttleRate = Float.parseFloat(sharedPrefs.getString("throttle-rate", String.valueOf(throttleRate)));
    servoRate = Float.parseFloat(sharedPrefs.getString("servo-rate", String.valueOf(servoRate)));
    
    angleCenter = calculateServoAngle(500);
    angleValueText.setText(Integer.toString(angleCenter));
    
    
    servoRateBar.setProgress(rateProgress(servoRate));
    throttleRateBar.setProgress(rateProgress(throttleRate));
    lowPassFilterBar.setProgress(filterSensivityToProgress());
    
    mInitAccelerometer = true;
        mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
        
        
        
        IntentFilter filter = new IntentFilter(BluetoothLinkService.RECEIVED_CMD);
        registerReceiver(myBTReceiver, filter);
        btServiceBind();
  }
  
  @Override
  protected void onStop() {
    sendData("b;");
        mSensorManager.unregisterListener(this);
        unregisterReceiver(myBTReceiver);
        btServiceUnbind();
        super.onStop();
  }
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
            
            //send tick to wake up arduino battery monitor (just in case when service is up and running already)
            sendData(".;");
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };


    public void sendData(String data) {
      if(mBound)
        mService.sendData(data);
    }
    
    
  private int rateProgress(double rateValue) {
    return (int)((rateValue - 1) * 10);
  }
  
  private double rateValue(int progress) {
    return (progress / 10.0d) + 1;
  }
  
  
  private int filterSensivityToProgress() {  
    int progress = (int) (filterSensivity * 100); 
    if(progress > lowPassFilterBar.getMax())
      progress = lowPassFilterBar.getMax();
    else if(progress < 0)
      progress = 0;
    
    return progress;
  }
  
    public int calculateServoProg(int  angleValue) {
        int prg=Math.round((angleValue-angleMin)*1000.0f/(angleMax - angleMin));
      if(prg<0)
        prg=0;
      else if(prg>1000)
        prg = 1000;
      
      return prg;
    }
    
  public int calculateServoAngle(int progValue) {
    return Math.round((angleMax - angleMin) * progValue / 1000.0f + angleMin);  
  }
  
  public int calculateThrottle(int progValue) {
    return Math.round((progValue-500) * 255*2/1000.0f);
  }
  
  public int calculateThrottleProgres(int thr) {
    int prg =  Math.round(thr*1000/(255*2.0f) + 500);
      if(prg<0)
        prg=0;
      else if(prg>1000)
        prg = 1000;
      
      return prg;
  }
  
  public void updateMotor(int throttle) {
    if(throttle < -255)
      throttle = -255;
    else if(throttle > 255)
      throttle=255;
    
    
    throttleValueText.setText(Integer.toString(throttle));

    if(throttle<-1*throttleDeadZone)
      sendData("r#" + Integer.toString(Math.abs(throttle)) + ";");
    else if (throttle > throttleDeadZone)
      sendData("f#" + Integer.toString(throttle) + ";");
    else
      sendData("b;");
    
  }
  
  public void updateServo(int angle) {
    if(angle < angleMin)
      angle = angleMin;
    else if(angle > angleMax)
      angle = angleMax;
    
    angleValueText.setText(Integer.toString(angle));
    sendData("s#" + Integer.toString(angle) + ";");  
  }
  
  
  @Override
  public void onProgressChanged(SeekBar seekBar, int progress,
      boolean fromUser) {
    
    if(!mDriving) {
      if(seekBar.getId() == R.id.servoAngleBar)
        updateServo( calculateServoAngle(progress) );
      else if( seekBar.getId() == R.id.throttleBar)  
        updateMotor( calculateThrottle(progress) );  
    }
    
    if(seekBar.getId() == R.id.lowPassFilterBar) {
      filterSensivity = progress / 100.0f;
      lowFilterPassValueText.setText(String.format("%.2f", filterSensivity ));  
    } else if(seekBar.getId() == R.id.servoRateSeekBar ) {
      servoRate = rateValue(progress);
      servoRateValueText.setText(String.format("%.1f", servoRate));
    } else if(seekBar.getId() == R.id.throttleRateSeekBar) {
      throttleRate = rateValue(progress);
      throttleRateValueText.setText(String.format("%.1f", throttleRate));
    }
      
    
  }
  
  

  @Override
  public void onStartTrackingTouch(SeekBar seekBar) {
    // TODO Auto-generated method stub
    
  }

  @Override
  public void onStopTrackingTouch(SeekBar seekBar) {
    // TODO Auto-generated method stub
    
  }

  @Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) {
    // TODO Auto-generated method stub
    
  }

  @Override
  public void onSensorChanged(SensorEvent event) {
    
    if(event.sensor == mAccelerometer) {
      float[] g = event.values;
      double g_len = Math.sqrt(g[0]*g[0] + g[1]*g[1] + g[2]*g[2]);
      
      mAccVector[0] = g[0]/g_len;
      mAccVector[1] = g[1]/g_len;
      mAccVector[2] = g[2]/g_len;
      
      //calculateAngle(mAccVector, mAccAngle);
      
      if(mInitAccelerometer) {
        mInitAccelerometer = false;
        System.arraycopy(mAccVector, 0, mAccAngleRef, 0, mAccVector.length);
        System.arraycopy(mAccVector, 0, mAccAngleFiltered, 0, mAccAngle.length);
        //System.arraycopy(mAccAngle, 0, mAccAngleRef, 0, mAccAngle.length);
        
      } else {
        lowPass(mAccVector, mAccAngleFiltered);
      }
      
      double x = mAccAngleFiltered[0] - mAccAngleRef[0];
      double y = mAccAngleFiltered[1] - mAccAngleRef[1];
      double z = mAccAngleFiltered[2] - mAccAngleRef[2];
      
          xRot.setText(String.format("%4.1f", g[0]));
          yRot.setText(String.format("%4.1f", g[1]));
          zRot.setText(String.format("%4.1f", g[2]));
          
          int angle = angleCenter - (int)Math.round(x*(angleMax-angleMin)/2*servoRate);
          int throttle = (int)Math.round(-y*255*throttleRate);
          
          if(mDriving) {
            updateMotor(throttle);
            updateServo(angle);
            
            throttleBar.setProgress(calculateThrottleProgres(throttle));
            servoAngleBar.setProgress(calculateServoProg(angle));
          }
      
    }
    
  }


  protected double[] lowPass( double[] input, double[] output ) {
      
    if ( output == null ) {
      output = input.clone();
        return output;
        
    }

      for ( int i=0; i<input.length; i++ )
          output[i] = output[i] + filterSensivity * (input[i] - output[i]);        
     
      return output;
  }

  
  @Override
  public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

  }
  
  
  private void btServiceBind() {
    Intent istart = new Intent(this, BluetoothLinkService.class);
    bindService(istart, mConnection, BIND_AUTO_CREATE);
  }
  
  private void btServiceUnbind() {
      if(mBound) {
        unbindService(mConnection);
        mBound = false;
      }
  }
  
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
      // Handle item selection
      switch (item.getItemId()) {
      case R.id.action_settings:
        Intent configActivity = new Intent(this, Settings.class);
        startActivity(configActivity);
          return true;
      case R.id.connect:
        Intent istart = new Intent(this, BluetoothLinkService.class);
        if(!mBound)
          btServiceBind();
        startService(istart);      
        return true;
      case R.id.disconnect:
        btServiceUnbind();
        Intent istop = new Intent(this, BluetoothLinkService.class);
        stopService(istop);
        return true;
      default:
          return super.onOptionsItemSelected(item);
      }
  }

  
  private void fullStop() {
    mDriving=false;
    mFullStop = true;
    sendData("b;");
    throttleBar.setProgress(500);
    servoAngleBar.setProgress(500);
  }
  
  
  private void handbreakVehicle() {
    mDriving=false;
    sendData("b;");
  }
  
  
  @Override
  public boolean onTouch(View v, MotionEvent event) {
    
    if(v.getId() == R.id.breaksButton) {
      if(event.getAction() == MotionEvent.ACTION_DOWN)
        fullStop();
    } else if(v.getId() == R.id.driveButton) {
      if(event.getAction() == MotionEvent.ACTION_DOWN) {
        mDriving = true;
        if(mFullStop) {
          mInitAccelerometer = true;
          mFullStop = false;
        }
      }
      else if(event.getAction() == MotionEvent.ACTION_UP)
        handbreakVehicle();
      
    }
    return false;
  }

}




Java Source Code List

pl.apcode.rcdevices.Car.java
pl.apcode.rcdevices.EventLogger.java
pl.apcode.rcdevices.MainActivity.java
pl.apcode.rcdevices.Settings.java
pl.apcode.rcdevices.communication.BluetoothLinkReceiver.java
pl.apcode.rcdevices.communication.BluetoothLinkServiceHandler.java
pl.apcode.rcdevices.communication.BluetoothLinkService.java