mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-12-01 09:24:10 +01:00
Added a simple PFD
This commit is contained in:
parent
fd3a02eb92
commit
bee5740983
@ -18,13 +18,8 @@
|
||||
</activity>
|
||||
|
||||
|
||||
<activity android:name="ObjectBrowser" android:label="@string/object_browser_name">
|
||||
<intent-filter>
|
||||
<action android:name="org.openpilot.intent.action.CONNECTED" />
|
||||
<action android:name="org.openpilot.intent.action.DISCONNECTED" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="ObjectBrowser" android:label="@string/object_browser_name" />
|
||||
<activity android:name="PFD" android:label="PFD"/>
|
||||
<activity android:name="Preferences" android:label="@string/preference_title"/>
|
||||
<activity android:name="ObjectEditor" android:label="ObjectEditor" android:theme="@android:style/Theme.Dialog"/>
|
||||
|
||||
|
BIN
androidgcs/res/drawable-hdpi/browser_icon.png
Normal file
BIN
androidgcs/res/drawable-hdpi/browser_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 456 B |
BIN
androidgcs/res/drawable-ldpi/browser_icon.png
Normal file
BIN
androidgcs/res/drawable-ldpi/browser_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 456 B |
BIN
androidgcs/res/drawable-mdpi/browser_icon.png
Normal file
BIN
androidgcs/res/drawable-mdpi/browser_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 456 B |
@ -3,5 +3,12 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<Button android:layout_alignParentTop="true" android:layout_height="wrap_content" android:text="@string/object_browser_name" android:layout_width="wrap_content" android:id="@+id/launch_object_browser"></Button>
|
||||
<Button
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/object_browser_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/launch_object_browser"
|
||||
android:drawableLeft="@drawable/browser_icon" android:layout_centerHorizontal="true"/>
|
||||
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/pfd_name" android:id="@+id/launch_pfd" android:drawableLeft="@drawable/browser_icon" android:layout_below="@+id/launch_object_browser" android:layout_alignLeft="@+id/launch_object_browser" android:layout_alignRight="@+id/launch_object_browser"></Button>
|
||||
</RelativeLayout>
|
||||
|
8
androidgcs/res/layout/pfd.xml
Normal file
8
androidgcs/res/layout/pfd.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<org.openpilot.androidgcs.CompassView android:id="@+id/compass_view" android:layout_height="wrap_content" android:layout_width="wrap_content"></org.openpilot.androidgcs.CompassView>
|
||||
<org.openpilot.androidgcs.AttitudeView android:id="@+id/attitude_view" android:layout_height="fill_parent" android:layout_width="fill_parent"></org.openpilot.androidgcs.AttitudeView>
|
||||
</LinearLayout>
|
6
androidgcs/res/values/colors.xml
Normal file
6
androidgcs/res/values/colors.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="background_color">#F555</color>
|
||||
<color name="marker_color">#AFFF</color>
|
||||
<color name="text_color">#AFFF</color>
|
||||
</resources>
|
@ -2,6 +2,7 @@
|
||||
<resources>
|
||||
<string name="app_name">OpenPilot GCS Home</string>
|
||||
<string name="object_browser_name">OpenPilot Object Browser</string>
|
||||
<string name="pfd_name">OpenPilot PFD</string>
|
||||
<string name="menu_item_settings">Settings</string>
|
||||
<string name="menu_item_connect">Connect</string>
|
||||
<string name="menu_item_disconnect">Disconnect</string>
|
||||
@ -10,4 +11,9 @@
|
||||
<string name="preference_checkbox_connection_type">Connection Type</string>
|
||||
<string name="preference_checkbox_bluetooth">Bluetooth</string>
|
||||
<string name="preference_connection_method_summary">Select the connection method</string>
|
||||
<string name="compass_name">Compass</string>
|
||||
<string name="cardinal_north">N</string>
|
||||
<string name="cardinal_east">E</string>
|
||||
<string name="cardinal_south">S</string>
|
||||
<string name="cardinal_west">W</string>
|
||||
</resources>
|
||||
|
89
androidgcs/src/org/openpilot/androidgcs/AttitudeView.java
Normal file
89
androidgcs/src/org/openpilot/androidgcs/AttitudeView.java
Normal file
@ -0,0 +1,89 @@
|
||||
package org.openpilot.androidgcs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
public class AttitudeView extends View {
|
||||
|
||||
public AttitudeView(Context context) {
|
||||
super(context);
|
||||
initAttitudeView();
|
||||
}
|
||||
|
||||
public AttitudeView(Context context, AttributeSet ats, int defaultStyle) {
|
||||
super(context, ats, defaultStyle);
|
||||
initAttitudeView();
|
||||
}
|
||||
|
||||
public AttitudeView(Context context, AttributeSet ats) {
|
||||
super(context, ats);
|
||||
initAttitudeView();
|
||||
}
|
||||
|
||||
protected void initAttitudeView() {
|
||||
setFocusable(true);
|
||||
|
||||
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
circlePaint.setColor(R.color.background_color);
|
||||
circlePaint.setStrokeWidth(1);
|
||||
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
Resources r = this.getResources();
|
||||
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
textPaint.setColor(r.getColor(R.color.text_color));
|
||||
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
markerPaint.setColor(r.getColor(R.color.marker_color));
|
||||
}
|
||||
|
||||
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int measuredWidth = measure(widthMeasureSpec);
|
||||
int measuredHeight = measure(heightMeasureSpec);
|
||||
int d = Math.min(measuredWidth, measuredHeight);
|
||||
setMeasuredDimension(d/2, d/2);
|
||||
}
|
||||
|
||||
private int measure(int measureSpec) {
|
||||
int result = 0;
|
||||
// Decode the measurement specifications.
|
||||
|
||||
int specMode = MeasureSpec.getMode(measureSpec);
|
||||
int specSize = MeasureSpec.getSize(measureSpec);
|
||||
|
||||
if (specMode == MeasureSpec.UNSPECIFIED) { // Return a default size of 200 if no bounds are specified.
|
||||
result = 200;
|
||||
} else {
|
||||
// As you want to fill the available space
|
||||
// always return the full available bounds.
|
||||
result = specSize;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private double roll;
|
||||
public void setRoll(double roll) {
|
||||
this.roll = roll;
|
||||
}
|
||||
private double pitch;
|
||||
public void setPitch(double d) {
|
||||
this.pitch = d;
|
||||
}
|
||||
|
||||
// Drawing related code
|
||||
private Paint markerPaint;
|
||||
private Paint textPaint;
|
||||
private Paint circlePaint;
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
int px = getMeasuredWidth() / 2;
|
||||
int py = getMeasuredHeight() /2 ;
|
||||
int radius = Math.min(px, py);
|
||||
|
||||
canvas.drawLine(px,py, (int) (px+radius * Math.cos(roll)), (int) (py + radius * Math.sin(roll)), markerPaint);
|
||||
canvas.drawLine(px,py, (int) (px+radius * Math.cos(pitch)), (int) (py + radius * Math.sin(pitch)), markerPaint);
|
||||
}
|
||||
|
||||
}
|
139
androidgcs/src/org/openpilot/androidgcs/CompassView.java
Normal file
139
androidgcs/src/org/openpilot/androidgcs/CompassView.java
Normal file
@ -0,0 +1,139 @@
|
||||
package org.openpilot.androidgcs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
public class CompassView extends View {
|
||||
|
||||
public CompassView(Context context) {
|
||||
super(context);
|
||||
initCompassView();
|
||||
}
|
||||
|
||||
public CompassView(Context context, AttributeSet ats, int defaultStyle) {
|
||||
super(context, ats, defaultStyle);
|
||||
initCompassView();
|
||||
}
|
||||
|
||||
public CompassView(Context context, AttributeSet ats) {
|
||||
super(context, ats);
|
||||
initCompassView();
|
||||
}
|
||||
|
||||
protected void initCompassView() {
|
||||
setFocusable(true);
|
||||
|
||||
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
circlePaint.setColor(R.color.background_color);
|
||||
circlePaint.setStrokeWidth(1);
|
||||
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
Resources r = this.getResources();
|
||||
northString = r.getString(R.string.cardinal_north);
|
||||
eastString = r.getString(R.string.cardinal_east);
|
||||
southString = r.getString(R.string.cardinal_south);
|
||||
westString = r.getString(R.string.cardinal_west);
|
||||
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
textPaint.setColor(r.getColor(R.color.text_color));
|
||||
textHeight = (int)textPaint.measureText("yY");
|
||||
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
markerPaint.setColor(r.getColor(R.color.marker_color));
|
||||
}
|
||||
|
||||
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int measuredWidth = measure(widthMeasureSpec);
|
||||
int measuredHeight = measure(heightMeasureSpec);
|
||||
int d = Math.min(measuredWidth, measuredHeight);
|
||||
setMeasuredDimension(d/2, d/2);
|
||||
}
|
||||
|
||||
private int measure(int measureSpec) {
|
||||
int result = 0;
|
||||
// Decode the measurement specifications.
|
||||
|
||||
int specMode = MeasureSpec.getMode(measureSpec);
|
||||
int specSize = MeasureSpec.getSize(measureSpec);
|
||||
|
||||
if (specMode == MeasureSpec.UNSPECIFIED) { // Return a default size of 200 if no bounds are specified.
|
||||
result = 200;
|
||||
} else {
|
||||
// As you want to fill the available space
|
||||
// always return the full available bounds.
|
||||
result = specSize;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private double bearing;
|
||||
public void setBearing(double bearing) {
|
||||
this.bearing = bearing;
|
||||
}
|
||||
|
||||
// Drawing related code
|
||||
private Paint markerPaint;
|
||||
private Paint textPaint;
|
||||
private Paint circlePaint;
|
||||
private String northString;
|
||||
private String eastString;
|
||||
private String southString;
|
||||
private String westString;
|
||||
private int textHeight;
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
int px = getMeasuredWidth() / 2;
|
||||
int py = getMeasuredHeight() /2 ;
|
||||
int radius = Math.min(px, py);
|
||||
// Draw the background
|
||||
canvas.drawCircle(px, py, radius, circlePaint);
|
||||
|
||||
// Rotate our perspective so that the ÔtopÕ is
|
||||
// facing the current bearing.
|
||||
canvas.save();
|
||||
canvas.rotate((float) -bearing, px, py);
|
||||
|
||||
int textWidth = (int)textPaint.measureText("W");
|
||||
int cardinalX = px-textWidth/2;
|
||||
int cardinalY = py-radius+textHeight;
|
||||
|
||||
// Draw the marker every 15 degrees and text every 45.
|
||||
for (int i = 0; i < 24; i++) {
|
||||
// Draw a marker.
|
||||
canvas.drawLine(px, py-radius, px, py-radius+10, markerPaint);
|
||||
canvas.save();
|
||||
canvas.translate(0, textHeight);
|
||||
// Draw the cardinal points
|
||||
if (i % 6 == 0) {
|
||||
String dirString = null;
|
||||
switch (i) {
|
||||
case 0 : {
|
||||
dirString = northString;
|
||||
int arrowY = 2*textHeight;
|
||||
canvas.drawLine(px, arrowY, px-5, 3*textHeight, markerPaint);
|
||||
canvas.drawLine(px, arrowY, px+5, 3*textHeight, markerPaint);
|
||||
break;
|
||||
}
|
||||
case 6: dirString = eastString; break;
|
||||
case 12: dirString = southString; break;
|
||||
case 18: dirString = westString; break;
|
||||
}
|
||||
canvas.drawText(dirString, cardinalX, cardinalY, textPaint);
|
||||
}
|
||||
else if (i % 3 == 0) {
|
||||
// Draw the text every alternate 45deg
|
||||
String angle = String.valueOf(i*15);
|
||||
float angleTextWidth = textPaint.measureText(angle);
|
||||
|
||||
int angleTextX = (int)(px-angleTextWidth/2);
|
||||
int angleTextY = py-radius+textHeight;
|
||||
canvas.drawText(angle, angleTextX, angleTextY, textPaint);
|
||||
}
|
||||
canvas.restore();
|
||||
canvas.rotate(15, px, py);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
@ -12,12 +12,21 @@ public class HomePage extends ObjectManagerActivity {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.gcs_home);
|
||||
|
||||
Button objectBrowser = (Button) findViewById(R.id.launch_object_browser);
|
||||
objectBrowser.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View arg0) {
|
||||
startActivity(new Intent(HomePage.this, ObjectBrowser.class));
|
||||
}
|
||||
});
|
||||
|
||||
Button pfd = (Button) findViewById(R.id.launch_pfd);
|
||||
pfd.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View arg0) {
|
||||
startActivity(new Intent(HomePage.this, PFD.class));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
51
androidgcs/src/org/openpilot/androidgcs/PFD.java
Normal file
51
androidgcs/src/org/openpilot/androidgcs/PFD.java
Normal file
@ -0,0 +1,51 @@
|
||||
package org.openpilot.androidgcs;
|
||||
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
import org.openpilot.uavtalk.UAVDataObject;
|
||||
import org.openpilot.uavtalk.UAVObject;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
public class PFD extends ObjectManagerActivity {
|
||||
|
||||
double heading;
|
||||
double roll;
|
||||
double pitch;
|
||||
|
||||
Runnable update = new Runnable() {
|
||||
public void run() {
|
||||
CompassView compass = (CompassView) findViewById(R.id.compass_view);
|
||||
compass.setBearing((int) heading);
|
||||
compass.invalidate();
|
||||
|
||||
AttitudeView attitude = (AttitudeView) findViewById(R.id.attitude_view);
|
||||
attitude.setRoll(roll / 180 * Math.PI);
|
||||
attitude.setPitch(pitch / 180 * Math.PI);
|
||||
attitude.invalidate();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.pfd);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onOPConnected() {
|
||||
|
||||
UAVObject obj = objMngr.getObject("AttitudeActual");
|
||||
if(obj != null)
|
||||
obj.addUpdatedObserver(new Observer() {
|
||||
public void update(Observable observable, Object data) {
|
||||
UAVDataObject obj = (UAVDataObject) data;
|
||||
heading = obj.getField("Yaw").getDouble();
|
||||
pitch = obj.getField("Pitch").getDouble();
|
||||
roll = obj.getField("Roll").getDouble();
|
||||
runOnUiThread(update);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user