1
0
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:
James Cotton 2011-03-22 12:59:01 -05:00
parent fd3a02eb92
commit bee5740983
12 changed files with 318 additions and 8 deletions

View File

@ -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"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

View File

@ -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>

View 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>

View 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>

View File

@ -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>

View 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);
}
}

View 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();
}
}

View File

@ -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));
}
});
}
}

View 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);
}
});
}
}