Merge branch 'android' into revo-mini
Conflicts: androidgcs/AndroidManifest.xml androidgcs/res/layout/gcs_home.xml androidgcs/res/values/strings.xml androidgcs/src/org/openpilot/androidgcs/AttitudeView.java androidgcs/src/org/openpilot/androidgcs/HomePage.java
@ -1,96 +1,71 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="org.openpilot.androidgcs" android:versionCode="1"
|
||||||
|
android:versionName="1.0">
|
||||||
|
<uses-sdk android:minSdkVersion="14" />
|
||||||
|
|
||||||
package="org.openpilot.androidgcs"
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
android:versionCode="1"
|
|
||||||
android:versionName="1.0" >
|
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="14" />
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-feature android:name="android.hardware.usb.host" />
|
||||||
|
|
||||||
|
<application android:icon="@drawable/ic_logo" android:label="@string/app_name" android:theme="@android:style/Theme.Holo">
|
||||||
|
<!-- for map overlay -->
|
||||||
|
<uses-library android:name="com.google.android.maps" />
|
||||||
|
|
||||||
<uses-feature android:glEsVersion="0x00020000" /> <!-- OpenGL min requierements (2.0) -->
|
<!-- Object browser - main activity at the moment -->
|
||||||
|
<activity android:name="HomePage" android:label="@string/app_name">
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- <intent-filter> -->
|
||||||
|
<!-- <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> -->
|
||||||
|
<!-- </intent-filter> -->
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<!-- <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" -->
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
<!-- android:resource="@xml/device_filter" /> -->
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
</activity>
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.usb.host" />
|
<activity android:name="ObjectBrowser" android:label="@string/object_browser_name" />
|
||||||
|
<activity android:name="PfdActivity" android:label="PFD" />
|
||||||
|
<activity android:name="Controller" android:label="@string/controller_name" />
|
||||||
|
<activity android:name="Preferences" android:label="@string/preference_title" />
|
||||||
|
<activity android:name="UAVLocation" android:label="@string/location_name" />
|
||||||
|
<activity android:name="SystemAlarmActivity" android:label="System Alarms" />
|
||||||
|
<activity android:name="TuningActivity" android:label="Tuning" />
|
||||||
|
<activity android:name="ObjectEditor" android:label="ObjectEditor"
|
||||||
|
android:theme="@android:style/Theme.Dialog" />
|
||||||
|
<activity android:name="Logger" android:label="Logger"
|
||||||
|
android:theme="@android:style/Theme.Dialog" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="FragmentTester"
|
||||||
|
android:label="FragmentTester" />
|
||||||
|
|
||||||
<application
|
|
||||||
android:icon="@drawable/ic_logo"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:theme="@android:style/Theme.Holo" >
|
|
||||||
|
|
||||||
<!-- for map overlay -->
|
|
||||||
<uses-library android:name="com.google.android.maps" />
|
|
||||||
|
|
||||||
<!-- Object browser - main activity at the moment -->
|
|
||||||
<activity
|
|
||||||
android:name="org.openpilot.androidgcs.HomePage"
|
|
||||||
android:label="@string/app_name" >
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
|
|
||||||
<!-- <intent-filter> -->
|
|
||||||
<!-- <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> -->
|
|
||||||
<!-- </intent-filter> -->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" -->
|
|
||||||
<!-- android:resource="@xml/device_filter" /> -->
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name="ObjectBrowser"
|
|
||||||
android:label="@string/object_browser_name" />
|
|
||||||
<activity
|
|
||||||
android:name="PfdActivity"
|
|
||||||
android:label="PFD" />
|
|
||||||
<activity
|
|
||||||
android:name="Controller"
|
|
||||||
android:label="@string/controller_name" />
|
|
||||||
<activity
|
|
||||||
android:name="Preferences"
|
|
||||||
android:label="@string/preference_title" />
|
|
||||||
<activity
|
|
||||||
android:name="UAVLocation"
|
|
||||||
android:label="@string/location_name" />
|
|
||||||
<activity
|
|
||||||
android:name="SystemAlarmActivity"
|
|
||||||
android:label="System Alarms" />
|
|
||||||
<activity
|
|
||||||
android:name="ObjectEditor"
|
|
||||||
android:label="ObjectEditor"
|
|
||||||
android:theme="@android:style/Theme.Dialog" />
|
|
||||||
<activity
|
|
||||||
android:name="Logger"
|
|
||||||
android:label="Logger"
|
|
||||||
android:theme="@android:style/Theme.Dialog" />
|
|
||||||
<activity android:name="FragmentTester" android:label="FragmentTester" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name="OsgViewer"
|
android:name="OsgViewer"
|
||||||
android:label="3DView" />
|
android:label="3DView" />
|
||||||
|
|
||||||
<receiver android:name="TelemetryWidget" >
|
<receiver android:name="TelemetryWidget">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="org.openpilot.intent.action.CONNECTED" />
|
<action android:name="org.openpilot.intent.action.CONNECTED" />
|
||||||
<action android:name="org.openpilot.intent.action.DISCONNECTED" />
|
<action android:name="org.openpilot.intent.action.DISCONNECTED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<meta-data android:name="android.appwidget.provider"
|
||||||
<meta-data
|
android:resource="@xml/telemetry_widget_info" />
|
||||||
android:name="android.appwidget.provider"
|
</receiver>
|
||||||
android:resource="@xml/telemetry_widget_info" />
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<service android:name="org.openpilot.androidgcs.telemetry.OPTelemetryService" >
|
|
||||||
</service>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
|
<service android:name="org.openpilot.androidgcs.telemetry.OPTelemetryService"></service>
|
||||||
|
</application>
|
||||||
</manifest>
|
</manifest>
|
Before Width: | Height: | Size: 823 B After Width: | Height: | Size: 849 B |
BIN
androidgcs/res/drawable-hdpi/ic_tuning.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 800 B After Width: | Height: | Size: 797 B |
BIN
androidgcs/res/drawable-hdpi/im_pfd_fixed.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 9.7 KiB |
BIN
androidgcs/res/drawable-hdpi/im_pfd_reticule.png
Normal file
After Width: | Height: | Size: 18 KiB |
138
androidgcs/res/layout-w600dp/gcs_home.xml
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_gravity="center_horizontal" >
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_controller"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="3"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:layout_row="1"
|
||||||
|
android:layout_rowSpan="4"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_controller"
|
||||||
|
android:text="@string/controller_name" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_object_browser"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="0"
|
||||||
|
android:layout_gravity="right|bottom"
|
||||||
|
android:layout_row="2"
|
||||||
|
android:layout_rowSpan="2"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_browser"
|
||||||
|
android:text="@string/object_browser_name" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_location"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="2"
|
||||||
|
android:layout_gravity="right|bottom"
|
||||||
|
android:layout_row="2"
|
||||||
|
android:layout_rowSpan="2"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_map"
|
||||||
|
android:text="@string/location_name" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_tuning"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="4"
|
||||||
|
android:layout_gravity="right|bottom"
|
||||||
|
android:layout_row="2"
|
||||||
|
android:layout_rowSpan="2"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_tuning"
|
||||||
|
android:text="@string/tuning" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_logger"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="3"
|
||||||
|
android:layout_gravity="left|bottom"
|
||||||
|
android:layout_row="3"
|
||||||
|
android:layout_rowSpan="3"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_logging"
|
||||||
|
android:text="@string/logger_name" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_alarms"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="0"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:layout_row="5"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_alarms"
|
||||||
|
android:text="@string/alarms" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_pfd"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="2"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:layout_row="5"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_pfd"
|
||||||
|
android:text="@string/pfd_name" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_osgViewer"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="0"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:layout_row="9"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_alarms"
|
||||||
|
android:text="@string/_3dview" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_tester"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="2"
|
||||||
|
android:layout_row="9"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_alarms"
|
||||||
|
android:text="@string/tester" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_column="0"
|
||||||
|
android:layout_row="0" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="47dp"
|
||||||
|
android:layout_column="0"
|
||||||
|
android:layout_row="4" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="47dp"
|
||||||
|
android:layout_column="0"
|
||||||
|
android:layout_row="8" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_height="15dp"
|
||||||
|
android:layout_column="1" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="100dp"
|
||||||
|
android:layout_height="2dp"
|
||||||
|
android:layout_row="6" />
|
||||||
|
|
||||||
|
</GridLayout>
|
103
androidgcs/res/layout-w600dp/tuning.xml
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:setting_attributes="http://schemas.android.com/apk/res/org.openpilot.androidgcs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/saveBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:text="@string/save" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/applyBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_toLeftOf="@+id/saveBtn"
|
||||||
|
android:text="@string/apply" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout3"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentTop="true" >
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/rollRateKp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
setting_attributes:max_value="0.01"
|
||||||
|
setting_attributes:setting_name="Roll Rate Kp" >
|
||||||
|
</org.openpilot.androidgcs.views.ScrollBarView>
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/pitchRateKp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
setting_attributes:max_value="0.01"
|
||||||
|
setting_attributes:setting_name="Pitch Rate Kp" >
|
||||||
|
</org.openpilot.androidgcs.views.ScrollBarView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_below="@+id/linearLayout3" >
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/rollRateKi"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
setting_attributes:max_value="0.05"
|
||||||
|
setting_attributes:setting_name="Roll Rate Ki" >
|
||||||
|
</org.openpilot.androidgcs.views.ScrollBarView>
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/pitchRateKi"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
setting_attributes:max_value="0.05"
|
||||||
|
setting_attributes:setting_name="Pitch Rate Ki" >
|
||||||
|
</org.openpilot.androidgcs.views.ScrollBarView>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout2"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_below="@+id/linearLayout1" >
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/rollKp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
setting_attributes:max_value="5"
|
||||||
|
setting_attributes:setting_name="Roll Kp" >
|
||||||
|
</org.openpilot.androidgcs.views.ScrollBarView>
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/pitchKp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
setting_attributes:max_value="5"
|
||||||
|
setting_attributes:setting_name="Pitch Kp" >
|
||||||
|
</org.openpilot.androidgcs.views.ScrollBarView>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -81,25 +81,37 @@
|
|||||||
android:id="@+id/launch_tester"
|
android:id="@+id/launch_tester"
|
||||||
android:layout_width="132dp"
|
android:layout_width="132dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_row="6"
|
android:layout_row="8"
|
||||||
android:layout_column="0"
|
android:layout_column="0"
|
||||||
android:layout_rowSpan="2"
|
android:layout_rowSpan="2"
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:drawableTop="@drawable/ic_alarms"
|
android:drawableTop="@drawable/ic_alarms"
|
||||||
android:text="@string/tester" />
|
android:text="@string/tester" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/launch_osgViewer"
|
android:id="@+id/launch_osgViewer"
|
||||||
|
android:layout_width="132dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_column="1"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:layout_row="8"
|
||||||
|
android:layout_rowSpan="2"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:drawableTop="@drawable/ic_alarms"
|
||||||
|
android:text="@string/_3dview" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_tuning"
|
||||||
android:layout_width="132dp"
|
android:layout_width="132dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_column="1"
|
android:layout_column="0"
|
||||||
android:layout_gravity="right"
|
android:layout_gravity="right"
|
||||||
android:layout_row="6"
|
android:layout_row="6"
|
||||||
android:layout_rowSpan="2"
|
android:layout_rowSpan="2"
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:drawableTop="@drawable/ic_alarms"
|
android:drawableTop="@drawable/ic_tuning"
|
||||||
android:text="@string/_3dview" />
|
android:text="@string/tuning" />
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="1dp"
|
android:layout_width="1dp"
|
||||||
android:layout_height="32dp"
|
android:layout_height="32dp"
|
||||||
|
@ -23,14 +23,14 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:checked="true"
|
android:checked="true"
|
||||||
android:text="Settings" />
|
android:text="@string/settings" />
|
||||||
|
|
||||||
<CheckBox
|
<CheckBox
|
||||||
android:id="@+id/dataCheck"
|
android:id="@+id/dataCheck"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:checked="true"
|
android:checked="true"
|
||||||
android:text="Data" />
|
android:text="@string/data" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -56,7 +56,7 @@
|
|||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:background="#FFFFFFFF" />
|
android:background="#FFFFFFFF" />
|
||||||
|
|
||||||
<LinearLayout
|
<RelativeLayout
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
@ -66,40 +66,29 @@
|
|||||||
android:id="@+id/object_information"
|
android:id="@+id/object_information"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginLeft="12dp"
|
android:layout_marginLeft="12dp"
|
||||||
android:layout_marginTop="12dp"
|
android:layout_marginTop="12dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
<Space
|
<Button
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/editButton"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:text="@string/edit" />
|
||||||
|
|
||||||
<Space
|
<Button
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/object_load_button"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_toLeftOf="@+id/editButton"
|
||||||
|
android:text="@string/load" />
|
||||||
|
|
||||||
<LinearLayout
|
</RelativeLayout>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content" >
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/object_load_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Load" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/editButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="right"
|
|
||||||
android:layout_marginBottom="32dp"
|
|
||||||
android:layout_marginRight="12dp"
|
|
||||||
android:text="Edit" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
83
androidgcs/res/layout/tuning.xml
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:setting_attributes="http://schemas.android.com/apk/res/org.openpilot.androidgcs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/rollRateKp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
setting_attributes:setting_name="Roll Rate Kp"
|
||||||
|
setting_attributes:max_value="0.01" />
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/pitchRateKp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
setting_attributes:setting_name="Pitch Rate Kp"
|
||||||
|
setting_attributes:max_value="0.01" />
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/rollRateKi"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
setting_attributes:setting_name="Roll Rate Ki"
|
||||||
|
setting_attributes:max_value="0.05" />
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/pitchRateKi"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
setting_attributes:setting_name="Pitch Rate Ki"
|
||||||
|
setting_attributes:max_value="0.05" />
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/rollKp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
setting_attributes:setting_name="Roll Kp"
|
||||||
|
setting_attributes:max_value="5" />
|
||||||
|
|
||||||
|
<org.openpilot.androidgcs.views.ScrollBarView
|
||||||
|
android:id="@+id/pitchKp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
setting_attributes:setting_name="Pitch Kp"
|
||||||
|
setting_attributes:max_value="5" />
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="right" >
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/applyBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/apply" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/saveBtn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/save" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
@ -14,4 +14,12 @@
|
|||||||
<item>3</item>
|
<item>3</item>
|
||||||
<item>4</item>
|
<item>4</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="controllerTypeArray">
|
||||||
|
<item>Mode 1</item>
|
||||||
|
<item>Mode 2</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="controllerTypeValues">
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
7
androidgcs/res/values/attrs.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="setting_attributes">
|
||||||
|
<attr name="setting_name" format="string"/>
|
||||||
|
<attr name="max_value" format="float"/>
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
@ -34,4 +34,11 @@
|
|||||||
<string name="rxrate">RxRate: </string>
|
<string name="rxrate">RxRate: </string>
|
||||||
<string name="tester">Tester</string>
|
<string name="tester">Tester</string>
|
||||||
<string name="_3dview">3DView</string>
|
<string name="_3dview">3DView</string>
|
||||||
|
<string name="tuning">Tuning</string>
|
||||||
|
<string name="apply">Apply</string>
|
||||||
|
<string name="save">Save</string>
|
||||||
|
<string name="settings">Settings</string>
|
||||||
|
<string name="data">Data</string>
|
||||||
|
<string name="edit">Edit</string>
|
||||||
|
<string name="load">Load</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
10
androidgcs/res/xml/controller_preferences.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
<PreferenceCategory android:title="Controller Settings">
|
||||||
|
<ListPreference android:title="Controller Mode"
|
||||||
|
android:key="controller_type" android:summary="Select whether you want the virtual controller to use mode 1 or mode 2 convention"
|
||||||
|
android:defaultValue="Mode 1"
|
||||||
|
android:entries="@array/controllerTypeArray"
|
||||||
|
android:entryValues="@array/controllerTypeValues"/>
|
||||||
|
</PreferenceCategory>
|
||||||
|
</PreferenceScreen>
|
@ -56,29 +56,64 @@ public class AttitudeView extends View {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
/**
|
||||||
int measuredWidth = measure(widthMeasureSpec);
|
* @see android.view.View#measure(int, int)
|
||||||
int measuredHeight = measure(heightMeasureSpec);
|
*/
|
||||||
int d = Math.min(measuredWidth, measuredHeight);
|
@Override
|
||||||
setMeasuredDimension(d/2, d/2);
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
}
|
setMeasuredDimension(measureWidth(widthMeasureSpec),
|
||||||
|
measureHeight(heightMeasureSpec));
|
||||||
|
}
|
||||||
|
|
||||||
private int measure(int measureSpec) {
|
|
||||||
int result = 0;
|
|
||||||
// Decode the measurement specifications.
|
|
||||||
|
|
||||||
int specMode = MeasureSpec.getMode(measureSpec);
|
/**
|
||||||
int specSize = MeasureSpec.getSize(measureSpec);
|
* Determines the height of this view
|
||||||
|
* @param measureSpec A measureSpec packed into an int
|
||||||
|
* @return The height of the view, honoring constraints from measureSpec
|
||||||
|
*/
|
||||||
|
private int measureHeight(int measureSpec) {
|
||||||
|
int result = 0;
|
||||||
|
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.
|
if (specMode == MeasureSpec.EXACTLY) {
|
||||||
result = 200;
|
// We were told how big to be
|
||||||
} else {
|
result = specSize;
|
||||||
// As you want to fill the available space
|
} else {
|
||||||
// always return the full available bounds.
|
// Measure the text (beware: ascent is a negative number)
|
||||||
result = specSize;
|
result = 1600;
|
||||||
}
|
if (specMode == MeasureSpec.AT_MOST) {
|
||||||
return result;
|
// Respect AT_MOST value if that was what is called for by measureSpec
|
||||||
}
|
result = Math.min(result, specSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the width of this view
|
||||||
|
* @param measureSpec A measureSpec packed into an int
|
||||||
|
* @return The width of the view, honoring constraints from measureSpec
|
||||||
|
*/
|
||||||
|
private int measureWidth(int measureSpec) {
|
||||||
|
int result = 0;
|
||||||
|
int specMode = MeasureSpec.getMode(measureSpec);
|
||||||
|
int specSize = MeasureSpec.getSize(measureSpec);
|
||||||
|
|
||||||
|
if (specMode == MeasureSpec.EXACTLY) {
|
||||||
|
// We were told how big to be
|
||||||
|
result = specSize;
|
||||||
|
} else {
|
||||||
|
// Measure the text
|
||||||
|
result = 800;
|
||||||
|
if (specMode == MeasureSpec.AT_MOST) {
|
||||||
|
// Respect AT_MOST value if that was what is called for by measureSpec
|
||||||
|
result = Math.min(result, specSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private float roll;
|
private float roll;
|
||||||
public void setRoll(double roll) {
|
public void setRoll(double roll) {
|
||||||
@ -101,25 +136,35 @@ public class AttitudeView extends View {
|
|||||||
|
|
||||||
canvas.save();
|
canvas.save();
|
||||||
canvas.rotate(-roll, PX / 2, PY / 2);
|
canvas.rotate(-roll, PX / 2, PY / 2);
|
||||||
|
canvas.save();
|
||||||
|
|
||||||
canvas.translate(0, pitch * DEG_TO_PX);
|
canvas.translate(0, pitch * DEG_TO_PX);
|
||||||
Drawable horizon = getContext().getResources().getDrawable(
|
Drawable horizon = getContext().getResources().getDrawable(
|
||||||
R.drawable.im_pfd_horizon);
|
R.drawable.im_pfd_horizon);
|
||||||
|
Drawable reticule = getContext().getResources().getDrawable(
|
||||||
|
R.drawable.im_pfd_reticule);
|
||||||
|
Drawable fixed = getContext().getResources().getDrawable(
|
||||||
|
R.drawable.im_pfd_fixed);
|
||||||
|
|
||||||
|
// Starting with a square image, want to size it equally
|
||||||
|
double margin = 0.2;
|
||||||
|
int screenSize = Math.min(PX, PY);
|
||||||
|
int imageHalfSize = (int) ((screenSize + screenSize * margin) / 2);
|
||||||
|
|
||||||
// This puts the image at the center of the PFD canvas (after it was
|
// This puts the image at the center of the PFD canvas (after it was
|
||||||
// translated)
|
// translated)
|
||||||
double margin = 0.5;
|
horizon.setBounds( PX/2 - imageHalfSize, PY/2 - imageHalfSize, PX/2 + imageHalfSize, PY/2 + imageHalfSize);
|
||||||
horizon.setBounds( (int) (-margin * PX), (int) (-margin * PY), (int) ((1 + margin) * PX), (int) ((1+margin) *PY));
|
|
||||||
horizon.draw(canvas);
|
horizon.draw(canvas);
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
|
|
||||||
canvas.drawLine(0, 0, PX, 0, markerPaint);
|
// Draw the overlay that only rolls
|
||||||
canvas.drawLine(0, 0, 0, PY, markerPaint);
|
reticule.setBounds( PX/2 - imageHalfSize, PY/2 - imageHalfSize, PX/2 + imageHalfSize, PY/2 + imageHalfSize);
|
||||||
canvas.drawLine(PX, 0, PX, PY, markerPaint);
|
reticule.draw(canvas);
|
||||||
canvas.drawLine(0, PY, PX, PY, markerPaint);
|
canvas.restore();
|
||||||
|
|
||||||
canvas.drawLine(0,PY/2,PX,PY/2,markerPaint);
|
// Draw the overlay that never moves
|
||||||
canvas.drawLine(PX/2,0,PX/2,PY,markerPaint);
|
fixed.setBounds( PX/2 - imageHalfSize, PY/2 - imageHalfSize, PX/2 + imageHalfSize, PY/2 + imageHalfSize);
|
||||||
|
fixed.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,10 +44,7 @@ public class BluetoothDevicePreference extends ListPreference {
|
|||||||
Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
|
Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
|
||||||
CharSequence[] entries = new CharSequence[pairedDevices.size()];
|
CharSequence[] entries = new CharSequence[pairedDevices.size()];
|
||||||
CharSequence[] entryValues = new CharSequence[pairedDevices.size()];
|
CharSequence[] entryValues = new CharSequence[pairedDevices.size()];
|
||||||
if (pairedDevices.size() == 0) {
|
if (pairedDevices.size() > 0) {
|
||||||
entries[0] = "No Devices";
|
|
||||||
entryValues[0] = "";
|
|
||||||
} else {
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (BluetoothDevice dev : pairedDevices) {
|
for (BluetoothDevice dev : pairedDevices) {
|
||||||
entries[i] = dev.getName();
|
entries[i] = dev.getName();
|
||||||
|
@ -34,7 +34,9 @@ import org.openpilot.uavtalk.UAVDataObject;
|
|||||||
import org.openpilot.uavtalk.UAVObject;
|
import org.openpilot.uavtalk.UAVObject;
|
||||||
import org.openpilot.uavtalk.UAVObjectField;
|
import org.openpilot.uavtalk.UAVObjectField;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
@ -76,7 +78,7 @@ public class Controller extends ObjectManagerActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void update(Observable observable, Object data) {
|
public void update(Observable observable, Object data) {
|
||||||
// Once we have updated settings we can active the GCS receiver mode
|
// Once we have updated settings we can active the GCS receiver mode
|
||||||
Log.d(TAG,"Got update from settings");
|
if (DEBUG) Log.d(TAG,"Got update from settings");
|
||||||
UAVDataObject manualControlSettings = (UAVDataObject) objMngr.getObject("ManualControlSettings");
|
UAVDataObject manualControlSettings = (UAVDataObject) objMngr.getObject("ManualControlSettings");
|
||||||
if(manualControlSettings != null) {
|
if(manualControlSettings != null) {
|
||||||
manualControlSettings.removeUpdatedObserver(this);
|
manualControlSettings.removeUpdatedObserver(this);
|
||||||
@ -89,7 +91,27 @@ public class Controller extends ObjectManagerActivity {
|
|||||||
void onOPConnected() {
|
void onOPConnected() {
|
||||||
super.onOPConnected();
|
super.onOPConnected();
|
||||||
|
|
||||||
Log.d(TAG, "onOPConnected()");
|
if (DEBUG) Log.d(TAG, "onOPConnected()");
|
||||||
|
|
||||||
|
DualJoystickView joystick = (DualJoystickView) findViewById(R.id.dualjoystickView);
|
||||||
|
joystick.setMovementConstraint(JoystickView.CONSTRAIN_BOX);
|
||||||
|
joystick.setMovementRange((int)MOVEMENT_RANGE, (int)MOVEMENT_RANGE);
|
||||||
|
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
int mode = Integer.decode(prefs.getString("controller_type", "1"));
|
||||||
|
switch(mode) {
|
||||||
|
case 1:
|
||||||
|
if (DEBUG) Log.d(TAG, "Mode1 connected");
|
||||||
|
joystick.setOnJostickMovedListener(mode1_left, mode1_right);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (DEBUG) Log.d(TAG, "Mode2 connected");
|
||||||
|
joystick.setOnJostickMovedListener(mode2_left, mode2_right);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Unknown controller type");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Subscribe to updates from ManualControlCommand and show the values for crude feedback
|
// Subscribe to updates from ManualControlCommand and show the values for crude feedback
|
||||||
UAVDataObject manualControl = (UAVDataObject) objMngr.getObject("ManualControlCommand");
|
UAVDataObject manualControl = (UAVDataObject) objMngr.getObject("ManualControlCommand");
|
||||||
@ -100,39 +122,6 @@ public class Controller extends ObjectManagerActivity {
|
|||||||
manualSettings.addUpdatedObserver(settingsUpdated);
|
manualSettings.addUpdatedObserver(settingsUpdated);
|
||||||
manualSettings.updateRequested();
|
manualSettings.updateRequested();
|
||||||
|
|
||||||
final double MOVEMENT_RANGE = 50.0;
|
|
||||||
DualJoystickView joystick = (DualJoystickView) findViewById(R.id.dualjoystickView);
|
|
||||||
joystick.setMovementConstraint(JoystickView.CONSTRAIN_BOX);
|
|
||||||
joystick.setMovementRange((int)MOVEMENT_RANGE, (int)MOVEMENT_RANGE);
|
|
||||||
|
|
||||||
// Hardcode a Mode 1 listener for now
|
|
||||||
joystick.setOnJostickMovedListener(new JoystickMovedListener() {
|
|
||||||
@Override
|
|
||||||
public void OnMoved(int pan, int tilt) {
|
|
||||||
pitch = tilt / MOVEMENT_RANGE;
|
|
||||||
yaw = pan / MOVEMENT_RANGE;
|
|
||||||
leftJoystickHeld = true;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void OnReleased() { leftJoystickHeld = false; throttle = -1; updated = true; }
|
|
||||||
@Override
|
|
||||||
public void OnReturnedToCenter() { }
|
|
||||||
}, new JoystickMovedListener() {
|
|
||||||
@Override
|
|
||||||
public void OnMoved(int pan, int tilt) {
|
|
||||||
throttle = (-tilt + (MOVEMENT_RANGE -5)) / (MOVEMENT_RANGE - 5);
|
|
||||||
throttle *= 0.5;
|
|
||||||
if (throttle < 0)
|
|
||||||
throttle = -1;
|
|
||||||
roll = pan / MOVEMENT_RANGE;
|
|
||||||
rightJoystickHeld = true;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void OnReleased() { rightJoystickHeld = false; throttle = -1; updated = true; }
|
|
||||||
@Override
|
|
||||||
public void OnReturnedToCenter() { }
|
|
||||||
});
|
|
||||||
|
|
||||||
//! This timer task actually periodically sends updates to the UAV
|
//! This timer task actually periodically sends updates to the UAV
|
||||||
TimerTask controllerTask = new TimerTask() {
|
TimerTask controllerTask = new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
@ -248,4 +237,64 @@ public class Controller extends ObjectManagerActivity {
|
|||||||
return (float) (neutral + (neutral - CHANNEL_MIN) * in);
|
return (float) (neutral + (neutral - CHANNEL_MIN) * in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final JoystickMovedListener mode1_left = new JoystickMovedListener() {
|
||||||
|
@Override
|
||||||
|
public void OnMoved(int pan, int tilt) {
|
||||||
|
pitch = tilt / MOVEMENT_RANGE;
|
||||||
|
yaw = pan / MOVEMENT_RANGE;
|
||||||
|
leftJoystickHeld = true;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void OnReleased() { leftJoystickHeld = false; throttle = -1; updated = true; }
|
||||||
|
@Override
|
||||||
|
public void OnReturnedToCenter() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
private final JoystickMovedListener mode1_right = new JoystickMovedListener() {
|
||||||
|
@Override
|
||||||
|
public void OnMoved(int pan, int tilt) {
|
||||||
|
throttle = (-tilt + (MOVEMENT_RANGE -5)) / (MOVEMENT_RANGE - 5);
|
||||||
|
throttle *= 0.5;
|
||||||
|
if (throttle < 0)
|
||||||
|
throttle = -1;
|
||||||
|
roll = pan / MOVEMENT_RANGE;
|
||||||
|
rightJoystickHeld = true;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void OnReleased() { rightJoystickHeld = false; throttle = -1; updated = true; }
|
||||||
|
@Override
|
||||||
|
public void OnReturnedToCenter() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
private final JoystickMovedListener mode2_left = new JoystickMovedListener() {
|
||||||
|
@Override
|
||||||
|
public void OnMoved(int pan, int tilt) {
|
||||||
|
throttle = (-tilt + (MOVEMENT_RANGE -5)) / (MOVEMENT_RANGE - 5);
|
||||||
|
throttle *= 0.5;
|
||||||
|
if (throttle < 0)
|
||||||
|
throttle = -1;
|
||||||
|
yaw = pan / MOVEMENT_RANGE;
|
||||||
|
leftJoystickHeld = true;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void OnReleased() { leftJoystickHeld = false; throttle = -1; updated = true; }
|
||||||
|
@Override
|
||||||
|
public void OnReturnedToCenter() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
private final JoystickMovedListener mode2_right = new JoystickMovedListener() {
|
||||||
|
@Override
|
||||||
|
public void OnMoved(int pan, int tilt) {
|
||||||
|
pitch = tilt / MOVEMENT_RANGE;
|
||||||
|
roll = pan / MOVEMENT_RANGE;
|
||||||
|
rightJoystickHeld = true;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void OnReleased() { rightJoystickHeld = false; throttle = -1; updated = true; }
|
||||||
|
@Override
|
||||||
|
public void OnReturnedToCenter() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
final double MOVEMENT_RANGE = 50.0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,7 @@ public class HomePage extends ObjectManagerActivity {
|
|||||||
startActivity(new Intent(HomePage.this, FragmentTester.class));
|
startActivity(new Intent(HomePage.this, FragmentTester.class));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Button osgViewer = (Button) findViewById(R.id.launch_osgViewer);
|
Button osgViewer = (Button) findViewById(R.id.launch_osgViewer);
|
||||||
osgViewer.setOnClickListener(new OnClickListener() {
|
osgViewer.setOnClickListener(new OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -99,6 +100,14 @@ public class HomePage extends ObjectManagerActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Button tuning = (Button) findViewById(R.id.launch_tuning);
|
||||||
|
tuning.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View arg0) {
|
||||||
|
startActivity(new Intent(HomePage.this, TuningActivity.class));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ public class Preferences extends PreferenceActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
// Load the preferences from an XML resource
|
// Load the preferences from an XML resource
|
||||||
addPreferencesFromResource(R.xml.preferences);
|
addPreferencesFromResource(R.xml.preferences);
|
||||||
|
addPreferencesFromResource(R.xml.controller_preferences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
47
androidgcs/src/org/openpilot/androidgcs/TuningActivity.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package org.openpilot.androidgcs;
|
||||||
|
|
||||||
|
import org.openpilot.androidgcs.util.SmartSave;
|
||||||
|
import org.openpilot.androidgcs.views.ScrollBarView;
|
||||||
|
import org.openpilot.uavtalk.UAVDataObject;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
public class TuningActivity extends ObjectManagerActivity {
|
||||||
|
private final String TAG = TuningActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
private final boolean DEBUG = false;
|
||||||
|
|
||||||
|
private SmartSave smartSave;
|
||||||
|
|
||||||
|
/** Called when the activity is first created. */
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.tuning);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onOPConnected() {
|
||||||
|
super.onOPConnected();
|
||||||
|
|
||||||
|
if (DEBUG) Log.d(TAG, "onOPConnected()");
|
||||||
|
|
||||||
|
// Subscribe to updates from ManualControlCommand and show the values for crude feedback
|
||||||
|
UAVDataObject stabilizationSettings = (UAVDataObject) objMngr.getObject("StabilizationSettings");
|
||||||
|
|
||||||
|
smartSave = new SmartSave(objMngr, stabilizationSettings,
|
||||||
|
(Button) findViewById(R.id.saveBtn),
|
||||||
|
(Button) findViewById(R.id.applyBtn));
|
||||||
|
|
||||||
|
smartSave.addControlMapping((ScrollBarView) findViewById(R.id.rollRateKp), "RollRatePID", 0);
|
||||||
|
smartSave.addControlMapping((ScrollBarView) findViewById(R.id.rollRateKi), "RollRatePID", 1);
|
||||||
|
smartSave.addControlMapping((ScrollBarView) findViewById(R.id.pitchRateKp), "PitchRatePID", 0);
|
||||||
|
smartSave.addControlMapping((ScrollBarView) findViewById(R.id.pitchRateKi), "PitchRatePID", 1);
|
||||||
|
smartSave.addControlMapping((ScrollBarView) findViewById(R.id.rollKp), "RollPI", 0);
|
||||||
|
smartSave.addControlMapping((ScrollBarView) findViewById(R.id.pitchKp), "PitchPI", 0);
|
||||||
|
smartSave.refreshSettingsDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package org.openpilot.androidgcs.util;
|
||||||
|
|
||||||
|
public interface ObjectFieldMappable {
|
||||||
|
public double getValue();
|
||||||
|
public void setValue(double val);
|
||||||
|
}
|
256
androidgcs/src/org/openpilot/androidgcs/util/SmartSave.java
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* @file SmartSave.java
|
||||||
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||||
|
* @brief Provides a handler to provide robust apply and save for settings
|
||||||
|
* and updating of the UI when the object changes.
|
||||||
|
* @see The GNU Public License (GPL) Version 3
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openpilot.androidgcs.util;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.openpilot.uavtalk.UAVObject;
|
||||||
|
import org.openpilot.uavtalk.UAVObjectManager;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
public class SmartSave {
|
||||||
|
|
||||||
|
private final static String TAG = SmartSave.class.getSimpleName();
|
||||||
|
private final static boolean DEBUG = false;
|
||||||
|
|
||||||
|
//! Create a smart save button attached to the object manager and an apply and ave button
|
||||||
|
public SmartSave(UAVObjectManager objMngr, UAVObject obj, Button saveButton, Button applyButton) {
|
||||||
|
Assert.assertNotNull(objMngr);
|
||||||
|
this.objMngr = objMngr;
|
||||||
|
this.applyBtn = applyButton;
|
||||||
|
this.obj = obj;
|
||||||
|
|
||||||
|
Assert.assertNotNull(objMngr);
|
||||||
|
Assert.assertNotNull(obj);
|
||||||
|
|
||||||
|
obj.addUpdatedObserver(ObjectUpdated);
|
||||||
|
|
||||||
|
controlFieldMapping = new HashMap<ObjectFieldMappable,FieldPairing>();
|
||||||
|
|
||||||
|
if (saveButton != null) {
|
||||||
|
saveBtn = saveButton;
|
||||||
|
saveBtn.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
saveBtn = null;
|
||||||
|
|
||||||
|
if (applyButton != null) {
|
||||||
|
applyBtn = applyButton;
|
||||||
|
applyBtn.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
applyBtn = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Disconnect any listeners when this object is destroyed
|
||||||
|
public void disconnect() {
|
||||||
|
obj.removeUpdatedObserver(ObjectUpdated);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a control to this SmartSave object which maps between a particular control
|
||||||
|
* and a UAVO field.
|
||||||
|
* @param control The control to associate with
|
||||||
|
* @param fieldName The name of the UAVO field
|
||||||
|
* @param fieldIndex The index of the UAVO field
|
||||||
|
*/
|
||||||
|
public void addControlMapping(ObjectFieldMappable control, String fieldName, int fieldIndex) {
|
||||||
|
FieldPairing pairing = new FieldPairing(fieldName, fieldIndex);
|
||||||
|
controlFieldMapping.put(control, pairing);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Update the settings in the UI from the mappings
|
||||||
|
public void refreshSettingsDisplay() {
|
||||||
|
if (DEBUG) Log.d(TAG, "Refreshing display");
|
||||||
|
|
||||||
|
Set<ObjectFieldMappable> keys = controlFieldMapping.keySet();
|
||||||
|
Iterator<ObjectFieldMappable> iter = keys.iterator();
|
||||||
|
while(iter.hasNext()) {
|
||||||
|
ObjectFieldMappable mappable = iter.next();
|
||||||
|
FieldPairing field = controlFieldMapping.get(mappable);
|
||||||
|
mappable.setValue(field.getValue(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call applySettings() and then save them
|
||||||
|
* @return True if the save succeeded or false otherwise
|
||||||
|
*/
|
||||||
|
private boolean saveSettings() {
|
||||||
|
/*
|
||||||
|
* 1. Update object
|
||||||
|
* 2. Install listener on object persistence
|
||||||
|
* 3. Send save operation
|
||||||
|
* 4. Wait for completed
|
||||||
|
* 5. Remove listener
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 1. Update object
|
||||||
|
if(!applySettings())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
UAVObject persistence = objMngr.getObject("ObjectPersistence");
|
||||||
|
Assert.assertNotNull(persistence);
|
||||||
|
|
||||||
|
// 2. Install listener
|
||||||
|
persistence.addUpdatedObserver(ObjectPersistenceUpdated);
|
||||||
|
|
||||||
|
// 3. Send save operation
|
||||||
|
Long objId = obj.getObjID();
|
||||||
|
if (DEBUG) Log.d(TAG, "Saving object ID: " + objId);
|
||||||
|
persistence.getField("ObjectID").setValue(objId);
|
||||||
|
persistence.getField("Operation").setValue("Save");
|
||||||
|
persistence.getField("Selection").setValue("SingleObject");
|
||||||
|
persistence.updated();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Robustly apply the settings to the UAV
|
||||||
|
* @return True if the apply is ack'd, False if not
|
||||||
|
*/
|
||||||
|
private boolean applySettings() {
|
||||||
|
/*
|
||||||
|
* 1. Set the values from the fields into the object
|
||||||
|
* 2. Install the listener on the object
|
||||||
|
* 3. Update object
|
||||||
|
* 4. Wait for the acknowledgment or timeout
|
||||||
|
* 5. Uninstall the listener
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 1. Set the fields in the object from the UI
|
||||||
|
Set<ObjectFieldMappable> keys = controlFieldMapping.keySet();
|
||||||
|
Iterator<ObjectFieldMappable> iter = keys.iterator();
|
||||||
|
while(iter.hasNext()) {
|
||||||
|
ObjectFieldMappable mappable = iter.next();
|
||||||
|
FieldPairing field = controlFieldMapping.get(mappable);
|
||||||
|
field.setValue(obj,mappable.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Install the listener on the object
|
||||||
|
obj.addTransactionCompleted(ApplyCompleted);
|
||||||
|
|
||||||
|
// 3. Update the object
|
||||||
|
obj.updated();
|
||||||
|
|
||||||
|
// 4. Wait for acknowledgment
|
||||||
|
// TODO: Set up some semaphore with timeout
|
||||||
|
// sem.wait(1000);
|
||||||
|
|
||||||
|
// 5. Uninstall the listener
|
||||||
|
//obj.removeTransactionCompleted(ApplyCompleted);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Private class to store the field mapping information
|
||||||
|
private class FieldPairing {
|
||||||
|
FieldPairing(String fieldName, int fieldIndex) {
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
this.fieldIndex = fieldIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Update the field in the UAVO
|
||||||
|
void setValue(UAVObject obj, double value) {
|
||||||
|
Assert.assertNotNull(obj);
|
||||||
|
obj.getField(fieldName).setDouble(value,fieldIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Get the value from the UAVO field
|
||||||
|
double getValue(UAVObject obj) {
|
||||||
|
double val = obj.getField(fieldName).getDouble(fieldIndex);
|
||||||
|
if (DEBUG) Log.d(TAG, "Getting value from: " + fieldName + " " + val);
|
||||||
|
return obj.getField(fieldName).getDouble(fieldIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Cache the name of the field
|
||||||
|
private final String fieldName;
|
||||||
|
|
||||||
|
//! Cache the field index
|
||||||
|
private final int fieldIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Installed on monitored object to know when an object is updated
|
||||||
|
private final Observer ApplyCompleted = new Observer() {
|
||||||
|
@Override
|
||||||
|
public void update(Observable observable, Object data) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Apply called");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Installed on monitored object to know when an object is updated
|
||||||
|
private final Observer ObjectUpdated = new Observer() {
|
||||||
|
@Override
|
||||||
|
public void update(Observable observable, Object data) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Object updated");
|
||||||
|
refreshSettingsDisplay();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Installed on object persistence to know when save completes
|
||||||
|
private final Observer ObjectPersistenceUpdated = new Observer() {
|
||||||
|
@Override
|
||||||
|
public void update(Observable observable, Object data) {
|
||||||
|
if (DEBUG) Log.d(TAG, "Object persistence updated");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Map of all the UAVO field <-> control mappings. The key is the control.
|
||||||
|
private final Map<ObjectFieldMappable,FieldPairing> controlFieldMapping;
|
||||||
|
|
||||||
|
//! Handle to the object manager
|
||||||
|
private final UAVObjectManager objMngr;
|
||||||
|
|
||||||
|
//! Handle to the apply button
|
||||||
|
private Button applyBtn;
|
||||||
|
|
||||||
|
//! Handle to the save button
|
||||||
|
private Button saveBtn;
|
||||||
|
|
||||||
|
//! Handle to the UAVO this class works with
|
||||||
|
private final UAVObject obj;
|
||||||
|
|
||||||
|
}
|
129
androidgcs/src/org/openpilot/androidgcs/views/ScrollBarView.java
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package org.openpilot.androidgcs.views;
|
||||||
|
|
||||||
|
import org.openpilot.androidgcs.R;
|
||||||
|
import org.openpilot.androidgcs.util.ObjectFieldMappable;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.GridLayout;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
public class ScrollBarView extends GridLayout implements ObjectFieldMappable {
|
||||||
|
|
||||||
|
private final static String TAG = ScrollBarView.class.getSimpleName();
|
||||||
|
|
||||||
|
private final TextView lbl;
|
||||||
|
private final EditText edit;
|
||||||
|
private final SeekBar bar;
|
||||||
|
private double value;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private final double SCALE = 1000000;
|
||||||
|
|
||||||
|
public ScrollBarView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
|
||||||
|
Log.d(TAG, "Scroll bar init called");
|
||||||
|
|
||||||
|
setOrientation(LinearLayout.VERTICAL);
|
||||||
|
setColumnCount(2);
|
||||||
|
|
||||||
|
lbl = new TextView(context);
|
||||||
|
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.setting_attributes, 0, 0);
|
||||||
|
lbl.setText(ta.getString(R.styleable.setting_attributes_setting_name));
|
||||||
|
addView(lbl, new GridLayout.LayoutParams(spec(0), spec(0)));
|
||||||
|
|
||||||
|
edit = new EditText(context);
|
||||||
|
addView(edit, new GridLayout.LayoutParams(spec(0), spec(1)));
|
||||||
|
|
||||||
|
bar = new SeekBar(context);
|
||||||
|
addView(bar, new GridLayout.LayoutParams(spec(1), spec(0,2)));
|
||||||
|
|
||||||
|
ta = context.obtainStyledAttributes(attrs, R.styleable.setting_attributes, 0, 0);
|
||||||
|
final double max = ta.getFloat(R.styleable.setting_attributes_max_value,0);
|
||||||
|
bar.setMax((int) (SCALE * max));
|
||||||
|
|
||||||
|
// Update the value when the progress bar changes
|
||||||
|
bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress,
|
||||||
|
boolean fromUser) {
|
||||||
|
value = progress / SCALE;
|
||||||
|
edit.setText(Double.toString(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update the value when the edit box changes
|
||||||
|
edit.addTextChangedListener(new TextWatcher() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
value = Double.parseDouble(s.toString());
|
||||||
|
bar.setProgress((int) (SCALE * value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count,
|
||||||
|
int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before,
|
||||||
|
int count) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setPadding(5,5,5,5);
|
||||||
|
|
||||||
|
setMinimumWidth(300);
|
||||||
|
setValue(0.0035);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String n)
|
||||||
|
{
|
||||||
|
name = n;
|
||||||
|
lbl.setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
|
||||||
|
// This shouldn't be needed if I could make this scroll bar
|
||||||
|
// automagically span both columns
|
||||||
|
android.view.ViewGroup.LayoutParams param = bar.getLayoutParams();
|
||||||
|
param.width = (int) (getMeasuredWidth() * 0.9);
|
||||||
|
|
||||||
|
// Force the label to half the page width
|
||||||
|
param = lbl.getLayoutParams();
|
||||||
|
param.width = getMeasuredWidth() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setValue(double val) {
|
||||||
|
value = val;
|
||||||
|
edit.setText(Double.toString(value));
|
||||||
|
bar.setProgress((int) (SCALE * value));
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 823 B After Width: | Height: | Size: 849 B |
BIN
artwork/Android/hdpi/ic_tuning.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
artwork/Android/hdpi/im_pfd_fixed.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 9.7 KiB |
BIN
artwork/Android/hdpi/im_pfd_reticule.png
Normal file
After Width: | Height: | Size: 18 KiB |