//
you're reading...
Android, How-to's

Improved Android Control App

enhanced

I have added some extra control to the previous Android EV3 control app

The adjust checkbox allows you to set the current angle of the robot, without rotating it. The two sliders let you adjust the travel and rotation speed of the robot up to the maximum.

The new MainActivity is:

package org.lejos.android.sample.ev3androidrotate;

import java.io.IOException;

import org.lejos.android.sample.ev3androidrotate.RotationControl.RotationListener;

import lejos.remote.ev3.RemoteRequestEV3;
import lejos.remote.ev3.RemoteRequestPilot;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.CheckBox;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnTouchListener,
		RotationListener, OnSeekBarChangeListener {
	private static final String HOST = "192.168.0.9";
	private RemoteRequestEV3 ev3;
	private RemoteRequestPilot pilot;
	private int angle;
	private ImageButton forward, backward;
	private SeekBar speed, rotationSpeed;
	private CheckBox adjust;
	private TextView speedValue, rotationSpeedValue;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		forward = (ImageButton) findViewById(R.id.forward);
		forward.setOnTouchListener(this);

		backward = (ImageButton) findViewById(R.id.backward);
		backward.setOnTouchListener(this);
		
		adjust = (CheckBox) findViewById(R.id.adjust);
		
		speed = (SeekBar) findViewById(R.id.speed);
		speed.setOnSeekBarChangeListener(this);	
		speedValue = (TextView) findViewById(R.id.speedValue);
		speed.setProgress(50);
		
		rotationSpeed = (SeekBar) findViewById(R.id.rotateSpeed);
		rotationSpeed.setOnSeekBarChangeListener(this);	
		rotationSpeedValue = (TextView) findViewById(R.id.rotateSpeedValue);
		rotationSpeed.setProgress(50);

		RotationControl rotateView = (RotationControl) findViewById(R.id.rotate);
		rotateView.setRotationListener(this);

		// Connect to the EV3
		new Control().execute("connect", HOST);
	}

	@Override
	public void onAngleChanged(int angle) {
		if (!adjust.isChecked()) new Control().execute("rotate", "" + angle);
		else this.angle = angle;
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		int action = event.getAction();
		if (action == MotionEvent.ACTION_UP)
			new Control().execute("stop");
		else if (action == MotionEvent.ACTION_DOWN) {
			if (v == forward)
				new Control().execute("forward");
			else if (v == backward)
				new Control().execute("backward");
		}
		return false;
	}
	
	@Override
	public void onProgressChanged(SeekBar seekBar, int progress,
			boolean fromUser) {
		if (seekBar == speed) speedValue.setText("Travel speed: " + progress);
		else if (seekBar == rotationSpeed) rotationSpeedValue.setText("Rotation speed: " + progress);
	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {
	}

	@Override
	public void onStopTrackingTouch(SeekBar seekBar) {	
	}

	private class Control extends AsyncTask<String, Integer, Long> {
		protected Long doInBackground(String... cmd) {
			if (cmd[0].equals("connect")) {
				try {
					ev3 = new RemoteRequestEV3(cmd[1]);
					pilot = (RemoteRequestPilot) ev3.createPilot(3.5f, 20f,
							"A", "B");
					speed.setMax((int) pilot.getMaxTravelSpeed());
					rotationSpeed.setMax((int) pilot.getRotateMaxSpeed());
				} catch (IOException e) {
					return 1l;
				}
			} else if (cmd[0].equals("rotate")) {
				if (ev3 == null)
					return 2l;
				int newAngle = Integer.parseInt(cmd[1]);
				pilot.setRotateSpeed(rotationSpeed.getProgress());
				pilot.rotate(angle - newAngle);
				angle = newAngle;
			} else if (cmd[0].equals("forward")) {
				if (ev3 == null)
					return 2l;
				pilot.setTravelSpeed(speed.getProgress());
				pilot.forward();
			} else if (cmd[0].equals("backward")) {
				if (ev3 == null)
					return 2l;
				pilot.setTravelSpeed(speed.getProgress());
				pilot.backward();
			} else if (cmd[0].equals("stop")) {
				if (ev3 == null)
					return 2l;
				pilot.stop();
			} else if (cmd[0].equals("close")) {
				if (ev3 == null)
					return 2l;
				pilot.close();
				ev3.disConnect();
			}
			return 0l;
		}

		protected void onPostExecute(Long result) {
			if (result == 1l)
				Toast.makeText(MainActivity.this, "Could not connect to EV3",
						Toast.LENGTH_LONG).show();
			else if (result == 2l)
				Toast.makeText(MainActivity.this, "Not connected",
						Toast.LENGTH_LONG).show();
		}
	}
}

The new layout is:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ImageButton
        android:id="@+id/backward"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentTop="true"
        android:layout_marginTop="21dp"
        android:layout_toLeftOf="@+id/rotate"
        android:background="@null"
        android:scaleType="fitCenter"
        android:src="@drawable/backward" />

    <ImageButton
        android:id="@+id/forward"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignTop="@+id/backward"
        android:layout_toRightOf="@+id/rotate"
        android:background="@null"
        android:scaleType="fitCenter"
        android:src="@drawable/forward" />

    <org.lejos.android.sample.ev3androidrotate.RotationControl
        android:id="@+id/rotate"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignTop="@+id/forward"
        android:layout_centerHorizontal="true" />

    <TextView
        android:id="@+id/speedValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/adjust"
        android:layout_below="@+id/speed"
        android:ems="10" >
    </TextView>

    <TextView
        android:id="@+id/rotateSpeedValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/rotateSpeed"
        android:layout_marginTop="18dp"
        android:layout_toLeftOf="@+id/forward"
        android:ems="10" />

    <CheckBox
        android:id="@+id/adjust"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/rotate"
        android:layout_centerHorizontal="true"
        android:text="Adjust" />

    <SeekBar
        android:id="@+id/speed"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/backward"
        android:layout_below="@+id/adjust"
        android:max="100" />

    <SeekBar
        android:id="@+id/rotateSpeed"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/speed"
        android:layout_below="@+id/speedValue"
        android:layout_marginTop="22dp"
        android:max="100" />

</RelativeLayout>
Advertisements

Discussion

One thought on “Improved Android Control App

  1. A really nice project that I finally got to work after having trouble because the RemoteRequestEV3- and RemoteRequestPilot-Classes are part of the 0.9-lejos-ev3 distribution that hasn’t been made available yet – so I used parts of the 0.8.2-distribution: http://sourceforge.net/p/lejos/ev3/ci/0.8.2-beta/tree/
    A minor issue:
    Changing screen orientation from portrait to landscape (and back) leads to repeated calls to onCreate and therefore to reconnecting although the connection hasn’t been properly closed before (with pilot.close() and ev3.disConnect();). This is troubling my EV3 so that it is no longer controllable. A simple but not very elegant remedy is to explicitly disconnect in the onDestroy-Method so that a fresh connection can be established again when screen orientation changes.

    @Override
    public void onDestroy() {
    super.onDestroy();
    new Control().execute(“close”, HOST);
    Toast.makeText(MainActivity.this, “Disconnecting…”,
    Toast.LENGTH_SHORT).show();
    }

    Thank you for publishing this project!

    Posted by Jaydee | 2014/08/28, 09:23

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

About leJOS News

leJOS News keeps you up-to-date with leJOS. It features latest news, explains cool features, shows advanced techniques and highlights amazing projects. Be sure to subscribe to leJOS News and never miss an article again. Best of all, subscription is free!
Follow leJOS News on WordPress.com
%d bloggers like this: