Added support of USB PS Joystic
Esse commit está contido em:
@@ -1,6 +1,6 @@
|
||||
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/AbsoluteLayout1"
|
||||
android:id="@+id/ps3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" >
|
||||
|
||||
@@ -57,8 +57,16 @@
|
||||
style="?android:attr/buttonStyleSmall"
|
||||
android:layout_width="90dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_x="106dp"
|
||||
android:layout_x="25dp"
|
||||
android:layout_y="250dp"
|
||||
android:text="Connect" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/ps3Button"
|
||||
android:layout_width="116dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_x="128dp"
|
||||
android:layout_y="251dp"
|
||||
android:text="Connect PS3" />
|
||||
|
||||
</AbsoluteLayout>
|
||||
@@ -0,0 +1,231 @@
|
||||
package com.codeminders.ardrone;
|
||||
|
||||
import com.codeminders.ardrone.ARDrone;
|
||||
import com.codeminders.ardrone.ARDrone.Animation;
|
||||
import com.codeminders.ardrone.ARDrone.LED;
|
||||
import com.codeminders.ardrone.ARDrone.VideoChannel;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
/**
|
||||
* This class represents one control mapping for a button and at the same
|
||||
* time implements all control logic for button presses.
|
||||
* @author normenhansen
|
||||
*/
|
||||
public class AssignableControl {
|
||||
|
||||
public enum Command {
|
||||
|
||||
TAKEOFF, LAND, TRIM, CLEAR_EMERGENCY, PLAY_ANIMATION, PLAY_LED, RESET,
|
||||
VIDEO_CYCLE, FRONTAL_CAM, BOTTOM_CAM, BOTTOM_CAM_SMALL, FRONTAL_CAM_SMALL, TAKE_SNAPSHOT, RECORD_VIDEO
|
||||
}
|
||||
|
||||
public enum ControllerButton {
|
||||
|
||||
PS, SELECT, START, LEFT_STICK, RIGHT_STICK, TRIANGLE, CIRCLE, CROSS, SQUARE, L1, L2, R1, R2
|
||||
}
|
||||
|
||||
public enum ControllerAxis {
|
||||
|
||||
LEFT_X, LEFT_Y, RIGHT_X, RIGHT_Y
|
||||
}
|
||||
|
||||
public enum DroneAxis {
|
||||
|
||||
FRONT_BACK, LEFT_RIGHT, UP_DOWN, ROTATE
|
||||
}
|
||||
private ControllerButton button;
|
||||
private Command command;
|
||||
private Animation anim;
|
||||
private LED led;
|
||||
private ControllerAxis controlAxis;
|
||||
private DroneAxis droneAxis;
|
||||
private float frequency;
|
||||
private int duration;
|
||||
private int delay;
|
||||
private String prefString;
|
||||
private static final VideoChannel[] VIDEO_CYCLE = {VideoChannel.HORIZONTAL_ONLY,
|
||||
VideoChannel.VERTICAL_ONLY, VideoChannel.VERTICAL_IN_HORIZONTAL, VideoChannel.HORIZONTAL_IN_VERTICAL};
|
||||
private int video_index = 0;
|
||||
private File recFile;
|
||||
|
||||
/**
|
||||
* Creates the control from a string that is stored in the java preferences of this app
|
||||
* @param prefString
|
||||
*/
|
||||
public AssignableControl(String prefString) {
|
||||
String[] strings = prefString.split("/");
|
||||
if (strings.length < 3) {
|
||||
throw new IllegalStateException("preference string malformed");
|
||||
}
|
||||
button = ControllerButton.valueOf(strings[0]);
|
||||
command = Command.valueOf(strings[1]);
|
||||
delay = Integer.parseInt(strings[2]);
|
||||
switch (command) {
|
||||
case PLAY_ANIMATION:
|
||||
anim = Animation.valueOf(strings[3]);
|
||||
duration = Integer.parseInt(strings[4]);
|
||||
break;
|
||||
case PLAY_LED:
|
||||
led = LED.valueOf(strings[3]);
|
||||
frequency = Float.parseFloat(strings[4]);
|
||||
duration = Integer.parseInt(strings[5]);
|
||||
break;
|
||||
case RECORD_VIDEO:
|
||||
case TAKE_SNAPSHOT:
|
||||
try {
|
||||
recFile = new File(strings[3].replace('?', File.separatorChar));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
this.prefString = prefString;
|
||||
}
|
||||
|
||||
public AssignableControl(ControllerButton button, LED led, int delay, float frequency, int duration) {
|
||||
this.command = Command.PLAY_LED;
|
||||
this.delay = delay;
|
||||
this.led = led;
|
||||
this.frequency = frequency;
|
||||
this.duration = duration;
|
||||
prefString = button.name() + "/" + command.name() + "/" + delay + "/" + led.name() + "/" + frequency + "/" + duration;
|
||||
}
|
||||
|
||||
public AssignableControl(ControllerButton button, Animation anim, int delay, int duration) {
|
||||
this.command = Command.PLAY_ANIMATION;
|
||||
this.delay = delay;
|
||||
this.anim = anim;
|
||||
this.duration = duration;
|
||||
prefString = button.name() + "/" + command.name() + "/" + delay + "/" + anim.name() + "/" + duration;
|
||||
}
|
||||
|
||||
public AssignableControl(ControllerButton button, Command command, int delay, File file) {
|
||||
this.command = command;
|
||||
this.delay = delay;
|
||||
this.recFile = file;
|
||||
prefString = button.name() + "/" + command.name() + "/" + delay + "/" + file.getPath().replace(File.separatorChar, '?');
|
||||
}
|
||||
|
||||
public AssignableControl(ControllerButton button, Command command, int delay) {
|
||||
this.command = command;
|
||||
this.delay = delay;
|
||||
prefString = button.name() + "/" + command.name() + "/" + delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the command to the supplied drone
|
||||
* @param drone
|
||||
* @throws IOException
|
||||
*/
|
||||
public void sendToDrone(final ARDrone drone) throws IOException {
|
||||
switch (command) {
|
||||
case PLAY_ANIMATION:
|
||||
drone.playAnimation(anim, duration);
|
||||
break;
|
||||
case PLAY_LED:
|
||||
drone.playLED(led, frequency, duration);
|
||||
break;
|
||||
case CLEAR_EMERGENCY:
|
||||
drone.clearEmergencySignal();
|
||||
break;
|
||||
case TRIM:
|
||||
drone.trim();
|
||||
break;
|
||||
case TAKEOFF:
|
||||
drone.takeOff();
|
||||
break;
|
||||
case LAND:
|
||||
drone.land();
|
||||
break;
|
||||
case RESET:
|
||||
drone.clearEmergencySignal();
|
||||
drone.trim();
|
||||
break;
|
||||
case VIDEO_CYCLE:
|
||||
cycleVideoChannel(drone);
|
||||
break;
|
||||
case FRONTAL_CAM:
|
||||
drone.selectVideoChannel(ARDrone.VideoChannel.VERTICAL_ONLY);
|
||||
break;
|
||||
case BOTTOM_CAM:
|
||||
drone.selectVideoChannel(ARDrone.VideoChannel.HORIZONTAL_ONLY);
|
||||
break;
|
||||
case BOTTOM_CAM_SMALL:
|
||||
drone.selectVideoChannel(ARDrone.VideoChannel.VERTICAL_IN_HORIZONTAL);
|
||||
break;
|
||||
case FRONTAL_CAM_SMALL:
|
||||
drone.selectVideoChannel(ARDrone.VideoChannel.HORIZONTAL_IN_VERTICAL);
|
||||
break;
|
||||
case TAKE_SNAPSHOT:
|
||||
|
||||
break;
|
||||
case RECORD_VIDEO:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used for VIDEO_CYCLE commands to cycle the video channel
|
||||
* @param drone
|
||||
* @throws IOException
|
||||
*/
|
||||
private void cycleVideoChannel(ARDrone drone) throws IOException {
|
||||
if (++video_index == VIDEO_CYCLE.length) {
|
||||
video_index = 0;
|
||||
}
|
||||
drone.selectVideoChannel(VIDEO_CYCLE[video_index]);
|
||||
}
|
||||
|
||||
public ControllerButton getButton() {
|
||||
return button;
|
||||
}
|
||||
|
||||
public Command getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public Animation getAnim() {
|
||||
return anim;
|
||||
}
|
||||
|
||||
public LED getLed() {
|
||||
return led;
|
||||
}
|
||||
|
||||
public ControllerAxis getControlAxis() {
|
||||
return controlAxis;
|
||||
}
|
||||
|
||||
public DroneAxis getDroneAxis() {
|
||||
return droneAxis;
|
||||
}
|
||||
|
||||
public float getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public int getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
public File getRecFile() {
|
||||
return recFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the complete data of this object as a string for storing into java preferences
|
||||
* @return
|
||||
*/
|
||||
public String getPrefString() {
|
||||
return prefString;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.codeminders.ardrone;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.codeminders.ardrone.AssignableControl.ControllerButton;
|
||||
|
||||
|
||||
public class ControlMap {
|
||||
|
||||
private HashMap<ControllerButton, List<AssignableControl>> map = new HashMap<ControllerButton, List<AssignableControl>>();
|
||||
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
|
||||
|
||||
public ControlMap() {
|
||||
loadMap();
|
||||
}
|
||||
|
||||
public synchronized void sendCommand(ARDrone drone, ControllerButton button) throws IOException {
|
||||
List<AssignableControl> commands = map.get(button);
|
||||
if (commands == null) {
|
||||
return;
|
||||
}
|
||||
for (Iterator<AssignableControl> it = commands.iterator(); it.hasNext();) {
|
||||
final AssignableControl assignableCommand = it.next();
|
||||
if (assignableCommand.getDelay() > 0) {
|
||||
delayCommand(assignableCommand, drone);
|
||||
} else {
|
||||
assignableCommand.sendToDrone(drone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a command for a drone with its assigned delay using an Executor
|
||||
* @param command
|
||||
* @param drone
|
||||
*/
|
||||
private void delayCommand(final AssignableControl command, final ARDrone drone) {
|
||||
exec.schedule(new Callable<Object>() {
|
||||
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
command.sendToDrone(drone);
|
||||
return null;
|
||||
}
|
||||
}, command.getDelay(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void loadMap() {
|
||||
map.put(ControllerButton.PS, new LinkedList<AssignableControl>());
|
||||
map.get(ControllerButton.PS).add(new AssignableControl(ControllerButton.PS, AssignableControl.Command.RESET, 0));
|
||||
|
||||
map.put(ControllerButton.START, new LinkedList<AssignableControl>());
|
||||
map.get(ControllerButton.START).add(new AssignableControl(ControllerButton.START, AssignableControl.Command.TAKEOFF, 0));
|
||||
|
||||
map.put(ControllerButton.SELECT, new LinkedList<AssignableControl>());
|
||||
map.get(ControllerButton.SELECT).add(new AssignableControl(ControllerButton.SELECT, AssignableControl.Command.LAND, 0));
|
||||
|
||||
map.put(ControllerButton.TRIANGLE, new LinkedList<AssignableControl>());
|
||||
map.get(ControllerButton.TRIANGLE).add(new AssignableControl(ControllerButton.TRIANGLE, AssignableControl.Command.VIDEO_CYCLE, 0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.codeminders.ardrone;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.codeminders.ardrone.AssignableControl.ControllerButton;
|
||||
import com.codeminders.ardrone.controller.PS3Controller;
|
||||
import com.codeminders.ardrone.controller.PS3ControllerState;
|
||||
import com.codeminders.ardrone.controller.PS3ControllerStateChange;
|
||||
|
||||
public class ControllerThread extends Thread{
|
||||
ARDrone drone;
|
||||
PS3Controller controller;
|
||||
private final ControlMap controlMap = new ControlMap();
|
||||
private static float CONTROL_THRESHOLD = 0.5f;
|
||||
private static final long READ_UPDATE_DELAY_MS = 5L;
|
||||
|
||||
private final AtomicBoolean flipSticks = new AtomicBoolean(false);
|
||||
|
||||
public ControllerThread(ARDrone drone, PS3Controller controller) {
|
||||
super();
|
||||
this.drone = drone;
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try
|
||||
{
|
||||
PS3ControllerState oldpad = null;
|
||||
while(true)
|
||||
{
|
||||
PS3ControllerState pad = controller.read();
|
||||
PS3ControllerStateChange pad_change = new PS3ControllerStateChange(oldpad, pad);
|
||||
oldpad = pad;
|
||||
|
||||
if(pad_change.isStartChanged() && pad_change.isStart())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.START);
|
||||
}
|
||||
if(pad_change.isSelectChanged() && pad_change.isSelect())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.SELECT);
|
||||
}
|
||||
if(pad_change.isPSChanged() && pad_change.isPS())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.PS);
|
||||
}
|
||||
if(pad_change.isTriangleChanged() && pad_change.isTriangle())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.TRIANGLE);
|
||||
}
|
||||
if(pad_change.isCrossChanged() && pad_change.isCross())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.CROSS);
|
||||
}
|
||||
if(pad_change.isSquareChanged() && pad_change.isSquare())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.SQUARE);
|
||||
}
|
||||
if(pad_change.isCircleChanged() && pad_change.isCircle())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.CIRCLE);
|
||||
}
|
||||
if(pad_change.isL1Changed() && pad_change.isL1())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.L1);
|
||||
}
|
||||
if(pad_change.isR1Changed() && pad_change.isR1())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.R1);
|
||||
}
|
||||
if(pad_change.isL2Changed() && pad_change.isL2())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.L2);
|
||||
}
|
||||
if(pad_change.isR2Changed() && pad_change.isR2())
|
||||
{
|
||||
controlMap.sendCommand(drone, ControllerButton.R2);
|
||||
}
|
||||
|
||||
int leftX = pad.getLeftJoystickX();
|
||||
int leftY = pad.getLeftJoystickY();
|
||||
|
||||
int rightX = pad.getRightJoystickX();
|
||||
int rightY = pad.getRightJoystickY();
|
||||
|
||||
float left_right_tilt = 0f;
|
||||
float front_back_tilt = 0f;
|
||||
float vertical_speed = 0f;
|
||||
float angular_speed = 0f;
|
||||
|
||||
if(Math.abs(((float) leftX) / 128f) > CONTROL_THRESHOLD)
|
||||
{
|
||||
left_right_tilt = ((float) leftX) / 128f;
|
||||
}
|
||||
|
||||
if(Math.abs(((float) leftY) / 128f) > CONTROL_THRESHOLD)
|
||||
{
|
||||
front_back_tilt = ((float) leftY) / 128f;
|
||||
}
|
||||
|
||||
if(Math.abs(((float) rightX) / 128f) > CONTROL_THRESHOLD)
|
||||
{
|
||||
angular_speed = ((float) rightX) / 128f;
|
||||
}
|
||||
|
||||
if(Math.abs(-1 * ((float) rightY) / 128f) > CONTROL_THRESHOLD)
|
||||
{
|
||||
vertical_speed = -1 * ((float) rightY) / 128f;
|
||||
}
|
||||
|
||||
if(left_right_tilt != 0 || front_back_tilt != 0 || vertical_speed != 0 || angular_speed != 0)
|
||||
{
|
||||
if(flipSticks.get())
|
||||
{
|
||||
drone.move(angular_speed, -1 * vertical_speed, -1 * front_back_tilt, left_right_tilt);
|
||||
}
|
||||
else
|
||||
{
|
||||
drone.move(left_right_tilt, front_back_tilt, vertical_speed, angular_speed);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
drone.hover();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Thread.sleep(READ_UPDATE_DELAY_MS);
|
||||
}
|
||||
catch(InterruptedException e)
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
try {
|
||||
drone.disconnect();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,11 +3,23 @@ package com.codeminders.ardrone;
|
||||
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.codeminders.ardrone.controller.PS3Controller;
|
||||
import com.codeminders.ardrone.controller.SonyPS3Controller;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
@@ -25,9 +37,54 @@ public class MainActivity extends Activity implements DroneVideoListener {
|
||||
ImageView display;
|
||||
TextView state;
|
||||
Button connectButton;
|
||||
PS3Controller controller;
|
||||
Button connectPs3Button;
|
||||
|
||||
UsbManager manager;
|
||||
|
||||
ControllerThread ctrThread;
|
||||
|
||||
private static final String ACTION_USB_PERMISSION = "com.access.device.USB_PERMISSION";
|
||||
|
||||
static MainActivity mainActivity;
|
||||
|
||||
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (ACTION_USB_PERMISSION.equals(action)) {
|
||||
synchronized (this) {
|
||||
UsbDevice deviceConnected = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
|
||||
|
||||
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
|
||||
|
||||
if (deviceConnected != null) {
|
||||
|
||||
if (SonyPS3Controller.isA(deviceConnected)) {
|
||||
try {
|
||||
controller = new SonyPS3Controller(deviceConnected, manager);
|
||||
connectPs3Button.setEnabled(false);
|
||||
connectPs3Button.setText("Connected");
|
||||
// Start joystic reading thread
|
||||
ctrThread = new ControllerThread(drone, controller);
|
||||
ctrThread.setName("Controll Thread");
|
||||
ctrThread.start();
|
||||
|
||||
} catch (Throwable e) {
|
||||
connectPs3Button.setText("Error");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
connectPs3Button.setText("Denied");
|
||||
connectPs3Button.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -52,9 +109,29 @@ public class MainActivity extends Activity implements DroneVideoListener {
|
||||
state.setText("Connecting...");
|
||||
(new DroneStarter()).execute(MainActivity.drone);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
connectPs3Button = (Button) findViewById(R.id.ps3Button);
|
||||
|
||||
|
||||
connectPs3Button.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
|
||||
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
|
||||
UsbDevice device = null;
|
||||
while (deviceIterator.hasNext()) {
|
||||
device = deviceIterator.next();
|
||||
break;
|
||||
}
|
||||
|
||||
if (null != device) {
|
||||
PendingIntent permissionIntent = PendingIntent.getBroadcast(mainActivity, 0, new Intent(ACTION_USB_PERMISSION), 0);
|
||||
IntentFilter permissionFilter = new IntentFilter(ACTION_USB_PERMISSION);
|
||||
mainActivity.registerReceiver(usbReceiver, permissionFilter);
|
||||
manager.requestPermission(device, permissionIntent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +274,6 @@ private class DroneStarter extends AsyncTask<ARDrone, Integer, Boolean> {
|
||||
drone.setCombinedYawMode(true);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
drone.clearEmergencySignal();
|
||||
drone.clearImageListeners();
|
||||
@@ -205,7 +281,6 @@ private class DroneStarter extends AsyncTask<ARDrone, Integer, Boolean> {
|
||||
drone.clearStatusChangeListeners();
|
||||
drone.disconnect();
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
package com.codeminders.ardrone.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import android.hardware.usb.UsbDevice;
|
||||
|
||||
|
||||
/**
|
||||
* Base abstract class for supported PS3-compatible USB controllers
|
||||
*
|
||||
* @author lord
|
||||
*
|
||||
*/
|
||||
public abstract class PS3Controller
|
||||
{
|
||||
UsbDevice dev;
|
||||
|
||||
|
||||
public abstract void close() throws IOException;
|
||||
|
||||
|
||||
public abstract PS3ControllerState read() throws IOException;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("PS3Controller [");
|
||||
builder.append("DeviceName=");
|
||||
builder.append(dev.getDeviceName());
|
||||
builder.append(", product=");
|
||||
builder.append(dev.getProductId());
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
|
||||
package com.codeminders.ardrone.controller;
|
||||
|
||||
/**
|
||||
* Data structure describing state of generic PS-3 compatible game controller.
|
||||
*
|
||||
* @author lord
|
||||
*/
|
||||
public class PS3ControllerState
|
||||
{
|
||||
// buttons with pictures
|
||||
protected boolean square;
|
||||
protected boolean cross;
|
||||
protected boolean circle;
|
||||
protected boolean triangle;
|
||||
|
||||
// Front-side buttons
|
||||
protected boolean L1;
|
||||
protected boolean R1;
|
||||
protected boolean L2;
|
||||
protected boolean R2;
|
||||
|
||||
// square small "select" button
|
||||
protected boolean select;
|
||||
// triangular small "start" button
|
||||
protected boolean start;
|
||||
|
||||
// Pressing on joysticks (button)
|
||||
protected boolean leftJoystickPress;
|
||||
protected boolean rightJoystickPress;
|
||||
|
||||
// PS3 button (sometimes labeled as Home on 3rd party models)
|
||||
protected boolean PS;
|
||||
|
||||
// Direction pad (hatswitch)
|
||||
protected int hatSwitchLeftRight;
|
||||
protected int hatSwitchUpDown;
|
||||
|
||||
// Analog joysticks
|
||||
|
||||
protected int leftJoystickX;
|
||||
protected int leftJoystickY;
|
||||
|
||||
protected int rightJoystickX;
|
||||
protected int rightJoystickY;
|
||||
|
||||
public PS3ControllerState(boolean square, boolean cross, boolean circle, boolean triangle, boolean l1, boolean r1,
|
||||
boolean l2, boolean r2, boolean select, boolean start, boolean leftJoystickPress,
|
||||
boolean rightJoystickPress, boolean pS, int hatSwitchLeftRight, int hatSwitchUpDown, int leftJoystickX,
|
||||
int leftJoystickY, int rightJoystickX, int rightJoystickY)
|
||||
{
|
||||
this.square = square;
|
||||
this.cross = cross;
|
||||
this.circle = circle;
|
||||
this.triangle = triangle;
|
||||
L1 = l1;
|
||||
R1 = r1;
|
||||
L2 = l2;
|
||||
R2 = r2;
|
||||
this.select = select;
|
||||
this.start = start;
|
||||
this.leftJoystickPress = leftJoystickPress;
|
||||
this.rightJoystickPress = rightJoystickPress;
|
||||
PS = pS;
|
||||
this.hatSwitchLeftRight = hatSwitchLeftRight;
|
||||
this.hatSwitchUpDown = hatSwitchUpDown;
|
||||
this.leftJoystickX = leftJoystickX;
|
||||
this.leftJoystickY = leftJoystickY;
|
||||
this.rightJoystickX = rightJoystickX;
|
||||
this.rightJoystickY = rightJoystickY;
|
||||
}
|
||||
|
||||
public PS3ControllerState(PS3ControllerState o)
|
||||
{
|
||||
this.square = o.square;
|
||||
this.cross = o.cross;
|
||||
this.circle = o.circle;
|
||||
this.triangle = o.triangle;
|
||||
L1 = o.L1;
|
||||
R1 = o.R1;
|
||||
L2 = o.L2;
|
||||
R2 = o.R2;
|
||||
this.select = o.select;
|
||||
this.start = o.start;
|
||||
this.leftJoystickPress = o.leftJoystickPress;
|
||||
this.rightJoystickPress = o.rightJoystickPress;
|
||||
PS = o.PS;
|
||||
this.hatSwitchLeftRight = o.hatSwitchLeftRight;
|
||||
this.hatSwitchUpDown = o.hatSwitchUpDown;
|
||||
this.leftJoystickX = o.leftJoystickX;
|
||||
this.leftJoystickY = o.leftJoystickY;
|
||||
this.rightJoystickX = o.rightJoystickX;
|
||||
this.rightJoystickY = o.rightJoystickY;
|
||||
|
||||
}
|
||||
|
||||
public PS3ControllerState()
|
||||
{
|
||||
}
|
||||
|
||||
public int getHatSwitchLeftRight()
|
||||
{
|
||||
return hatSwitchLeftRight;
|
||||
}
|
||||
|
||||
public int getHatSwitchUpDown()
|
||||
{
|
||||
return hatSwitchUpDown;
|
||||
}
|
||||
|
||||
public int getLeftJoystickX()
|
||||
{
|
||||
return leftJoystickX;
|
||||
}
|
||||
|
||||
public int getLeftJoystickY()
|
||||
{
|
||||
return leftJoystickY;
|
||||
}
|
||||
|
||||
public int getRightJoystickX()
|
||||
{
|
||||
return rightJoystickX;
|
||||
}
|
||||
|
||||
public int getRightJoystickY()
|
||||
{
|
||||
return rightJoystickY;
|
||||
}
|
||||
|
||||
public boolean isCircle()
|
||||
{
|
||||
return circle;
|
||||
}
|
||||
|
||||
public boolean isCross()
|
||||
{
|
||||
return cross;
|
||||
}
|
||||
|
||||
public boolean isL1()
|
||||
{
|
||||
return L1;
|
||||
}
|
||||
|
||||
public boolean isL2()
|
||||
{
|
||||
return L2;
|
||||
}
|
||||
|
||||
public boolean isLeftJoystickPress()
|
||||
{
|
||||
return leftJoystickPress;
|
||||
}
|
||||
|
||||
public boolean isPS()
|
||||
{
|
||||
return PS;
|
||||
}
|
||||
|
||||
public boolean isR1()
|
||||
{
|
||||
return R1;
|
||||
}
|
||||
|
||||
public boolean isR2()
|
||||
{
|
||||
return R2;
|
||||
}
|
||||
|
||||
public boolean isRightJoystickPress()
|
||||
{
|
||||
return rightJoystickPress;
|
||||
}
|
||||
|
||||
public boolean isSelect()
|
||||
{
|
||||
return select;
|
||||
}
|
||||
|
||||
public boolean isSquare()
|
||||
{
|
||||
return square;
|
||||
}
|
||||
|
||||
public boolean isStart()
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
public boolean isTriangle()
|
||||
{
|
||||
return triangle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("PS3ControllerState [square=");
|
||||
builder.append(square);
|
||||
builder.append(", cross=");
|
||||
builder.append(cross);
|
||||
builder.append(", circle=");
|
||||
builder.append(circle);
|
||||
builder.append(", triangle=");
|
||||
builder.append(triangle);
|
||||
builder.append(", L1=");
|
||||
builder.append(L1);
|
||||
builder.append(", R1=");
|
||||
builder.append(R1);
|
||||
builder.append(", L2=");
|
||||
builder.append(L2);
|
||||
builder.append(", R2=");
|
||||
builder.append(R2);
|
||||
builder.append(", select=");
|
||||
builder.append(select);
|
||||
builder.append(", start=");
|
||||
builder.append(start);
|
||||
builder.append(", rightJoystickPress=");
|
||||
builder.append(rightJoystickPress);
|
||||
builder.append(", leftJoystickPress=");
|
||||
builder.append(leftJoystickPress);
|
||||
builder.append(", PS=");
|
||||
builder.append(PS);
|
||||
builder.append(", hatSwitchLeftRight=");
|
||||
builder.append(hatSwitchLeftRight);
|
||||
builder.append(", hatSwitchUpDown=");
|
||||
builder.append(hatSwitchUpDown);
|
||||
builder.append(", leftJoystickX=");
|
||||
builder.append(leftJoystickX);
|
||||
builder.append(", leftJoystickY=");
|
||||
builder.append(leftJoystickY);
|
||||
builder.append(", rightJoystickX=");
|
||||
builder.append(rightJoystickX);
|
||||
builder.append(", rightJoystickY=");
|
||||
builder.append(rightJoystickY);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
|
||||
package com.codeminders.ardrone.controller;
|
||||
|
||||
public class PS3ControllerStateChange extends PS3ControllerState
|
||||
{
|
||||
protected boolean squareChanged;
|
||||
protected boolean crossChanged;
|
||||
protected boolean circleChanged;
|
||||
protected boolean triangleChanged;
|
||||
protected boolean L1Changed;
|
||||
protected boolean R1Changed;
|
||||
protected boolean L2Changed;
|
||||
protected boolean R2Changed;
|
||||
protected boolean selectChanged;
|
||||
protected boolean startChanged;
|
||||
protected boolean leftJoystickPressChanged;
|
||||
protected boolean rightJoystickPressChanged;
|
||||
protected boolean PSChanged;
|
||||
protected int hatSwitchLeftRightChange;
|
||||
protected int hatSwitchUpDownChange;
|
||||
protected int leftJoystickXChange;
|
||||
protected int leftJoystickYChange;
|
||||
protected int rightJoystickXChange;
|
||||
protected int rightJoystickYChange;
|
||||
|
||||
// composite change flags
|
||||
private boolean buttonStateChanged;
|
||||
private boolean hatChanged;
|
||||
private boolean leftJoystickChanged;
|
||||
private boolean rightJoystickChanged;
|
||||
private boolean joysticksChanged;
|
||||
private boolean changed;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param o Old state
|
||||
* @param n New state
|
||||
*/
|
||||
public PS3ControllerStateChange(PS3ControllerState o, PS3ControllerState n)
|
||||
{
|
||||
super(n);
|
||||
|
||||
if(o==null)
|
||||
o=n;
|
||||
|
||||
squareChanged = o.square != n.square;
|
||||
crossChanged = o.cross != n.cross;
|
||||
circleChanged = o.circle != n.circle;
|
||||
triangleChanged = o.triangle != n.triangle;
|
||||
L1Changed = o.L1 != n.L1;
|
||||
R1Changed = o.R1 != n.R1;
|
||||
L2Changed = o.L2 != n.L2;
|
||||
R2Changed = o.R2 != n.R2;
|
||||
selectChanged = o.select != n.select;
|
||||
startChanged = o.start != n.start;
|
||||
leftJoystickPressChanged = o.leftJoystickPress != n.leftJoystickPress;
|
||||
rightJoystickPressChanged = o.rightJoystickPress != n.rightJoystickPress;
|
||||
PSChanged = o.PS != n.PS;
|
||||
|
||||
hatSwitchLeftRightChange = n.hatSwitchLeftRight - o.hatSwitchLeftRight;
|
||||
hatSwitchUpDownChange = n.hatSwitchUpDown - o.hatSwitchUpDown;
|
||||
|
||||
leftJoystickXChange = n.leftJoystickX - o.leftJoystickX;
|
||||
leftJoystickYChange = n.leftJoystickY - o.leftJoystickY;
|
||||
rightJoystickXChange = n.rightJoystickX - o.rightJoystickX;
|
||||
rightJoystickYChange = n.rightJoystickY - o.rightJoystickY;
|
||||
|
||||
buttonStateChanged = squareChanged || crossChanged || circleChanged || triangleChanged || L1Changed
|
||||
|| R1Changed || L2Changed || R2Changed || selectChanged || startChanged || leftJoystickPressChanged
|
||||
|| rightJoystickPressChanged || PSChanged;
|
||||
|
||||
hatChanged = hatSwitchLeftRightChange != 0 || hatSwitchUpDownChange != 0;
|
||||
|
||||
leftJoystickChanged = leftJoystickXChange != 0 || leftJoystickYChange != 0;
|
||||
rightJoystickChanged = rightJoystickXChange != 0 || rightJoystickYChange != 0;
|
||||
|
||||
joysticksChanged = leftJoystickChanged || rightJoystickChanged;
|
||||
|
||||
changed = joysticksChanged || hatChanged || buttonStateChanged;
|
||||
|
||||
}
|
||||
|
||||
public int getHatSwitchLeftRightChange()
|
||||
{
|
||||
return hatSwitchLeftRightChange;
|
||||
}
|
||||
|
||||
public int getHatSwitchUpDownChange()
|
||||
{
|
||||
return hatSwitchUpDownChange;
|
||||
}
|
||||
|
||||
public int getLeftJoystickXChange()
|
||||
{
|
||||
return leftJoystickXChange;
|
||||
}
|
||||
|
||||
public int getLeftJoystickYChange()
|
||||
{
|
||||
return leftJoystickYChange;
|
||||
}
|
||||
|
||||
public int getRightJoystickXChange()
|
||||
{
|
||||
return rightJoystickXChange;
|
||||
}
|
||||
|
||||
public int getRightJoystickYChange()
|
||||
{
|
||||
return rightJoystickYChange;
|
||||
}
|
||||
|
||||
public boolean isButtonStateChanged()
|
||||
{
|
||||
return buttonStateChanged;
|
||||
}
|
||||
|
||||
public boolean isChanged()
|
||||
{
|
||||
return changed;
|
||||
}
|
||||
|
||||
public boolean isCircleChanged()
|
||||
{
|
||||
return circleChanged;
|
||||
}
|
||||
|
||||
public boolean isCrossChanged()
|
||||
{
|
||||
return crossChanged;
|
||||
}
|
||||
|
||||
public boolean isHatChanged()
|
||||
{
|
||||
return hatChanged;
|
||||
}
|
||||
|
||||
public boolean isJoysticksChanged()
|
||||
{
|
||||
return joysticksChanged;
|
||||
}
|
||||
|
||||
public boolean isL1Changed()
|
||||
{
|
||||
return L1Changed;
|
||||
}
|
||||
|
||||
public boolean isL2Changed()
|
||||
{
|
||||
return L2Changed;
|
||||
}
|
||||
|
||||
public boolean isLeftJoystickChanged()
|
||||
{
|
||||
return leftJoystickChanged;
|
||||
}
|
||||
|
||||
public boolean isLeftJoystickPressChanged()
|
||||
{
|
||||
return leftJoystickPressChanged;
|
||||
}
|
||||
|
||||
public boolean isPSChanged()
|
||||
{
|
||||
return PSChanged;
|
||||
}
|
||||
|
||||
public boolean isR1Changed()
|
||||
{
|
||||
return R1Changed;
|
||||
}
|
||||
|
||||
public boolean isR2Changed()
|
||||
{
|
||||
return R2Changed;
|
||||
}
|
||||
|
||||
public boolean isRightJoystickChanged()
|
||||
{
|
||||
return rightJoystickChanged;
|
||||
}
|
||||
|
||||
public boolean isRightJoystickPressChanged()
|
||||
{
|
||||
return rightJoystickPressChanged;
|
||||
}
|
||||
|
||||
public boolean isSelectChanged()
|
||||
{
|
||||
return selectChanged;
|
||||
}
|
||||
|
||||
public boolean isSquareChanged()
|
||||
{
|
||||
return squareChanged;
|
||||
}
|
||||
|
||||
public boolean isStartChanged()
|
||||
{
|
||||
return startChanged;
|
||||
}
|
||||
|
||||
public boolean isTriangleChanged()
|
||||
{
|
||||
return triangleChanged;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
|
||||
package com.codeminders.ardrone.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.BitSet;
|
||||
|
||||
import android.hardware.usb.UsbConstants;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbEndpoint;
|
||||
import android.hardware.usb.UsbInterface;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.hardware.usb.UsbRequest;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
||||
public class SonyPS3Controller extends PS3Controller
|
||||
{
|
||||
private static final int VENDOR_ID = 1356;
|
||||
private static final int PRODUCT_ID = 616;
|
||||
|
||||
int bufferSize = 0;
|
||||
ByteBuffer buffer;
|
||||
|
||||
UsbDeviceConnection readDataConnection = null;
|
||||
UsbEndpoint usbEndpointRead = null;
|
||||
UsbRequest request;
|
||||
UsbRequest requestQueued;
|
||||
|
||||
public static boolean isA(UsbDevice dev)
|
||||
{
|
||||
return(dev.getVendorId() == VENDOR_ID && dev.getProductId() == PRODUCT_ID);
|
||||
}
|
||||
|
||||
|
||||
public SonyPS3Controller(UsbDevice dev, UsbManager manager) throws IOException
|
||||
{
|
||||
this.dev = dev;
|
||||
readDataConnection = manager.openDevice(dev);
|
||||
if (null == readDataConnection) {
|
||||
throw new IOException("Failed to open connection to USB device");
|
||||
}
|
||||
UsbInterface usbInterfaceRead = dev.getInterface(0);
|
||||
readDataConnection.claimInterface(usbInterfaceRead, true);
|
||||
|
||||
for(int i = 0; i < usbInterfaceRead.getEndpointCount(); i++) {
|
||||
if (usbInterfaceRead.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) {
|
||||
usbEndpointRead = usbInterfaceRead.getEndpoint(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (null == usbEndpointRead) {
|
||||
throw new IOException("Failed to find usb read endpoint");
|
||||
}
|
||||
|
||||
bufferSize = usbEndpointRead.getMaxPacketSize();
|
||||
buffer = ByteBuffer.allocate(bufferSize + 1);
|
||||
request = new UsbRequest();
|
||||
request.initialize(readDataConnection, usbEndpointRead);
|
||||
}
|
||||
|
||||
private int joystickCoordConv(byte b)
|
||||
{
|
||||
int v = b < 0 ? b + 256 : b;
|
||||
return(v - 128);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PS3ControllerState read() throws IOException
|
||||
{
|
||||
|
||||
PS3ControllerState res = null;
|
||||
buffer.clear();
|
||||
request.queue(buffer, bufferSize);
|
||||
requestQueued = readDataConnection.requestWait();
|
||||
if (request.equals(requestQueued))
|
||||
{
|
||||
byte[] buf = new byte[bufferSize + 1];
|
||||
buffer.get(buf, 0, bufferSize);
|
||||
|
||||
BitSet bs = new BitSet(24);
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
if((1 & (buf[2] >> i)) == 1)
|
||||
bs.set(i);
|
||||
}
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
if((1 & (buf[3] >> i)) == 1)
|
||||
bs.set(8 + i);
|
||||
}
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
if((1 & (buf[4] >> i)) == 1)
|
||||
bs.set(16 + i);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
boolean select = bs.get(i++);
|
||||
boolean leftJoystickPress = bs.get(i++);
|
||||
boolean rightJoystickPress = bs.get(i++);
|
||||
boolean start = bs.get(i++);
|
||||
bs.get(i++);
|
||||
bs.get(i++);
|
||||
bs.get(i++);
|
||||
bs.get(i++);
|
||||
boolean L2 = bs.get(i++);
|
||||
boolean R2 = bs.get(i++);
|
||||
boolean R1 = bs.get(i++);
|
||||
boolean L1 = bs.get(i++);
|
||||
boolean triangle = bs.get(i++);
|
||||
boolean circle = bs.get(i++);
|
||||
boolean cross = bs.get(i++);
|
||||
boolean square = bs.get(i++);
|
||||
boolean PS = bs.get(i++);
|
||||
|
||||
int leftJoystickX = joystickCoordConv(buf[6]);
|
||||
int leftJoystickY = joystickCoordConv(buf[7]);
|
||||
int rightJoystickX = joystickCoordConv(buf[8]);
|
||||
int rightJoystickY = joystickCoordConv(buf[9]);
|
||||
|
||||
int hatSwitchLeftRight = 0;
|
||||
int hatSwitchUpDown = 0;
|
||||
|
||||
res = new PS3ControllerState(square, cross, circle, triangle, L1, R1, L2, R2, select, start,
|
||||
leftJoystickPress, rightJoystickPress, PS, hatSwitchLeftRight, hatSwitchUpDown, leftJoystickX,
|
||||
leftJoystickY, rightJoystickX, rightJoystickY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (null != readDataConnection) {
|
||||
readDataConnection.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Referência em uma Nova Issue
Bloquear um usuário