From bee57409835e2faea5b4f28bb8e3ef4d0a612ff8 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Tue, 22 Mar 2011 12:59:01 -0500 Subject: [PATCH] Added a simple PFD --- androidgcs/AndroidManifest.xml | 9 +- androidgcs/res/drawable-hdpi/browser_icon.png | Bin 0 -> 456 bytes androidgcs/res/drawable-ldpi/browser_icon.png | Bin 0 -> 456 bytes androidgcs/res/drawable-mdpi/browser_icon.png | Bin 0 -> 456 bytes androidgcs/res/layout/gcs_home.xml | 9 +- androidgcs/res/layout/pfd.xml | 8 + androidgcs/res/values/colors.xml | 6 + androidgcs/res/values/strings.xml | 6 + .../openpilot/androidgcs/AttitudeView.java | 89 +++++++++++ .../org/openpilot/androidgcs/CompassView.java | 139 ++++++++++++++++++ .../org/openpilot/androidgcs/HomePage.java | 9 ++ .../src/org/openpilot/androidgcs/PFD.java | 51 +++++++ 12 files changed, 318 insertions(+), 8 deletions(-) create mode 100644 androidgcs/res/drawable-hdpi/browser_icon.png create mode 100644 androidgcs/res/drawable-ldpi/browser_icon.png create mode 100644 androidgcs/res/drawable-mdpi/browser_icon.png create mode 100644 androidgcs/res/layout/pfd.xml create mode 100644 androidgcs/res/values/colors.xml create mode 100644 androidgcs/src/org/openpilot/androidgcs/AttitudeView.java create mode 100644 androidgcs/src/org/openpilot/androidgcs/CompassView.java create mode 100644 androidgcs/src/org/openpilot/androidgcs/PFD.java diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index fe8c6ae9a..1942146c4 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -18,13 +18,8 @@ - - - - - - - + + diff --git a/androidgcs/res/drawable-hdpi/browser_icon.png b/androidgcs/res/drawable-hdpi/browser_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3fcee485245922172e66bad2eb2203db14cdac39 GIT binary patch literal 456 zcmV;(0XP1MP)2!duSV%belNQ;||iLJSe+;1>Z9S#NM0kJ-$^wmm*RY+To8 zv9OU+Vp%S#Dwxlg2qCa-7b$%#%SVV+t!?|?eYIMiWKtswJ$f(3w;l5V%m%S&OW63?^9=i}S!{|oRH^?GKj631~Um0~;V0=*5_l}PE6%PFYp yZavDW{)W@(8>Xp~%_jEdoebdExV#6+x#JU=$8dKofqu*Y00002!duSV%belNQ;||iLJSe+;1>Z9S#NM0kJ-$^wmm*RY+To8 zv9OU+Vp%S#Dwxlg2qCa-7b$%#%SVV+t!?|?eYIMiWKtswJ$f(3w;l5V%m%S&OW63?^9=i}S!{|oRH^?GKj631~Um0~;V0=*5_l}PE6%PFYp yZavDW{)W@(8>Xp~%_jEdoebdExV#6+x#JU=$8dKofqu*Y00002!duSV%belNQ;||iLJSe+;1>Z9S#NM0kJ-$^wmm*RY+To8 zv9OU+Vp%S#Dwxlg2qCa-7b$%#%SVV+t!?|?eYIMiWKtswJ$f(3w;l5V%m%S&OW63?^9=i}S!{|oRH^?GKj631~Um0~;V0=*5_l}PE6%PFYp yZavDW{)W@(8>Xp~%_jEdoebdExV#6+x#JU=$8dKofqu*Y0000 - + diff --git a/androidgcs/res/layout/pfd.xml b/androidgcs/res/layout/pfd.xml new file mode 100644 index 000000000..191a80eb9 --- /dev/null +++ b/androidgcs/res/layout/pfd.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/androidgcs/res/values/colors.xml b/androidgcs/res/values/colors.xml new file mode 100644 index 000000000..dc8eaf315 --- /dev/null +++ b/androidgcs/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #F555 + #AFFF + #AFFF + diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index e9b66a312..3b3a38d02 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -2,6 +2,7 @@ OpenPilot GCS Home OpenPilot Object Browser + OpenPilot PFD Settings Connect Disconnect @@ -10,4 +11,9 @@ Connection Type Bluetooth Select the connection method + Compass + N + E + S + W diff --git a/androidgcs/src/org/openpilot/androidgcs/AttitudeView.java b/androidgcs/src/org/openpilot/androidgcs/AttitudeView.java new file mode 100644 index 000000000..24a8bf5f0 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/AttitudeView.java @@ -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); + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/CompassView.java b/androidgcs/src/org/openpilot/androidgcs/CompassView.java new file mode 100644 index 000000000..50e4abc0a --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/CompassView.java @@ -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(); + } +} diff --git a/androidgcs/src/org/openpilot/androidgcs/HomePage.java b/androidgcs/src/org/openpilot/androidgcs/HomePage.java index 478c7cdca..7d03e1b04 100644 --- a/androidgcs/src/org/openpilot/androidgcs/HomePage.java +++ b/androidgcs/src/org/openpilot/androidgcs/HomePage.java @@ -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)); + } + }); + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/PFD.java b/androidgcs/src/org/openpilot/androidgcs/PFD.java new file mode 100644 index 000000000..e0d1b9f24 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/PFD.java @@ -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); + } + }); + } +}