Android Open Source - MultiWork Brazo Robot






From Project

Back to project page MultiWork.

License

The source code is released under:

Copyright (c) 2013, Torti Andr?s Fernando All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions a...

If you think the Android project MultiWork 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 com.roboticarm.andres;
//from  w ww  .  j ava  2  s  .c  o  m
import com.bluetoothutils.andres.BTSingleSynchTransfer;
import com.multiwork.andres.ApplicationContext;
import com.multiwork.andres.R;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;

public class BrazoRobot extends Activity implements OnTouchListener{

  private static final boolean DEBUG = true;
  
  /** Datos de transmicion */
  private static final byte Pad1 = 0;
  private static final byte Pad2 = 1;
  private static final byte Munieca = 2;
  private static final byte Pinza = 3;
  
  /** View que dibuja los joystick */
  private static JoystickView mView;
  private static int pointerID1;
  private static int pointerID2;
  
  /** Centro en x del circulo que se mueve */
  private static float xCenter1 ;
  /** Centro en y del circulo que se mueve */
  private static float yCenter1;
  /** Centro en x del circulo que se mueve */
  private static float xCenter2;
  /** Centro en y del circulo que se mueve */
  private static float yCenter2;
  /** Radio de los circulos estticos (contorno) */
  private static float staticRadio;
  /** Radio de los circulos que se mueven */
  private static float joystickRadio;
  /** Padding de los circulos estaticos desde la mitad y bordes de pantalla */
  private static final int padding = 50;
  /** Padding de los botones de control del servo desde el centro de la pantalla */
  private static final int paddingCenter = 40;
  /** Relacion del tamao de los joystick con los radios externos (estticos) si es 2 por ejemplo es la mitad */
  private static final float ampFactor = 3f;
  /** Offset del centro de los joystick */
  private static final float centerOffset = 40;
  
  /** Joysticks */
  private static Joystick pad1, pad2;
  
  // Limites de los circulos
  private static float rightLimit1;
  private static float rightLimit2;
  private static float leftLimit1;
  private static float leftLimit2;
  
  private static float upperLimit1;
  private static float upperLimit2;
  private static float lowerLimit1;
  private static float lowerLimit2;
  
  // Mueca
  private static final int servo1MaxAngle  = 180;
  private static final int servo1MinAngle  = 0;
  // Pinza
  private static final int servo2MaxAngle  = 140;
  private static final int servo2MinAngle  = 65;
  
  private static final int angleStep = 5;
  
  private static int servo1Angle = servo1MinAngle, servo2Angle = servo2MinAngle;
  
  /** Cdigo que obtengo en onActivityResult() al recibir el resultado de activar el bluetooth */
  private static final int REQUEST_ENABLE_BT = 1;
  private static BTSingleSynchTransfer mBTSingleSynchTransfer;
  
  /** Inidica si ya se tomaron las medidas de la pantalla y se puede usar el touchscreen */
  private static boolean isSystemRdy = false;
  
  private static int screenHeight;
  private static int screenWidth;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(DEBUG) Log.i("BrazoRobot", "onCreate()");
    
    setContentView(R.layout.brazo_robot);
    mView = (JoystickView) findViewById(R.id.joystickView);
    mView.setOnTouchListener(this);
    
