Bluetooth Library
 
Android Robotics
 

 

The Java RaspiJLib robotics library has been ported to Android Java. Consult the JDroidLib website for more information.

The classical example is a remote control of a robot vehicle. The direct mode of RaspiBrick is perfectly adapted to control the motors from a remote device. The BrickGate server running on the brick together with the class library RaspiJLib for Android hide the IP socket client-server programming code.

As special gadget the left or right LEDs are blinking when the robot takes a left or right turn. This is not a trivial task, because the blinker has to run in a separate thread.

tut01

package ch.aplu.raspipilot;

import ch.aplu.android.*;
import ch.aplu.android.raspi.*;
import android.graphics.Color;

public class RaspiPilot extends GameGrid
  implements ConnectionListener, GGPushButtonListener
{
  private class Blinker extends Thread
  {
    private boolean isLeft;
    private boolean isRunning;

    public Blinker(boolean isLeft)
    {
      this.isLeft = isLeft;
      isRunning = true;
      start();
    }

    public void run()
    {
      Led led;
      if (isLeft)
        led = new Led(Led.LED_LEFT);
      else
        led = new Led(Led.LED_RIGHT);
      while (isRunning)
      {
        led.setColor(Color.YELLOW);
        Tools.delay(200);
        led.setColor(Color.BLACK);
        Tools.delay(200);
      }
    }

    public void terminate()
    {
      isRunning = false;
    }
  }

  private String VERSION ="1.1";
  private Robot robot;
  private Gear gear;
  private Led led1, led2;
  private GGPushButton fasterBtn;
  private GGPushButton slowerBtn;
  private GGPushButton leftBtn;
  private GGPushButton rightBtn;
  private GGPushButton stopBtn;
  private GGTextField textField;
  private int v = 0;
  private final int vInc = 10;
  private int dir = 0;
  private final int dirInc = 5;
  private Blinker blinker = null;
  private boolean isButtonPressed = false;

  public RaspiPilot()
  {
    super(21, 21, 0);
    setScreenOrientation(PORTRAIT);
  }

  public void main()
  {
    String ipAddress = askIPAddress();
    getBg().clear(Color.BLUE);
    new GGTextField("Raspi Pilot V" + VERSION,
      new Location(0, 1), true).show();
    addButtons();

    robot = new Robot(this, ipAddress);
    if (!robot.isConnected())
    {
      new GGTextField("Connection failed", new Location(4, 19),
        true).show();
      return;
    }
    textField = new GGTextField("Connection established", new Location(3, 19),
      true);
    textField.show();
    gear = new Gear();
    gear.setSpeed(0);
    L.i("Creating LED_FRONT");
    led1 = new Led(Led.LED_FRONT);
    led1.setColor(Color.WHITE);
    led2 = new Led(Led.LED_REAR);
    led2.setColor(Color.RED);
    enableButtons();
    while (robot.isConnected())
    {
      dispatchButtons();
      Tools.delay(100);
    }
  }

  private String askIPAddress()
  {
    GGPreferences prefs = new GGPreferences(this);
    String oldName = prefs.retrieveString("IPAddress");
    String newName = null;
    while (newName == null || newName.equals(""))
    {
      newName = GGInputDialog.show(this, "Raspi", "Enter IP Address",
        oldName == null ? "192.168.0.4" : oldName);
    }
    prefs.storeString("IPAddress", newName);
    return newName;
  }

  private void addButtons()
  {
    fasterBtn = new GGPushButton("faster");
    addActor(fasterBtn, new Location(10, 5));
    slowerBtn = new GGPushButton("slower");
    addActor(slowerBtn, new Location(10, 15));
    leftBtn = new GGPushButton("left");
    addActor(leftBtn, new Location(3, 10));
    rightBtn = new GGPushButton("right");
    addActor(rightBtn, new Location(17, 10));
    stopBtn = new GGPushButton("stop");
    addActor(stopBtn, new Location(10, 10));
  }
  
  private void enableButtons()
  {
    fasterBtn.addPushButtonListener(this);
    slowerBtn.addPushButtonListener(this);
    leftBtn.addPushButtonListener(this);
    rightBtn.addPushButtonListener(this);
    stopBtn.addPushButtonListener(this);
  }


  public void onPause()
  {
    if (robot != null)
      robot.exit();
    super.onPause();
  }

  private void dispatchButtons()
  {
    if (fasterBtn.isPressed() && !isButtonPressed)
    {  
      isButtonPressed = true;
      faster();
    }
    else if (slowerBtn.isPressed())
    {  
      isButtonPressed = true;
      slower();
    }  
    else if (leftBtn.isPressed())
    {  
      isButtonPressed = true;
      turnLeft();
    }  
    else if (rightBtn.isPressed())
    {  
      isButtonPressed = true;
      turnRight();
    }  
    else if (stopBtn.isPressed())
    {  
      isButtonPressed = true;
      doStop();
    }  
    else if (!(fasterBtn.isPressed() || leftBtn.isPressed() || 
      rightBtn.isPressed() || stopBtn.isPressed()))
        isButtonPressed = false;
  }


  private void faster()
  {
    L.i("faster");
    if (v < 100)
    {
      v = v += vInc;
      doIt();
    }
  }

  private void slower()
  {
    L.i("slower");
    if (v > -100)
    {
      v = v -= vInc;
      doIt();
    }
  }

  private void doStop()
  {
    L.i("stop");
    v = 0;
    dir = 0;
    doIt();
  }

  private void turnLeft()
  {
    L.i("turnLeft");
    if (dir > -80 && v != 0)
    {
      dir -= dirInc;
      doIt();
    }
  }

  private void turnRight()
  {
    L.i("turnRight");
    if (dir < 80 && v != 0)
    {
      dir += dirInc;
      doIt();
    }
  }

  private void doIt()
  {
    double radius = toRadius(dir);
    gear.setSpeed(Math.abs(v));
    if (v > 0)
    {
      if (dir > 0)
      {
        gear.rightArc(radius);
        if (blinker != null)
          blinker.terminate();
        blinker = new Blinker(false);
      }
      else if (dir < 0)
      {
        gear.leftArc(radius);
        if (blinker != null)
          blinker.terminate();
        blinker = new Blinker(true);
      }
      else
      {
        gear.forward();
        if (blinker != null)
        {
          blinker.terminate();
          blinker = null;
        }
      }
    }
    else if (v < 0)
    {
      if (dir > 0)
      {
        gear.leftArc(-radius);
        if (blinker != null)
          blinker.terminate();
        blinker = new Blinker(false);
      }
      else if (dir < 0)
      {
        gear.rightArc(-radius);
        if (blinker != null)
          blinker.terminate();
        blinker = new Blinker(true);
      }
      else
      {
        gear.backward();
        if (blinker != null)
        {
          blinker.terminate();
          blinker = null;
        }
      }
    }
    else
    {
      gear.stop();
      if (blinker != null)
      {
        blinker.terminate();
        blinker = null;
      }
    }
  }

  private double toRadius(double direction)
  {
    double R = 0.05;
    if (direction != 0)
    {
      double r = Math.abs(R / Math.sin(Math.toRadians(direction)));
      return r;
    }
    return 0;
  }

  public void notifyConnection(boolean connected)
  {
    showToast(connected ? "Connection established" : "Connection lost", true);
    if (!connected)
    {
      textField.hide();
      new GGTextField("Connection lost", new Location(4, 19),
        true).show();
    }
  }
  
  public void buttonPressed(GGPushButton button)
  {}
  public void buttonReleased(GGPushButton button)
  {}
  public void buttonClicked(GGPushButton button)
  {}
  public void buttonRepeated(GGPushButton button)
  {}
}


Create QR code to download Android app to your smartphone.

downlink source (RaspiPilot.zip).
downlink Android app for installation on a smartphone or emulator.