From 5cd670ef49b03cf0220ca42eab926683af139d01 Mon Sep 17 00:00:00 2001 From: James Cotton Date: Mon, 6 Aug 2012 08:32:07 -0500 Subject: [PATCH] AndroidGCS: Add a telemetry monitor to the action bar that shows the TX/RX data rate. Right now seem to have a bug when going into the same widget twice it crashes teh second time. --- androidgcs/res/layout/telemetry_stats.xml | 31 +++++++++++ androidgcs/res/menu/status_menu.xml | 8 ++- androidgcs/res/values/strings.xml | 2 + .../org/openpilot/androidgcs/Controller.java | 4 +- .../src/org/openpilot/androidgcs/Logger.java | 2 + .../openpilot/androidgcs/ObjectBrowser.java | 3 +- .../androidgcs/ObjectManagerActivity.java | 49 ++++++++++++++++- .../src/org/openpilot/androidgcs/PFD.java | 55 ++++++++++--------- 8 files changed, 122 insertions(+), 32 deletions(-) create mode 100644 androidgcs/res/layout/telemetry_stats.xml diff --git a/androidgcs/res/layout/telemetry_stats.xml b/androidgcs/res/layout/telemetry_stats.xml new file mode 100644 index 000000000..442609c1e --- /dev/null +++ b/androidgcs/res/layout/telemetry_stats.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/androidgcs/res/menu/status_menu.xml b/androidgcs/res/menu/status_menu.xml index 7e59b8445..b9865e891 100644 --- a/androidgcs/res/menu/status_menu.xml +++ b/androidgcs/res/menu/status_menu.xml @@ -1,5 +1,9 @@ - - + + + \ No newline at end of file diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 3e0b88b7d..18de8b766 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -30,4 +30,6 @@ Number of objects Number of bytes Alarms + TxRate: + RxRate: diff --git a/androidgcs/src/org/openpilot/androidgcs/Controller.java b/androidgcs/src/org/openpilot/androidgcs/Controller.java index baa61229b..b40e37f93 100644 --- a/androidgcs/src/org/openpilot/androidgcs/Controller.java +++ b/androidgcs/src/org/openpilot/androidgcs/Controller.java @@ -66,8 +66,8 @@ public class Controller extends ObjectManagerActivity { @Override void onOPConnected() { - Log.d(TAG, "onOPConnected()"); - + super.onOPConnected(); + // Subscribe to updates from ManualControlCommand and show the values for crude feedback UAVDataObject manualControl = (UAVDataObject) objMngr.getObject("ManualControlCommand"); if(manualControl != null) { diff --git a/androidgcs/src/org/openpilot/androidgcs/Logger.java b/androidgcs/src/org/openpilot/androidgcs/Logger.java index 6fedeb095..8ad3d20df 100644 --- a/androidgcs/src/org/openpilot/androidgcs/Logger.java +++ b/androidgcs/src/org/openpilot/androidgcs/Logger.java @@ -77,6 +77,8 @@ public class Logger extends ObjectManagerActivity { @Override void onOPConnected() { + super.onOPConnected(); + if (DEBUG) Log.d(TAG, "onOPConnected()"); onStartLogging(); registerObjectUpdates(objMngr.getObjects()); diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java index b27fef785..95aa34810 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -53,14 +53,15 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); setContentView(R.layout.object_browser); prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); + super.onCreate(savedInstanceState); } @Override void onOPConnected() { + super.onOPConnected(); Log.d(TAG, "onOPConnected()"); OnCheckedChangeListener checkListener = new OnCheckedChangeListener() { diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java index bfa76569f..a314cffdc 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java @@ -24,6 +24,7 @@ import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; +import android.widget.TextView; public abstract class ObjectManagerActivity extends Activity { @@ -42,7 +43,9 @@ public abstract class ObjectManagerActivity extends Activity { LocalBinder binder; //! Store the broadcast receiver to unregister it BroadcastReceiver connectedReceiver; - + //! Indicate if this activity has already connected it's telemetry callbacks + private boolean telemetryStatsConnected = false; + /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { @@ -118,19 +121,60 @@ public abstract class ObjectManagerActivity extends Activity { } } + private void updateStats() { + UAVObject stats = objMngr.getObject("GCSTelemetryStats"); + TextView rxRate = (TextView) findViewById(R.id.telemetry_stats_rx_rate); + TextView txRate = (TextView) findViewById(R.id.telemetry_stats_tx_rate); + if (rxRate != null) + rxRate.setText(Integer.valueOf((int) stats.getField("RxDataRate").getDouble()).toString()); + if (rxRate != null) + txRate.setText(Integer.valueOf((int) stats.getField("TxDataRate").getDouble()).toString()); + + } + + final Observer telemetryObserver = new Observer() { + public void update(Observable observable, Object data) { + uavobjHandler.post(new Runnable() { + @Override + public void run() { + updateStats(); + } + }); + } + }; + /** * Called when either the telemetry establishes a connection or * if it already has on creation of this activity + * + * This should be called by all inherited classes if they want the telemetry bar etc */ void onOPConnected() { + if ( telemetryStatsConnected ) + return; + // We are not using the objectUpdated mechanism in place so that all the children + // don't have to sort through the messages. + UAVObject stats = objMngr.getObject("GCSTelemetryStats"); + if (stats == null) + return; + + stats.addUpdatedObserver(telemetryObserver); + telemetryStatsConnected = true; + updateStats(); } /** * Called when telemetry drops the connection + * + * This should be called by all inherited classes if they want the telemetry bar etc */ void onOPDisconnected() { - + // Indicate no connection + TextView rxRate = (TextView) findViewById(R.id.telemetry_stats_rx_rate); + TextView txRate = (TextView) findViewById(R.id.telemetry_stats_tx_rate); + rxRate.setText(""); + txRate.setText(""); } @Override @@ -154,6 +198,7 @@ public abstract class ObjectManagerActivity extends Activity { @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.status_menu, menu); inflater.inflate(R.menu.options_menu, menu); return true; } diff --git a/androidgcs/src/org/openpilot/androidgcs/PFD.java b/androidgcs/src/org/openpilot/androidgcs/PFD.java index e0d1b9f24..654e6d695 100644 --- a/androidgcs/src/org/openpilot/androidgcs/PFD.java +++ b/androidgcs/src/org/openpilot/androidgcs/PFD.java @@ -1,31 +1,42 @@ 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 { + final long MIN_UPDATE_PERIOD = 50; + long lastUpdateMs; 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(); + /** + * Update the UI whenever the attitude is updated + */ + protected void objectUpdated(UAVObject obj) { + // Throttle the UI redraws. Eventually this should maybe come from a periodic task + if ((System.currentTimeMillis() - lastUpdateMs) < MIN_UPDATE_PERIOD) + return; + if (obj.getName().compareTo("AttitudeActual") != 0) + return; - AttitudeView attitude = (AttitudeView) findViewById(R.id.attitude_view); - attitude.setRoll(roll / 180 * Math.PI); - attitude.setPitch(pitch / 180 * Math.PI); - attitude.invalidate(); - } - }; + lastUpdateMs = System.currentTimeMillis(); + + heading = obj.getField("Yaw").getDouble(); + pitch = obj.getField("Pitch").getDouble(); + roll = obj.getField("Roll").getDouble(); + + 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) { @@ -35,17 +46,11 @@ public class PFD extends ObjectManagerActivity { @Override void onOPConnected() { + super.onOPConnected(); + // Connect the update method to AttitudeActual 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); - } - }); + if (obj != null) + registerObjectUpdates(obj); } }