From: Keith Packard Date: Mon, 15 Apr 2013 03:02:10 +0000 (-0700) Subject: Merge branch 'master' into droid-gps X-Git-Tag: altosdroid_v1.2-1~9^2~13 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=c6f85cb149dff8732104521cb62b355e8a0d7148;hp=58dd4b88fe738e005a13dfd69651853ea7f79205 Merge branch 'master' into droid-gps --- diff --git a/altosdroid/res/layout/altosdroid.xml b/altosdroid/res/layout/altosdroid.xml index 364f6ba6..71b7ad05 100644 --- a/altosdroid/res/layout/altosdroid.xml +++ b/altosdroid/res/layout/altosdroid.xml @@ -47,7 +47,7 @@ android:layout_height="wrap_content" android:layout_below="@+id/callsign_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> diff --git a/altosdroid/res/layout/tab_ascent.xml b/altosdroid/res/layout/tab_ascent.xml index b7e97086..d2d721e1 100644 --- a/altosdroid/res/layout/tab_ascent.xml +++ b/altosdroid/res/layout/tab_ascent.xml @@ -47,7 +47,7 @@ android:layout_alignParentRight="true" android:layout_below="@id/height_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -99,7 +99,7 @@ android:layout_alignParentRight="true" android:layout_below="@id/speed_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -151,7 +151,7 @@ android:layout_alignParentRight="true" android:layout_below="@id/accel_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -194,7 +194,7 @@ android:layout_alignParentRight="true" android:layout_below="@id/lat_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> \ No newline at end of file diff --git a/altosdroid/res/layout/tab_descent.xml b/altosdroid/res/layout/tab_descent.xml index 4b62acf9..56e8a00a 100644 --- a/altosdroid/res/layout/tab_descent.xml +++ b/altosdroid/res/layout/tab_descent.xml @@ -46,7 +46,7 @@ android:layout_alignParentRight="true" android:layout_below="@id/speed_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -99,7 +99,7 @@ android:layout_alignParentRight="true" android:layout_below="@id/elevation_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -152,7 +152,7 @@ android:layout_alignParentRight="true" android:layout_below="@id/bearing_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -205,7 +205,7 @@ android:layout_alignParentRight="true" android:layout_below="@id/distance_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> diff --git a/altosdroid/res/layout/tab_landed.xml b/altosdroid/res/layout/tab_landed.xml index b5c8d8c2..f27baa9e 100644 --- a/altosdroid/res/layout/tab_landed.xml +++ b/altosdroid/res/layout/tab_landed.xml @@ -37,7 +37,7 @@ android:layout_alignParentRight="true" android:layout_below="@+id/bearing_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:text="@string/target_latitude_label" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:text="@string/target_longitude_label" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + + + + + + + + + + + + + + + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> \ No newline at end of file diff --git a/altosdroid/res/layout/tab_map.xml b/altosdroid/res/layout/tab_map.xml index b9f4e69e..f611ae48 100644 --- a/altosdroid/res/layout/tab_map.xml +++ b/altosdroid/res/layout/tab_map.xml @@ -46,16 +46,16 @@ android:id="@+id/distance_label" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:paddingRight="4dp" android:text="@string/distance_label" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -96,19 +96,19 @@ android:paddingTop="5dp" > + android:paddingRight="4dp" + android:text="@string/target_latitude_label" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:paddingRight="4dp" + android:text="@string/target_longitude_label" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/altosdroid/res/layout/tab_pad.xml b/altosdroid/res/layout/tab_pad.xml index f5ec46b5..a21f9bbb 100644 --- a/altosdroid/res/layout/tab_pad.xml +++ b/altosdroid/res/layout/tab_pad.xml @@ -55,7 +55,7 @@ android:layout_below="@id/battery_voltage_label" android:layout_toRightOf="@id/battery_greenled" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -265,10 +266,9 @@ android:id="@+id/pad_lat_value" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_below="@id/pad_lat_label" - android:layout_toRightOf="@id/gps_ready_greenled" + android:layout_toRightOf="@id/pad_lat_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -288,10 +289,9 @@ android:id="@+id/pad_lon_value" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_below="@id/pad_lon_label" - android:layout_toRightOf="@id/gps_ready_greenled" + android:layout_toRightOf="@id/pad_lon_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -311,10 +312,9 @@ android:id="@+id/pad_alt_value" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_below="@id/pad_alt_label" - android:layout_toRightOf="@id/gps_ready_greenled" + android:layout_toRightOf="@id/pad_alt_label" android:text="" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> \ No newline at end of file diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 639611c2..90da617b 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -72,8 +72,12 @@ GPS Ready Latitude Longitude - Pad Latitude - Pad Longitude - Pad Altitude + Tar Lat + Tar Lon + My Lat + My Lon + Pad Lat + Pad Lon + Pad Alt diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index c9ce46a0..5ce6f810 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -47,6 +47,7 @@ import android.widget.TabHost; import android.widget.TextView; import android.widget.Toast; import android.app.AlertDialog; +import android.location.Location; import org.altusmetrum.altoslib_1.*; @@ -59,6 +60,8 @@ public class AltosDroid extends FragmentActivity { public static final int MSG_STATE_CHANGE = 1; public static final int MSG_TELEMETRY = 2; public static final int MSG_UPDATE_AGE = 3; + public static final int MSG_LOCATION = 4; + public static final int MSG_CRC_ERROR = 5; // Intent request codes private static final int REQUEST_CONNECT_DEVICE = 1; @@ -87,6 +90,7 @@ public class AltosDroid extends FragmentActivity { // Timer and Saved flight state for Age calculation private Timer timer = new Timer(); AltosState saved_state; + Location saved_location; // Service private boolean mIsBound = false; @@ -122,7 +126,6 @@ public class AltosDroid extends FragmentActivity { ad.mTitle.setText(R.string.title_connected_to); ad.mTitle.append(str); Toast.makeText(ad.getApplicationContext(), "Connected to " + str, Toast.LENGTH_SHORT).show(); - ad.mAltosVoice.speak("Connected"); break; case TelemetryService.STATE_CONNECTING: ad.mTitle.setText(R.string.title_connecting); @@ -137,6 +140,10 @@ public class AltosDroid extends FragmentActivity { case MSG_TELEMETRY: ad.update_ui((AltosState) msg.obj); break; + case MSG_LOCATION: + ad.set_location((Location) msg.obj); + break; + case MSG_CRC_ERROR: case MSG_UPDATE_AGE: if (ad.saved_state != null) { ad.mAgeView.setText(String.format("%d", (System.currentTimeMillis() - ad.saved_state.report_time + 500) / 1000)); @@ -196,8 +203,13 @@ public class AltosDroid extends FragmentActivity { mTabs.remove(mTab); } + void set_location(Location location) { + saved_location = location; + update_ui(saved_state); + } + void update_ui(AltosState state) { - if (saved_state != null) { + if (state != null && saved_state != null) { if (saved_state.state != state.state) { String currentTab = mTabHost.getCurrentTabTag(); switch (state.state) { @@ -215,16 +227,33 @@ public class AltosDroid extends FragmentActivity { } saved_state = state; - mCallsignView.setText(state.data.callsign); - mSerialView.setText(String.format("%d", state.data.serial)); - mFlightView.setText(String.format("%d", state.data.flight)); - mStateView.setText(state.data.state()); - mRSSIView.setText(String.format("%d", state.data.rssi)); + AltosGreatCircle from_receiver = null; + + if (state != null && saved_location != null && state.gps != null && state.gps.locked) { + double altitude = 0; + if (saved_location.hasAltitude()) + altitude = saved_location.getAltitude(); + from_receiver = new AltosGreatCircle(saved_location.getLatitude(), + saved_location.getLongitude(), + altitude, + state.gps.lat, + state.gps.lon, + state.gps.alt); + } + + if (state != null) { + mCallsignView.setText(state.data.callsign); + mSerialView.setText(String.format("%d", state.data.serial)); + mFlightView.setText(String.format("%d", state.data.flight)); + mStateView.setText(state.data.state()); + mRSSIView.setText(String.format("%d", state.data.rssi)); + } for (AltosDroidTab mTab : mTabs) - mTab.update_ui(state); + mTab.update_ui(state, from_receiver, saved_location); - mAltosVoice.tell(state); + if (state != null) + mAltosVoice.tell(state); } private void onTimerTick() { @@ -242,7 +271,7 @@ public class AltosDroid extends FragmentActivity { } int deg = (int) Math.floor(p); double min = (p - Math.floor(p)) * 60.0; - return String.format("%d° %9.6f\" %s", deg, min, h); + return String.format("%d°%9.4f\" %s", deg, min, h); } @Override @@ -283,6 +312,8 @@ public class AltosDroid extends FragmentActivity { mTabsAdapter.addTab(mTabHost.newTabSpec("landed").setIndicator("Landed"), TabLanded.class, null); mTabsAdapter.addTab(mTabHost.newTabSpec("map").setIndicator("Map"), TabMap.class, null); + for (int i = 0; i < 5; i++) + mTabHost.getTabWidget().getChildAt(i).getLayoutParams().height = 45; // Set up the custom title mTitle = (TextView) findViewById(R.id.title_left_text); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java index 68bbe593..6ebb47f7 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidTab.java @@ -17,8 +17,9 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_1.AltosState; +import org.altusmetrum.altoslib_1.*; +import android.location.Location; public interface AltosDroidTab { - public void update_ui(AltosState state); + public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver); } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java index 7da5c4a9..b3dba626 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java @@ -38,7 +38,6 @@ public class AltosVoice { public void onInit(int status) { if (status == TextToSpeech.SUCCESS) tts_enabled = true; if (tts_enabled) { - speak("AltosDroid ready"); idle_thread = new IdleThread(); } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java index bda6b1fd..23d2e97c 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_1.AltosState; +import org.altusmetrum.altoslib_1.*; import android.app.Activity; import android.os.Bundle; @@ -27,6 +27,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import android.location.Location; public class TabAscent extends Fragment implements AltosDroidTab { AltosDroid mAltosDroid; @@ -84,21 +85,25 @@ public class TabAscent extends Fragment implements AltosDroidTab { mAltosDroid = null; } - public void update_ui(AltosState state) { - mHeightView.setText(String.format("%6.0f m", state.height)); - mMaxHeightView.setText(String.format("%6.0f m", state.max_height)); - mSpeedView.setText(String.format("%6.0f m/s", state.speed())); - mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed())); - mAccelView.setText(String.format("%6.0f m/s²", state.acceleration)); - mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration)); - - mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S")); - mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E")); - - mApogeeVoltageView.setText(String.format("%4.2f V", state.drogue_sense)); - mApogeeLights.set(state.drogue_sense > 3.2); - - mMainVoltageView.setText(String.format("%4.2f V", state.main_sense)); - mMainLights.set(state.main_sense > 3.2); + public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { + if (state != null) { + mHeightView.setText(String.format("%6.0f m", state.height)); + mMaxHeightView.setText(String.format("%6.0f m", state.max_height)); + mSpeedView.setText(String.format("%6.0f m/s", state.speed())); + mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed())); + mAccelView.setText(String.format("%6.0f m/s²", state.acceleration)); + mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration)); + + if (state.gps != null) { + mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S")); + mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E")); + } + + mApogeeVoltageView.setText(String.format("%4.2f V", state.drogue_sense)); + mApogeeLights.set(state.drogue_sense > 3.2); + + mMainVoltageView.setText(String.format("%4.2f V", state.main_sense)); + mMainLights.set(state.main_sense > 3.2); + } } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java index 3805b7e7..49774a30 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java @@ -17,8 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_1.AltosGreatCircle; -import org.altusmetrum.altoslib_1.AltosState; +import org.altusmetrum.altoslib_1.*; import android.app.Activity; import android.os.Bundle; @@ -28,6 +27,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import android.location.Location; public class TabDescent extends Fragment implements AltosDroidTab { AltosDroid mAltosDroid; @@ -89,24 +89,34 @@ public class TabDescent extends Fragment implements AltosDroidTab { mAltosDroid = null; } - public void update_ui(AltosState state) { - mSpeedView.setText(String.format("%6.0f m/s", state.speed())); - mHeightView.setText(String.format("%6.0f m", state.height)); - mElevationView.setText(String.format("%3.0f°", state.elevation)); - mRangeView.setText(String.format("%6.0f m", state.range)); - if (state.from_pad != null) { - mBearingView.setText(String.format("%3.0f°", state.from_pad.bearing)); - mCompassView.setText(state.from_pad.bearing_words(AltosGreatCircle.BEARING_LONG)); + public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { + if (state != null) { + mSpeedView.setText(String.format("%6.0f m/s", state.speed())); + mHeightView.setText(String.format("%6.0f m", state.height)); + if (from_receiver != null) { + mElevationView.setText(String.format("%3.0f°", from_receiver.elevation)); + mRangeView.setText(String.format("%6.0f m", from_receiver.range)); + mBearingView.setText(String.format("%3.0f°", from_receiver.bearing)); + mCompassView.setText(from_receiver.bearing_words(AltosGreatCircle.BEARING_LONG)); + mDistanceView.setText(String.format("%6.0f m", from_receiver.distance)); + } else { + mElevationView.setText(""); + mRangeView.setText(""); + mBearingView.setText(""); + mCompassView.setText(""); + mDistanceView.setText(""); + } + if (state.gps != null) { + mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S")); + mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E")); + } + + mApogeeVoltageView.setText(String.format("%4.2f V", state.drogue_sense)); + mApogeeLights.set(state.drogue_sense > 3.2); + + mMainVoltageView.setText(String.format("%4.2f V", state.main_sense)); + mMainLights.set(state.main_sense > 3.2); } - mDistanceView.setText(String.format("%6.0f m", state.range)); - mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S")); - mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E")); - - mApogeeVoltageView.setText(String.format("%4.2f V", state.drogue_sense)); - mApogeeLights.set(state.drogue_sense > 3.2); - - mMainVoltageView.setText(String.format("%4.2f V", state.main_sense)); - mMainLights.set(state.main_sense > 3.2); } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java index a95e9145..f42b46b5 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabLanded.java @@ -17,7 +17,7 @@ package org.altusmetrum.AltosDroid; -import org.altusmetrum.altoslib_1.AltosState; +import org.altusmetrum.altoslib_1.*; import android.app.Activity; import android.os.Bundle; @@ -26,14 +26,17 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import android.location.Location; public class TabLanded extends Fragment implements AltosDroidTab { AltosDroid mAltosDroid; private TextView mBearingView; private TextView mDistanceView; - private TextView mLatitudeView; - private TextView mLongitudeView; + private TextView mTargetLatitudeView; + private TextView mTargetLongitudeView; + private TextView mReceiverLatitudeView; + private TextView mReceiverLongitudeView; private TextView mMaxHeightView; private TextView mMaxSpeedView; private TextView mMaxAccelView; @@ -52,8 +55,10 @@ public class TabLanded extends Fragment implements AltosDroidTab { mBearingView = (TextView) v.findViewById(R.id.bearing_value); mDistanceView = (TextView) v.findViewById(R.id.distance_value); - mLatitudeView = (TextView) v.findViewById(R.id.lat_value); - mLongitudeView = (TextView) v.findViewById(R.id.lon_value); + mTargetLatitudeView = (TextView) v.findViewById(R.id.target_lat_value); + mTargetLongitudeView = (TextView) v.findViewById(R.id.target_lon_value); + mReceiverLatitudeView = (TextView) v.findViewById(R.id.receiver_lat_value); + mReceiverLongitudeView = (TextView) v.findViewById(R.id.receiver_lon_value); mMaxHeightView = (TextView) v.findViewById(R.id.max_height_value); mMaxSpeedView = (TextView) v.findViewById(R.id.max_speed_value); mMaxAccelView = (TextView) v.findViewById(R.id.max_accel_value); @@ -68,16 +73,26 @@ public class TabLanded extends Fragment implements AltosDroidTab { mAltosDroid = null; } - public void update_ui(AltosState state) { - if (state.from_pad != null) { - mBearingView.setText(String.format("%3.0f°", state.from_pad.bearing)); - mDistanceView.setText(String.format("%6.0f m", state.from_pad.distance)); + public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { + if (from_receiver != null) { + mBearingView.setText(String.format("%3.0f°", from_receiver.bearing)); + mDistanceView.setText(String.format("%6.0f m", from_receiver.distance)); + } + if (state != null && state.gps != null) { + mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S")); + mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E")); + } + + if (receiver != null) { + mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S")); + mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E")); + } + + if (state != null) { + mMaxHeightView.setText(String.format("%6.0f m", state.max_height)); + mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration)); + mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed())); } - mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S")); - mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E")); - mMaxHeightView.setText(String.format("%6.0f m", state.max_height)); - mMaxAccelView.setText(String.format("%6.0f m/s²", state.max_acceleration)); - mMaxSpeedView.setText(String.format("%6.0f m/s", state.max_speed())); } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java index 8fc8f592..66669ad0 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabMap.java @@ -40,6 +40,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import android.location.Location; public class TabMap extends Fragment implements AltosDroidTab { AltosDroid mAltosDroid; @@ -54,8 +55,12 @@ public class TabMap extends Fragment implements AltosDroidTab { private TextView mDistanceView; private TextView mBearingView; - private TextView mLatitudeView; - private TextView mLongitudeView; + private TextView mTargetLatitudeView; + private TextView mTargetLongitudeView; + private TextView mReceiverLatitudeView; + private TextView mReceiverLongitudeView; + + private double mapAccuracy = -1; @Override public void onAttach(Activity activity) { @@ -83,8 +88,10 @@ public class TabMap extends Fragment implements AltosDroidTab { View v = inflater.inflate(R.layout.tab_map, container, false); mDistanceView = (TextView)v.findViewById(R.id.distance_value); mBearingView = (TextView)v.findViewById(R.id.bearing_value); - mLatitudeView = (TextView)v.findViewById(R.id.lat_value); - mLongitudeView = (TextView)v.findViewById(R.id.lon_value); + mTargetLatitudeView = (TextView)v.findViewById(R.id.target_lat_value); + mTargetLongitudeView = (TextView)v.findViewById(R.id.target_lon_value); + mReceiverLatitudeView = (TextView)v.findViewById(R.id.receiver_lat_value); + mReceiverLongitudeView = (TextView)v.findViewById(R.id.receiver_lon_value); return v; } @@ -113,7 +120,6 @@ public class TabMap extends Fragment implements AltosDroidTab { mMap.setMyLocationEnabled(true); mMap.getUiSettings().setTiltGesturesEnabled(false); mMap.getUiSettings().setZoomControlsEnabled(false); - mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(40.8,-104.7),8)); mRocketMarker = mMap.addMarker( // From: http://mapicons.nicolasmollet.com/markers/industry/military/missile-2/ @@ -139,26 +145,52 @@ public class TabMap extends Fragment implements AltosDroidTab { } } - public void update_ui(AltosState state) { - if (state.from_pad != null) { - mDistanceView.setText(String.format("%6.0f m", state.from_pad.distance)); - mBearingView.setText(String.format("%3.0f°", state.from_pad.bearing)); + private void center(double lat, double lon, double accuracy) { + if (mapAccuracy < 0 || accuracy < mapAccuracy/10) { + mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lon),14)); + mapAccuracy = accuracy; + } + } + public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { + if (state != null) { + if (state.from_pad != null) { + mDistanceView.setText(String.format("%6.0f m", state.from_pad.distance)); + mBearingView.setText(String.format("%3.0f°", state.from_pad.bearing)); + } + if (mapLoaded) { + if (state.gps != null) { + mRocketMarker.setPosition(new LatLng(state.gps.lat, state.gps.lon)); + mRocketMarker.setVisible(true); + + mPolyline.setPoints(Arrays.asList(new LatLng(state.pad_lat, state.pad_lon), new LatLng(state.gps.lat, state.gps.lon))); + mPolyline.setVisible(true); + } + + if (state.state == AltosLib.ao_flight_pad) { + mPadMarker.setPosition(new LatLng(state.pad_lat, state.pad_lon)); + mPadMarker.setVisible(true); + } + } + if (state.gps != null) { + mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S")); + mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E")); + if (state.gps.locked && state.gps.nsat >= 4) + center (state.gps.lat, state.gps.lon, 10); + } } - mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S")); - mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E")); - - if (mapLoaded) { - mRocketMarker.setPosition(new LatLng(state.gps.lat, state.gps.lon)); - mRocketMarker.setVisible(true); - mPolyline.setPoints(Arrays.asList(new LatLng(state.pad_lat, state.pad_lon), new LatLng(state.gps.lat, state.gps.lon))); - mPolyline.setVisible(true); + if (receiver != null) { + double accuracy; - if (state.state == AltosLib.ao_flight_pad) { - mPadMarker.setPosition(new LatLng(state.pad_lat, state.pad_lon)); - mPadMarker.setVisible(true); - } + if (receiver.hasAccuracy()) + accuracy = receiver.getAccuracy(); + else + accuracy = 1000; + mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S")); + mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E")); + center (receiver.getLatitude(), receiver.getLongitude(), accuracy); } + } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java index 41776c10..3c168e37 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java @@ -27,6 +27,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import android.location.Location; public class TabPad extends Fragment implements AltosDroidTab { AltosDroid mAltosDroid; @@ -100,40 +101,48 @@ public class TabPad extends Fragment implements AltosDroidTab { mAltosDroid = null; } - public void update_ui(AltosState state) { - mBatteryVoltageView.setText(String.format("%4.2f V", state.battery)); - mBatteryLights.set(state.battery > 3.7); - - mApogeeVoltageView.setText(String.format("%4.2f V", state.drogue_sense)); - mApogeeLights.set(state.drogue_sense > 3.2); - - mMainVoltageView.setText(String.format("%4.2f V", state.main_sense)); - mMainLights.set(state.main_sense > 3.2); - - if (state.data.flight != 0) { - if (state.data.state <= AltosLib.ao_flight_pad) - mDataLoggingView.setText("Ready to record"); - else if (state.data.state < AltosLib.ao_flight_landed) - mDataLoggingView.setText("Recording data"); - else - mDataLoggingView.setText("Recorded data"); - } else { - mDataLoggingView.setText("Storage full"); + public void update_ui(AltosState state, AltosGreatCircle from_receiver, Location receiver) { + if (state != null) { + mBatteryVoltageView.setText(String.format("%4.2f V", state.battery)); + mBatteryLights.set(state.battery > 3.7); + + mApogeeVoltageView.setText(String.format("%4.2f V", state.drogue_sense)); + mApogeeLights.set(state.drogue_sense > 3.2); + + mMainVoltageView.setText(String.format("%4.2f V", state.main_sense)); + mMainLights.set(state.main_sense > 3.2); + + if (state.data.flight != 0) { + if (state.data.state <= AltosLib.ao_flight_pad) + mDataLoggingView.setText("Ready to record"); + else if (state.data.state < AltosLib.ao_flight_landed) + mDataLoggingView.setText("Recording data"); + else + mDataLoggingView.setText("Recorded data"); + } else { + mDataLoggingView.setText("Storage full"); + } + mDataLoggingLights.set(state.data.flight != 0); + + if (state.gps != null) { + mGPSLockedView.setText(String.format("%4d sats", state.gps.nsat)); + mGPSLockedLights.set(state.gps.locked && state.gps.nsat >= 4); + if (state.gps_ready) + mGPSReadyView.setText("Ready"); + else + mGPSReadyView.setText(String.format("Waiting %d", state.gps_waiting)); + mGPSReadyLights.set(state.gps_ready); + } } - mDataLoggingLights.set(state.data.flight != 0); - mGPSLockedView.setText(String.format("%4d sats", state.gps.nsat)); - mGPSLockedLights.set(state.gps.locked && state.gps.nsat >= 4); - - if (state.gps_ready) - mGPSReadyView.setText("Ready"); - else - mGPSReadyView.setText(String.format("Waiting %d", state.gps_waiting)); - mGPSReadyLights.set(state.gps_ready); - - mPadLatitudeView.setText(AltosDroid.pos(state.pad_lat, "N", "S")); - mPadLongitudeView.setText(AltosDroid.pos(state.pad_lon, "W", "E")); - mPadAltitudeView.setText(String.format("%4.0f m", state.pad_alt)); + if (receiver != null) { + double altitude = 0; + if (receiver.hasAltitude()) + altitude = receiver.getAltitude(); + mPadLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S")); + mPadLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E")); + mPadAltitudeView.setText(String.format("%4.0f m", altitude)); + } } } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java index 9460bdbc..716ec589 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java @@ -68,12 +68,12 @@ public class TelemetryReader extends Thread { if (record == null) break; state = new AltosState(record, state); - handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget(); } catch (ParseException pp) { Log.e(TAG, String.format("Parse error: %d \"%s\"", pp.getErrorOffset(), pp.getMessage())); } catch (AltosCRCException ce) { ++crc_errors; + handler.obtainMessage(TelemetryService.MSG_CRC_ERROR, new Integer(crc_errors)).sendToTarget(); } } } catch (InterruptedException ee) { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index e1a5ada8..f1304a95 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -45,9 +45,10 @@ import android.location.LocationListener; import org.altusmetrum.altoslib_1.*; class AltosLocationListener implements LocationListener { - boolean fine; + Handler handler; public void onLocationChanged(Location location) { + handler.obtainMessage(TelemetryService.MSG_LOCATION, location).sendToTarget(); } public void onStatusChanged(String provider, int status, Bundle extras) { @@ -59,8 +60,8 @@ class AltosLocationListener implements LocationListener { public void onProviderDisabled(String provider) { } - public AltosLocationListener(boolean fine) { - this.fine = fine; + public AltosLocationListener(Handler handler) { + this.handler = handler; } } @@ -77,6 +78,8 @@ public class TelemetryService extends Service { static final int MSG_DISCONNECTED = 6; static final int MSG_TELEMETRY = 7; static final int MSG_SETFREQUENCY = 8; + static final int MSG_LOCATION = 9; + static final int MSG_CRC_ERROR = 10; public static final int STATE_NONE = 0; public static final int STATE_READY = 1; @@ -107,9 +110,14 @@ public class TelemetryService extends Service { // location listeners - private AltosLocationListener gpsListener; - private AltosLocationListener netListener; + private AltosLocationListener locationListener; + // Last data seen; send to UI when it starts + + private AltosState last_state; + private Location last_location; + private int last_crc_errors; + // Handler of incoming messages from clients. static class IncomingHandler extends Handler { private final WeakReference service; @@ -129,6 +137,12 @@ public class TelemetryService extends Service { s.mClients.remove(msg.replyTo); } if (D) Log.d(TAG, "Client bound to service"); + if (s.last_state != null) + s.sendTelemetry(s.last_state); + if (s.last_location != null) + s.sendLocation(s.last_location); + if (s.last_crc_errors != 0) + s.sendCrcErrors(s.last_crc_errors); break; case MSG_UNREGISTER_CLIENT: s.mClients.remove(msg.replyTo); @@ -155,8 +169,20 @@ public class TelemetryService extends Service { } break; case MSG_TELEMETRY: + // forward telemetry messages + s.last_state = (AltosState) msg.obj; s.sendMessageToClients(Message.obtain(null, AltosDroid.MSG_TELEMETRY, msg.obj)); break; + case MSG_LOCATION: + // forward location messages + s.last_location = (Location) msg.obj; + s.sendMessageToClients(Message.obtain(null, AltosDroid.MSG_LOCATION, msg.obj)); + break; + case MSG_CRC_ERROR: + // forward crc error messages + s.last_crc_errors = (Integer) msg.obj; + s.sendMessageToClients(Message.obtain(null, AltosDroid.MSG_CRC_ERROR, msg.obj)); + break; case MSG_SETFREQUENCY: if (s.state == STATE_CONNECTED) { try { @@ -172,6 +198,16 @@ public class TelemetryService extends Service { } } + public void sendTelemetry(AltosState state) { + } + + public void sendLocation(Location location) { + mHandler.obtainMessage(MSG_LOCATION, location).sendToTarget(); + } + + public void sendCrcErrors(int crc_errors) { + } + private void sendMessageToClients(Message m) { for (int i=mClients.size()-1; i>=0; i--) { try { @@ -209,6 +245,9 @@ public class TelemetryService extends Service { } private void startAltosBluetooth() { + if (device == null) { + return; + } if (mAltosBluetooth == null) { if (D) Log.d(TAG, String.format("startAltosBluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress())); mAltosBluetooth = new AltosBluetooth(device, mHandler); @@ -238,6 +277,8 @@ public class TelemetryService extends Service { private void connected() { try { + if (mAltosBluetooth == null) + throw new InterruptedException("no bluetooth"); mConfigData = mAltosBluetooth.config_data(); } catch (InterruptedException e) { } catch (TimeoutException e) { @@ -279,13 +320,12 @@ public class TelemetryService extends Service { timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 10000L, 10000L); // Listen for GPS and Network position updates - gpsListener = new AltosLocationListener(true); - netListener = new AltosLocationListener(false); + locationListener = new AltosLocationListener(mHandler); LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpsListener); - locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, netListener); + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); + locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); } @Override @@ -320,8 +360,7 @@ public class TelemetryService extends Service { // Stop listening for location updates LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); - locationManager.removeUpdates(gpsListener); - locationManager.removeUpdates(netListener); + locationManager.removeUpdates(locationListener); // Stop the bluetooth Comms threads stopAltosBluetooth(); diff --git a/altoslib/AltosGreatCircle.java b/altoslib/AltosGreatCircle.java index 921356a5..f1cf0ae9 100644 --- a/altoslib/AltosGreatCircle.java +++ b/altoslib/AltosGreatCircle.java @@ -22,6 +22,8 @@ import java.lang.Math; public class AltosGreatCircle { public double distance; public double bearing; + public double range; + public double elevation; double sqr(double a) { return a * a; } @@ -54,9 +56,8 @@ public class AltosGreatCircle { return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; } - public AltosGreatCircle (double start_lat, double start_lon, - double end_lat, double end_lon) - { + public AltosGreatCircle (double start_lat, double start_lon, double start_alt, + double end_lat, double end_lon, double end_alt) { double lat1 = rad * start_lat; double lon1 = rad * -start_lon; double lat2 = rad * end_lat; @@ -88,14 +89,25 @@ public class AltosGreatCircle { } distance = d * earth_radius; bearing = course * 180/Math.PI; + + double height_diff = end_alt - start_alt; + range = Math.sqrt(distance * distance + height_diff * height_diff); + elevation = Math.atan2(height_diff, distance) * 180 / Math.PI; + } + + public AltosGreatCircle (double start_lat, double start_lon, + double end_lat, double end_lon) { + this(start_lat, start_lon, 0, end_lat, end_lon, 0); } public AltosGreatCircle(AltosGPS start, AltosGPS end) { - this(start.lat, start.lon, end.lat, end.lon); + this(start.lat, start.lon, start.alt, end.lat, end.lon, end.alt); } public AltosGreatCircle() { distance = 0; bearing = 0; + range = 0; + elevation = 0; } } diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index f1bcb1c1..a3b9a8c0 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -248,23 +248,21 @@ public class AltosState { if (height != AltosRecord.MISSING && height > max_height) max_height = height; + elevation = 0; + range = -1; + gps_height = 0; if (data.gps != null) { if (gps == null || !gps.locked || data.gps.locked) gps = data.gps; if (ngps > 0 && gps.locked) { - from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); - } - } - elevation = 0; - range = -1; - if (ngps > 0) { - gps_height = gps.alt - pad_alt; - if (from_pad != null) { - elevation = Math.atan2(height, from_pad.distance) * 180 / Math.PI; - range = Math.sqrt(height * height + from_pad.distance * from_pad.distance); + double h = height; + + if (h == AltosRecord.MISSING) h = 0; + from_pad = new AltosGreatCircle(pad_lat, pad_lon, 0, gps.lat, gps.lon, h); + elevation = from_pad.elevation; + range = from_pad.range; + gps_height = gps.alt - pad_alt; } - } else { - gps_height = 0; } }