    // Se llama al listener cuando el layout termin de dibujarse porque si tomaramos las medidas antes nos darian 0
    // porque el layout an no se dibuja en onCreate() ni en onResume()
    mView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
      @Override
      public void onGlobalLayout() {
        if(!isSystemRdy){
          
          screenHeight = mView.getHeight();
          screenWidth = mView.getWidth();
              
          if(DEBUG) Log.i("BrazoRobot", "Screen Height: " + screenHeight);
          if(DEBUG) Log.i("BrazoRobot", "Screen Width: " + screenWidth);
              
          // Creo los PAD
          pad1 = new Joystick();
          pad2 = new Joystick();
              
          // Pad 1
          xCenter1 = (screenWidth / 4) - centerOffset;            // Extremo izquierdo
          yCenter1 = screenHeight / 2;
          // Pad 2
          xCenter2 = (screenWidth - (screenWidth / 4)) + centerOffset;    // Extremo derecho
          yCenter2 = screenHeight / 2;
          // Radios
          staticRadio = ((screenWidth / 2) - (3*padding)) / 2;
          joystickRadio = staticRadio / ampFactor;
          // Lmites
          rightLimit1 = xCenter1 + staticRadio;
          rightLimit2 = xCenter2 + staticRadio;
          leftLimit1 = xCenter1 - staticRadio;
          leftLimit2 = xCenter2 - staticRadio;
          
          upperLimit1 = yCenter1 - staticRadio;
          upperLimit2 = yCenter2 - staticRadio;
          lowerLimit1 = yCenter1 + staticRadio;
          lowerLimit2 = yCenter2 + staticRadio;
              
          // Pad 1
          pad1.setXCenter(xCenter1);
          pad1.setYCenter(yCenter1);
          pad1.setX(xCenter1);
          pad1.setY(yCenter1);
          pad1.setMaxDistance(staticRadio);
          pad1.setMaxProportional(500);
              
          // Pad 2
          pad2.setXCenter(xCenter2);
          pad2.setYCenter(yCenter2);
          pad2.setX(xCenter2);
          pad2.setY(yCenter2);
          pad2.setMaxDistance(staticRadio);
          pad2.setMaxProportional(500);
          
          // Configuro los radios
          mView.setConfigurations(staticRadio, joystickRadio, pad1, pad2);
              
          if(DEBUG) Log.i("BrazoRobot", "xCenter1: " + pad1.getXCenter());
          if(DEBUG) Log.i("BrazoRobot", "xCenter2: " + pad2.getXCenter());
          
          // Posicin rotacion de mueca
          RelativeLayout.LayoutParams params = (LayoutParams) findViewById(R.id.rightGiro).getLayoutParams();
          params.leftMargin = (int)((screenWidth/2f) + paddingCenter);
          findViewById(R.id.rightGiro).setLayoutParams(params);
          
          params = (LayoutParams) findViewById(R.id.leftGiro).getLayoutParams();
          params.leftMargin = (int)((screenWidth/2f) - paddingCenter - findViewById(R.id.leftGiro).getWidth());
          findViewById(R.id.leftGiro).setLayoutParams(params);
          
          // Posicin apertura y cierre de pinza
          params = (LayoutParams) findViewById(R.id.openClaw).getLayoutParams();
          params.leftMargin = (int)((screenWidth/2f) + paddingCenter);
          findViewById(R.id.openClaw).setLayoutParams(params);
          
          params = (LayoutParams) findViewById(R.id.closeClaw).getLayoutParams();
          params.leftMargin = (int)((screenWidth/2f) - paddingCenter - findViewById(R.id.closeClaw).getWidth());
          findViewById(R.id.closeClaw).setLayoutParams(params);
          
          isSystemRdy = true;    
          mView.redraw();
        }
      }
    });
    
    // Mueca, gira izquierda
    findViewById(R.id.leftGiro).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Log.i("Button", "Button left");
        if(servo1Angle >= (servo1MinAngle+angleStep)) servo1Angle -= angleStep;
        mBTSingleSynchTransfer.btSendDataWithSync(new byte[] {(byte)servo1Angle}, Munieca);
      }
    });
    
    // Mueca, gira derecha
    findViewById(R.id.rightGiro).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Log.i("Button", "Button right");
        if(servo1Angle <= (servo1MaxAngle-angleStep)) servo1Angle += angleStep;
        mBTSingleSynchTransfer.btSendDataWithSync(new byte[] {(byte)servo1Angle}, Munieca);
      }
    });
    
    // Pinza, cierra
    findViewById(R.id.closeClaw).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Log.i("Button", "Close claw");
        if(servo2Angle >= (servo2MinAngle+angleStep)) servo2Angle -= angleStep;
        mBTSingleSynchTransfer.btSendDataWithSync(new byte[] {(byte)servo2Angle}, Pinza);
      }
    });
    
    // Pinza, abre
    findViewById(R.id.openClaw).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Log.i("Button", "Open claw");
        if(servo2Angle <= (servo2MaxAngle-angleStep)) servo2Angle += angleStep;
        mBTSingleSynchTransfer.btSendDataWithSync(new byte[] {(byte)servo2Angle}, Pinza);
      }
    });
    
    // Esto permite que se puedan tocar los View debajo de este View. El Canvas del joystick usa toda la pantalla
    // por lo que si tocamos sobre algn boton el sistema no lo toma ya que primero esta el Canvas de los
    // Joystick arriba. Esto permite que se toquen los botones abajo de este View. Viene desactivado por defecto
    // por seguridad. http://stackoverflow.com/questions/12398402/android-overlay-layout-on-top-of-all-windows-that-receives-touches
    mView.setFilterTouchesWhenObscured(false);
    
  }

  @Override
  protected void onResume() {
    super.onResume();
    if(DEBUG) Log.i("BrazoRobot", "onResume()");
    
    ApplicationContext myApp = (ApplicationContext)getApplication();
    isSystemRdy = false;
    
    mBTSingleSynchTransfer = new BTSingleSynchTransfer(myApp.mOutputStream,
        myApp.mInputStream);
      mBTSingleSynchTransfer.start();
  }
    
  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == REQUEST_ENABLE_BT){
      if(resultCode == RESULT_CANCELED){
        finish();
      }
    }
  }

  @Override
  public boolean onTouch(View v, MotionEvent event) {
    // Evita que se modifique pad1 y pad2 si an no han sido creados porque las medidas de la pantalla no se tomaron an
    if(isSystemRdy){
      if(DEBUG) Log.i("BrazoRobotTouch", "onTouch()");
      
      int touchEvents = event.getPointerCount();
      float tempX[] = new float[touchEvents];
      float tempY[] = new float[touchEvents];
      
      // Busco las coordenadas de todos los eventos Multi-Touch
      // http://stackoverflow.com/questions/8059127/android-multi-touch
      // http://android-developers.blogspot.com.ar/2010/06/making-sense-of-multitouch.html
      for(int n=0; n < touchEvents; ++n) {
        tempX[n] = event.getX(n);
        tempY[n] = event.getY(n);
        //if(DEBUG) Log.i("BrazoRobotP", "pointerID[" + n + "]: " + event.getPointerId(n));
      }
      
      // Debug
      if(DEBUG) Log.i("BrazoRobotTouch", "PointerCount: " + touchEvents);
      if(DEBUG) {
        for(int n=0; n < tempX.length; ++n) {
          Log.i("BrazoRobotTouch","tempX[" + n + "]: " + tempX[n] +
                     "   tempY[" + n + "]: " + tempY[n]);
        }
      }
  
      // Compruebo que coordenadas estan dentro del primer circulo
      for(int n=0; n < touchEvents; ++n) {
        if(tempX[n] < rightLimit1 && tempX[n] > leftLimit1 && tempY[n] > upperLimit1 && tempY[n] < lowerLimit1) {
          //pad1.setX(tempX[n]);
          if( Math.abs(pad1.getY() - tempY[n]) > 10){
            pad1.setY(tempY[n]);
            mBTSingleSynchTransfer.btSendDataWithSync(pad1.toYBytes(), Pad1);
          }
          pointerID1 = event.getPointerId(n);    // Obtengo el ID del touch este
        }
      }
      // Compruebo que coordenadas estan dentro del segundo circulo
      for(int n=0; n < touchEvents; ++n) {
        if(tempX[n] < rightLimit2 && tempX[n] > leftLimit2 && tempY[n] > upperLimit2 && tempY[n] < lowerLimit2) {
          //pad2.setX(tempX[n]);
          if( Math.abs(pad2.getY() - tempY[n]) > 10){
            pad2.setY(tempY[n]);
            mBTSingleSynchTransfer.btSendDataWithSync(pad2.toYBytes(), Pad2);
          }
          pointerID2 = event.getPointerId(n);    // Obtengo el ID del touch este
        }
      }
      
      // Cuando se suelta el touch
      // http://android-developers.blogspot.com.ar/2010/06/making-sense-of-multitouch.html
      if( ( (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) ||
            ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) ) {
          if(DEBUG) Log.i("BrazoRobotTouch", "Pointer_UP - UP");
          
          // Obtengo el ID del touch que se solto
          final int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                      >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
              final int pointerID = event.getPointerId(pointerIndex);
              
              if(DEBUG) Log.i("BrazoRobotTouch", "pointerID: " + pointerID);
          if(DEBUG) Log.i("BrazoRobotTouch", "ID1: " + pointerID1);
          if(DEBUG) Log.i("BrazoRobotTouch", "ID2: " + pointerID2);
              
          // Si el ID es el del primer circulo
              if(pointerID == pointerID1) {
                if(DEBUG) Log.i("BrazoRobotTouch", "Reset 1");
            //pad1.setX(xCenter1);
            pad1.setY(yCenter1);
            mBTSingleSynchTransfer.btSendDataWithSync(pad1.toYBytes(), Pad1);
              }
              // Si el ID es del segundo circulo
              if(pointerID == pointerID2) {
                if(DEBUG) Log.i("BrazoRobotTouch", "Reset 2");
            //pad2.setX(xCenter2);
            pad2.setY(yCenter2);
            mBTSingleSynchTransfer.btSendDataWithSync(pad2.toYBytes(), Pad2);
              }
        }
      mView.redraw();
      
      // Duermo el Thread por 20mS para reducir uso de CPU
      try { Thread.sleep(20); } 
      catch (InterruptedException e) { e.printStackTrace(); }
    }
    
    return true;  // Si el valor aqui es 'false' se retorna y se espera a que se suelte y se toque de nuevo la pantalla
            // Si el valor aqui es 'true' nos da continuamente las coordenadas (permite deslizarnos sin clicks)
  }

}




Java Source Code List

com.bluetoothutils.andres.BTSingleSynchTransfer.java
com.bluetoothutils.andres.BluetoothHelper.java
com.bluetoothutils.andres.DeviceScanner.java
com.bluetoothutils.andres.OnBluetoothConnected.java
com.bluetoothutils.andres.OnDeviceSelected.java
com.bluetoothutils.andres.OnNewBluetoothDataReceived.java
com.frecuencimeter.andres.FrecView.java
com.frecuencimeter.andres.Frecuencia.java
com.multiwork.andres.ApplicationContext.java
com.multiwork.andres.LCView.java
com.multiwork.andres.MainMenu.java
com.multiwork.andres.MainPrefs.java
com.multiwork.andres.MenuListAdapter.java
com.protocolanalyzer.andres.AnalyzerExpandableAdapter.java
com.protocolanalyzer.andres.CRC16.java
com.protocolanalyzer.andres.LogicAnalizerPrefsFragment.java
com.protocolanalyzer.andres.LogicAnalizerPrefs.java
com.protocolanalyzer.andres.LogicAnalyzerActivity.java
com.protocolanalyzer.andres.LogicAnalyzerChartFragment.java
com.protocolanalyzer.andres.LogicAnalyzerListFragment.java
com.protocolanalyzer.andres.OnActionBarClickListener.java
com.protocolanalyzer.andres.OnDataClearedListener.java
com.protocolanalyzer.andres.OnDataDecodedListener.java
com.roboticarm.andres.BrazoRobot.java
com.roboticarm.andres.JoystickView.java
com.roboticarm.andres.Joystick.java
com.tjerkw.slideexpandable.library.AbstractSlideExpandableListAdapter.java
com.tjerkw.slideexpandable.library.ActionSlideExpandableListView.java
com.tjerkw.slideexpandable.library.ExpandCollapseAnimation.java
com.tjerkw.slideexpandable.library.SlideExpandableListAdapter.java
com.tjerkw.slideexpandable.library.SlideExpandableListView.java
com.tjerkw.slideexpandable.library.WrapperListAdapterImpl.java
com.utils.andres.ConflictChecker.java
com.utils.andres.Dependency.java
com.utils.andres.Pair.java