1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-29 14:52:12 +01:00

Merge branch 'android' into sim_android

Conflicts:
	androidgcs/AndroidManifest.xml
	androidgcs/res/layout/gcs_home.xml
	androidgcs/res/layout/pfd.xml
	androidgcs/res/layout/system_alarms.xml
	androidgcs/src/org/openpilot/androidgcs/AttitudeView.java
	androidgcs/src/org/openpilot/androidgcs/BluetoothDevicePreference.java
	androidgcs/src/org/openpilot/androidgcs/CompassView.java
	androidgcs/src/org/openpilot/androidgcs/Controller.java
	androidgcs/src/org/openpilot/androidgcs/HomePage.java
	androidgcs/src/org/openpilot/androidgcs/Logger.java
	androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java
	androidgcs/src/org/openpilot/androidgcs/ObjectEditor.java
	androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java
	androidgcs/src/org/openpilot/androidgcs/Preferences.java
	androidgcs/src/org/openpilot/androidgcs/SystemAlarmActivity.java
	androidgcs/src/org/openpilot/androidgcs/TelemetryWidget.java
	androidgcs/src/org/openpilot/androidgcs/UAVLocation.java
	androidgcs/src/org/openpilot/uavtalk/Telemetry.java
	androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java
	androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java
	androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java
	androidgcs/src/org/openpilot/uavtalk/UAVObject.java
	androidgcs/src/org/openpilot/uavtalk/UAVObjectField.java
	androidgcs/src/org/openpilot/uavtalk/UAVObjectManager.java
	androidgcs/src/org/openpilot/uavtalk/UAVTalk.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/AltitudeHoldSettings.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/FirmwareIAPObj.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatterySettings.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightBatteryState.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/FlightStatus.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/HomeLocation.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/HwSettings.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/ManualControlSettings.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/OveroSyncStats.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/PositionActual.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/RevoCalibration.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/SystemAlarms.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/TaskInfo.java
	androidgcs/src/org/openpilot/uavtalk/uavobjects/UAVObjectsInitialize.java
	flight/Modules/GPS/GPS.c
This commit is contained in:
James Cotton 2012-08-08 15:27:40 -05:00
commit f530702ce9
103 changed files with 10399 additions and 769 deletions

View File

@ -1,5 +1,13 @@
Short summary of changes. For a complete list see the git log.
2012-07-20
AeroSimRC simulator plugin is now included into the Windows distribution
(will be installed into .../OpenPilot/misc/AeroSIM-RC directory). Still
being an experimental development tool, it could be used to play with
HITL version 2. Other platforms include udp_test utility which can be
used to check the connectivity with AeroSimRC plugin running on Windows
machine.
2012-07-10
On Windows the installation mode was changed from per-user to per-machine
(for all users) installation. It is recommended to completely uninstall

View File

@ -24,7 +24,7 @@
</activity>
<activity android:name="ObjectBrowser" android:label="@string/object_browser_name" />
<activity android:name="PFD" android:label="PFD" />
<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" />
@ -46,6 +46,6 @@
android:resource="@xml/telemetry_widget_info" />
</receiver>
<service android:name=".OPTelemetryService"></service>
<service android:name="org.openpilot.androidgcs.telemetry.OPTelemetryService"></service>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -33,9 +33,9 @@
android:id="@+id/launch_pfd"
android:layout_width="132dp"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_column="0"
android:layout_gravity="center"
android:layout_row="0"
android:layout_row="2"
android:layout_rowSpan="2"
android:background="@android:color/transparent"
android:drawableTop="@drawable/ic_pfd"
@ -45,7 +45,7 @@
android:id="@+id/launch_controller"
android:layout_width="132dp"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_column="1"
android:layout_gravity="right"
android:layout_row="2"
android:layout_rowSpan="2"
@ -57,9 +57,9 @@
android:id="@+id/launch_logger"
android:layout_width="132dp"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_column="0"
android:layout_gravity="right"
android:layout_row="2"
android:layout_row="4"
android:layout_rowSpan="2"
android:background="@android:color/transparent"
android:drawableTop="@drawable/ic_logging"
@ -69,9 +69,9 @@
android:id="@+id/launch_alarms"
android:layout_width="132dp"
android:layout_height="wrap_content"
android:layout_column="2"
android:layout_column="1"
android:layout_gravity="right"
android:layout_row="2"
android:layout_row="4"
android:layout_rowSpan="2"
android:background="@android:color/transparent"
android:drawableTop="@drawable/ic_alarms"

View File

@ -3,14 +3,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<org.openpilot.androidgcs.CompassView
android:id="@+id/compass_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<org.openpilot.androidgcs.AttitudeView
android:id="@+id/attitude_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@ -4,11 +4,16 @@
android:layout_height="match_parent"
android:layout_gravity="center" >
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/system_alarms_status"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" />
<fragment
android:name="org.openpilot.androidgcs.fragments.SystemAlarmsFragment"
android:id="@+id/viewer"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
<fragment
android:name="org.openpilot.androidgcs.fragments.PFD"
android:id="@+id/pfd"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ProgressBar
android:id="@+id/progressBar3"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/system_alarms_fragment_field"
android:layout_width="200dip"
android:layout_height="match_parent" />
</LinearLayout>

View File

@ -1,89 +1,117 @@
/**
******************************************************************************
* @file AttitudeView.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief A view for UAV attitude.
* @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;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
public class AttitudeView extends View {
private Paint markerPaint;
public AttitudeView(Context context) {
super(context);
initAttitudeView();
}
public AttitudeView(Context context, AttributeSet ats, int defaultStyle) {
public AttitudeView(Context context, AttributeSet ats, int defaultStyle) {
super(context, ats, defaultStyle);
initAttitudeView();
}
public AttitudeView(Context context, AttributeSet ats) {
public AttitudeView(Context context, AttributeSet ats) {
super(context, ats);
initAttitudeView();
}
protected void initAttitudeView() {
protected void initAttitudeView() {
setFocusable(true);
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
markerPaint.setColor(getContext().getResources().getColor(
R.color.marker_color));
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(R.color.background_color);
circlePaint.setStrokeWidth(1);
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
Resources r = this.getResources();
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(r.getColor(R.color.text_color));
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
markerPaint.setColor(r.getColor(R.color.marker_color));
}
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
int d = Math.min(measuredWidth, measuredHeight);
int d = Math.min(measuredWidth, measuredHeight);
setMeasuredDimension(d/2, d/2);
}
private int measure(int measureSpec) {
private int measure(int measureSpec) {
int result = 0;
// Decode the measurement specifications.
// Decode the measurement specifications.
int specMode = MeasureSpec.getMode(measureSpec);
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.UNSPECIFIED) { // Return a default size of 200 if no bounds are specified.
result = 200;
} else {
// As you want to fill the available space
// always return the full available bounds.
} else {
// As you want to fill the available space
// always return the full available bounds.
result = specSize;
}
return result;
}
private double roll;
public void setRoll(double roll) {
this.roll = roll;
}
private double pitch;
public void setPitch(double d) {
this.pitch = d;
}
private float roll;
public void setRoll(double roll) {
this.roll = (float) roll;
}
// Drawing related code
private Paint markerPaint;
private Paint textPaint;
private Paint circlePaint;
private float pitch;
public void setPitch(double d) {
this.pitch = (float) d;
}
@Override
protected void onDraw(Canvas canvas) {
int px = getMeasuredWidth() / 2;
int py = getMeasuredHeight() /2 ;
int radius = Math.min(px, py);
canvas.drawLine(px,py, (int) (px+radius * Math.cos(roll)), (int) (py + radius * Math.sin(roll)), markerPaint);
canvas.drawLine(px,py, (int) (px+radius * Math.cos(pitch)), (int) (py + radius * Math.sin(pitch)), markerPaint);
final int PX = getMeasuredWidth() / 2;
final int PY = getMeasuredHeight() / 2;
// TODO: Figure out why these magic numbers are needed to center it
final int WIDTH = 600;
final int HEIGHT = 600;
final int DEG_TO_PX = 10; // Magic number for how to scale pitch
canvas.save(0);
canvas.rotate(-roll, PX, PY);
canvas.translate(0, pitch * DEG_TO_PX);
Drawable horizon = getContext().getResources().getDrawable(
R.drawable.im_pfd_horizon);
// This puts the image at the center of the PFD canvas (after it was
// translated)
horizon.setBounds(-(WIDTH - PX) / 2, -(HEIGHT - PY) / 2, WIDTH, HEIGHT);
horizon.draw(canvas);
canvas.restore();
}
}

View File

@ -1,26 +1,59 @@
/**
******************************************************************************
* @file BluetoothDevicePreference.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief A dialog in the preferences options that shows the paired BT
* devices.
* @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;
import android.bluetooth.*;
import java.util.Set;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.preference.ListPreference;
import android.util.AttributeSet;
import java.util.Set;
public class BluetoothDevicePreference extends ListPreference {
public BluetoothDevicePreference(Context context, AttributeSet attrs) {
super(context, attrs);
BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter();
if (bta == null)
return; // BT not supported
Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
CharSequence[] entries = new CharSequence[pairedDevices.size()];
CharSequence[] entryValues = new CharSequence[pairedDevices.size()];
int i = 0;
for (BluetoothDevice dev : pairedDevices) {
entries[i] = dev.getName();
entryValues[i] = dev.getAddress();
i++;
if (pairedDevices.size() == 0) {
entries[0] = "No Devices";
entryValues[0] = "";
} else {
int i = 0;
for (BluetoothDevice dev : pairedDevices) {
entries[i] = dev.getName();
entryValues[i] = dev.getAddress();
i++;
}
}
setEntries(entries);
setEntryValues(entryValues);

View File

@ -1,3 +1,27 @@
/**
******************************************************************************
* @file CompassView.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief A view of the compass heading.
* @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;
import android.content.Context;
@ -14,104 +38,104 @@ public class CompassView extends View {
initCompassView();
}
public CompassView(Context context, AttributeSet ats, int defaultStyle) {
public CompassView(Context context, AttributeSet ats, int defaultStyle) {
super(context, ats, defaultStyle);
initCompassView();
}
public CompassView(Context context, AttributeSet ats) {
public CompassView(Context context, AttributeSet ats) {
super(context, ats);
initCompassView();
}
protected void initCompassView() {
protected void initCompassView() {
setFocusable(true);
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(R.color.background_color);
circlePaint.setStrokeWidth(1);
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(getResources().getColor(R.color.background_color));
circlePaint.setStrokeWidth(1);
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
Resources r = this.getResources();
northString = r.getString(R.string.cardinal_north);
eastString = r.getString(R.string.cardinal_east);
southString = r.getString(R.string.cardinal_south);
Resources r = this.getResources();
northString = r.getString(R.string.cardinal_north);
eastString = r.getString(R.string.cardinal_east);
southString = r.getString(R.string.cardinal_south);
westString = r.getString(R.string.cardinal_west);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(r.getColor(R.color.text_color));
textHeight = (int)textPaint.measureText("yY");
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
markerPaint.setColor(r.getColor(R.color.marker_color));
markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
markerPaint.setColor(r.getColor(R.color.marker_color));
}
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = measure(widthMeasureSpec);
int measuredWidth = measure(widthMeasureSpec);
int measuredHeight = measure(heightMeasureSpec);
int d = Math.min(measuredWidth, measuredHeight);
int d = Math.min(measuredWidth, measuredHeight);
setMeasuredDimension(d/2, d/2);
}
private int measure(int measureSpec) {
private int measure(int measureSpec) {
int result = 0;
// Decode the measurement specifications.
// Decode the measurement specifications.
int specMode = MeasureSpec.getMode(measureSpec);
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.UNSPECIFIED) { // Return a default size of 200 if no bounds are specified.
result = 200;
} else {
// As you want to fill the available space
// always return the full available bounds.
} else {
// As you want to fill the available space
// always return the full available bounds.
result = specSize;
}
return result;
}
private double bearing;
public void setBearing(double bearing) {
public void setBearing(double bearing) {
this.bearing = bearing;
}
}
// Drawing related code
private Paint markerPaint;
private Paint textPaint;
private Paint circlePaint;
private String northString;
private String eastString;
private String southString;
private String westString;
private Paint markerPaint;
private Paint textPaint;
private Paint circlePaint;
private String northString;
private String eastString;
private String southString;
private String westString;
private int textHeight;
@Override
protected void onDraw(Canvas canvas) {
int px = getMeasuredWidth() / 2;
int px = getMeasuredWidth() / 2;
int py = getMeasuredHeight() /2 ;
int radius = Math.min(px, py);
// Draw the background
// Draw the background
canvas.drawCircle(px, py, radius, circlePaint);
// Rotate our perspective so that the ÔtopÕ is
// facing the current bearing.
canvas.save();
// Rotate our perspective so that the ÔtopÕ is
// facing the current bearing.
canvas.save();
canvas.rotate((float) -bearing, px, py);
int textWidth = (int)textPaint.measureText("W");
int cardinalX = px-textWidth/2;
int textWidth = (int)textPaint.measureText("W");
int cardinalX = px-textWidth/2;
int cardinalY = py-radius+textHeight;
// Draw the marker every 15 degrees and text every 45.
// Draw the marker every 15 degrees and text every 45.
for (int i = 0; i < 24; i++) {
// Draw a marker.
// Draw a marker.
canvas.drawLine(px, py-radius, px, py-radius+10, markerPaint);
canvas.save();
canvas.save();
canvas.translate(0, textHeight);
// Draw the cardinal points
// Draw the cardinal points
if (i % 6 == 0) {
String dirString = null;
switch (i) {
case 0 : {
dirString = northString;
int arrowY = 2*textHeight;
dirString = northString;
int arrowY = 2*textHeight;
canvas.drawLine(px, arrowY, px-5, 3*textHeight, markerPaint);
canvas.drawLine(px, arrowY, px+5, 3*textHeight, markerPaint);
break;
@ -122,18 +146,18 @@ public class CompassView extends View {
}
canvas.drawText(dirString, cardinalX, cardinalY, textPaint);
}
else if (i % 3 == 0) {
// Draw the text every alternate 45deg
String angle = String.valueOf(i*15);
else if (i % 3 == 0) {
// Draw the text every alternate 45deg
String angle = String.valueOf(i*15);
float angleTextWidth = textPaint.measureText(angle);
int angleTextX = (int)(px-angleTextWidth/2);
int angleTextY = py-radius+textHeight;
int angleTextX = (int)(px-angleTextWidth/2);
int angleTextY = py-radius+textHeight;
canvas.drawText(angle, angleTextX, angleTextY, textPaint);
}
canvas.restore();
canvas.rotate(15, px, py);
}
canvas.restore();
canvas.restore();
}
}

View File

@ -1,3 +1,28 @@
/**
******************************************************************************
* @file Controller.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Allows controlling the UAV over telemetry. This activity
* pushes the appropriate settings to the remote device for it to
* listen to the GCSReceiver.
* @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;
import java.util.Observable;
@ -9,16 +34,16 @@ import org.openpilot.uavtalk.UAVDataObject;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectField;
import com.MobileAnarchy.Android.Widgets.Joystick.DualJoystickView;
import com.MobileAnarchy.Android.Widgets.Joystick.JoystickMovedListener;
import com.MobileAnarchy.Android.Widgets.Joystick.JoystickView;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.MobileAnarchy.Android.Widgets.Joystick.DualJoystickView;
import com.MobileAnarchy.Android.Widgets.Joystick.JoystickMovedListener;
import com.MobileAnarchy.Android.Widgets.Joystick.JoystickView;
public class Controller extends ObjectManagerActivity {
private final String TAG = "Controller";
@ -29,18 +54,18 @@ public class Controller extends ObjectManagerActivity {
private final int PITCH_CHANNEL = 2;
private final int YAW_CHANNEL = 3;
private final int FLIGHTMODE_CHANNEL = 4;
private final int CHANNEL_MIN = 1000;
private final int CHANNEL_MAX = 2000;
private final int CHANNEL_NEUTRAL = 1500;
private final int CHANNEL_NEUTRAL_THROTTLE = 1100;
private double throttle = 0.1, roll = 0.1, pitch = -0.1, yaw = 0;
private boolean updated;
private boolean leftJoystickHeld, rightJoystickHeld;
Timer sendTimer = new Timer();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
@ -63,7 +88,7 @@ public class Controller extends ObjectManagerActivity {
}
}
};
@Override
void onOPConnected() {
super.onOPConnected();
@ -74,43 +99,48 @@ public class Controller extends ObjectManagerActivity {
manualControl.addUpdatedObserver(updatedObserver);
}
UAVDataObject manualControlSettings = (UAVDataObject) objMngr.getObject("ManualControlSettings");
if(manualControlSettings != null) {
Log.d(TAG, "Requested settings update");
manualControlSettings.addUpdatedObserver(updatedObserver);
manualControlSettings.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 = (double) tilt / MOVEMENT_RANGE;
yaw = (double) pan / MOVEMENT_RANGE;
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 = (double) (-tilt + (MOVEMENT_RANGE -5)) / (MOVEMENT_RANGE - 5);
throttle = (-tilt + (MOVEMENT_RANGE -5)) / (MOVEMENT_RANGE - 5);
throttle *= 0.5;
if (throttle < 0)
throttle = -1;
roll = (double) pan / MOVEMENT_RANGE;
roll = pan / MOVEMENT_RANGE;
rightJoystickHeld = true;
}
@Override
public void OnReleased() { rightJoystickHeld = false; throttle = -1; updated = true; }
@Override
public void OnReturnedToCenter() { }
}) ;
TimerTask controllerTask = new TimerTask() {
@Override
public void run() {
uavobjHandler.post(new Runnable() {
@Override
@ -152,17 +182,19 @@ public class Controller extends ObjectManagerActivity {
* The callbacks from the UAVOs must run in the correct thread to update the
* UI. This is what using a runnable does.
*/
final Handler uavobjHandler = new Handler();
final Handler uavobjHandler = new Handler();
final Runnable updateText = new Runnable() {
@Override
public void run() {
updateManualControl();
}
};
private final Observer updatedObserver = new Observer() {
@Override
public void update(Observable observable, Object data) {
uavobjHandler.post(updateText);
}
}
};
/**
@ -174,33 +206,33 @@ public class Controller extends ObjectManagerActivity {
if (manualView != null && manualControl != null)
manualView.setText(manualControl.toStringData());
}
/**
* Active GCS receiver mode
*/
private void activateGcsReceiver() {
UAVObject manualControlSettings = objMngr.getObject("ManualControlSettings");
if (manualControlSettings == null) {
Toast.makeText(this, "Failed to get manual control settings", Toast.LENGTH_SHORT).show();
return;
}
UAVObjectField channelGroups = manualControlSettings.getField("ChannelGroups");
UAVObjectField channelNumber = manualControlSettings.getField("ChannelNumber");
UAVObjectField channelMax = manualControlSettings.getField("ChannelMax");
UAVObjectField channelNeutral = manualControlSettings.getField("ChannelNeutral");
UAVObjectField channelMin = manualControlSettings.getField("ChannelMin");
if (channelGroups == null || channelMax == null || channelNeutral == null ||
if (channelGroups == null || channelMax == null || channelNeutral == null ||
channelMin == null || channelNumber == null) {
Toast.makeText(this, "Manual control settings not formatted correctly", Toast.LENGTH_SHORT).show();
return;
}
/* Configure the manual control module how the GCS controller expects
* This order MUST correspond to the enumeration order of ChannelNumber in
* This order MUST correspond to the enumeration order of ChannelNumber in
* ManualControlSettings.
*/
*/
int channels[] = { THROTTLE_CHANNEL, ROLL_CHANNEL, PITCH_CHANNEL, YAW_CHANNEL, FLIGHTMODE_CHANNEL };
for (int i = 0; i < channels.length; i++) {
channelGroups.setValue("GCS", channels[i]);
@ -216,23 +248,23 @@ public class Controller extends ObjectManagerActivity {
break;
}
}
// Send settings to the UAV
manualControlSettings.updated();
}
/**
* Scale the channels to the output range the flight controller expects
*/
private float scaleChannel(double in, double neutral) {
private float scaleChannel(double in, double neutral) {
// Check bounds
if (in > 1)
if (in > 1)
in = 1;
if (in < -1)
in = -1;
if (in >= 0)
return (float) (neutral + (CHANNEL_MAX - neutral) * in);
return (float) (neutral + (neutral - CHANNEL_MIN) * in);

View File

@ -1,3 +1,26 @@
/**
******************************************************************************
* @file HomePage.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Main launch page for the Android GCS actitivies
* @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;
import android.content.Intent;
@ -10,48 +33,54 @@ public class HomePage extends ObjectManagerActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gcs_home);
super.onCreate(savedInstanceState);
setContentView(R.layout.gcs_home);
Button objectBrowser = (Button) findViewById(R.id.launch_object_browser);
objectBrowser.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(HomePage.this, ObjectBrowser.class));
}
startActivity(new Intent(HomePage.this, ObjectBrowser.class));
}
});
Button pfd = (Button) findViewById(R.id.launch_pfd);
pfd.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(HomePage.this, PFD.class));
}
startActivity(new Intent(HomePage.this, PfdActivity.class));
}
});
Button location = (Button) findViewById(R.id.launch_location);
location.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(HomePage.this, UAVLocation.class));
}
startActivity(new Intent(HomePage.this, UAVLocation.class));
}
});
Button controller = (Button) findViewById(R.id.launch_controller);
controller.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(HomePage.this, Controller.class));
}
startActivity(new Intent(HomePage.this, Controller.class));
}
});
Button logger = (Button) findViewById(R.id.launch_logger);
logger.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(HomePage.this, Logger.class));
startActivity(new Intent(HomePage.this, Logger.class));
}
});
Button alarms = (Button) findViewById(R.id.launch_alarms);
alarms.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
startActivity(new Intent(HomePage.this, SystemAlarmActivity.class));
startActivity(new Intent(HomePage.this, SystemAlarmActivity.class));
}
});
}

View File

@ -1,3 +1,27 @@
/**
******************************************************************************
* @file Logger.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Controller for logging data as well as interface for getting that
* data on and off the tablet.
* @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;
import java.io.File;
@ -16,17 +40,17 @@ import android.widget.TextView;
public class Logger extends ObjectManagerActivity {
final String TAG = "Logger";
final boolean VERBOSE = false;
final boolean DEBUG = true;
private File file;
private boolean logging;
private FileOutputStream fileStream;
private UAVTalk uavTalk;
private int writtenBytes;
private int writtenObjects;
@ -36,15 +60,15 @@ public class Logger extends ObjectManagerActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.logger);
}
private void onStartLogging() {
File root = Environment.getExternalStorageDirectory();
Date d = new Date();
String date = (new SimpleDateFormat("yyyyMMdd_hhmmss")).format(d);
String fileName = "/logs/logs_" + date + ".opl";
file = new File(root, fileName);
if (DEBUG) Log.d(TAG, "Trying for file: " + file.getAbsolutePath());
try {
@ -60,10 +84,10 @@ public class Logger extends ObjectManagerActivity {
} catch (IOException e) {
Log.e(TAG, "Could not write file " + e.getMessage());
}
// TODO: if logging succeeded then retrieve all settings
}
private void onStopLogging() {
if (DEBUG) Log.d(TAG, "Stop logging");
logging = false;
@ -74,11 +98,11 @@ public class Logger extends ObjectManagerActivity {
e.printStackTrace();
}
}
@Override
void onOPConnected() {
super.onOPConnected();
if (DEBUG) Log.d(TAG, "onOPConnected()");
onStartLogging();
registerObjectUpdates(objMngr.getObjects());
@ -104,7 +128,7 @@ public class Logger extends ObjectManagerActivity {
onStartLogging();
}
/**
* Called whenever any objects subscribed to via registerObjects
* Called whenever any objects subscribed to via registerObjects
*/
@Override
protected void objectUpdated(UAVObject obj) {
@ -126,18 +150,18 @@ public class Logger extends ObjectManagerActivity {
fileStream.write((byte)(size & 0x0000ff0000000000l) >> 40);
fileStream.write((byte)(size & 0x00ff000000000000l) >> 48);
fileStream.write((byte)(size & 0xff00000000000000l) >> 56);
uavTalk.sendObject(obj, false, false);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
writtenBytes += obj.getNumBytes();
writtenObjects ++;
((TextView) findViewById(R.id.logger_number_of_bytes)).setText(Integer.valueOf(writtenBytes).toString());
((TextView) findViewById(R.id.logger_number_of_objects)).setText(Integer.valueOf(writtenObjects).toString());
((TextView) findViewById(R.id.logger_number_of_objects)).setText(Integer.valueOf(writtenObjects).toString());
}
}
}

View File

@ -1,3 +1,27 @@
/**
******************************************************************************
* @file ObjectBrowser.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief A simple object browser for UAVOs that allows viewing, editing,
* loading and saving.
* @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;
import java.util.ArrayList;
@ -6,6 +30,9 @@ import java.util.ListIterator;
import java.util.Observable;
import java.util.Observer;
import org.openpilot.uavtalk.UAVDataObject;
import org.openpilot.uavtalk.UAVObject;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
@ -16,6 +43,7 @@ import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
@ -23,10 +51,6 @@ import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import org.openpilot.uavtalk.UAVDataObject;
import org.openpilot.uavtalk.UAVObject;
public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPreferenceChangeListener {
@ -36,24 +60,26 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref
SharedPreferences prefs;
ArrayAdapter<UAVDataObject> adapter;
List<UAVDataObject> allObjects;
final Handler uavobjHandler = new Handler();
final Handler uavobjHandler = new Handler();
final Runnable updateText = new Runnable() {
@Override
public void run() {
updateObject();
}
};
private final Observer updatedObserver = new Observer() {
@Override
public void update(Observable observable, Object data) {
uavobjHandler.post(updateText);
}
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.object_browser);
setContentView(R.layout.object_browser);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
super.onCreate(savedInstanceState);
@ -63,7 +89,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref
void onOPConnected() {
super.onOPConnected();
Log.d(TAG, "onOPConnected()");
OnCheckedChangeListener checkListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
@ -71,10 +97,10 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref
updateList();
}
};
((CheckBox) findViewById(R.id.dataCheck)).setOnCheckedChangeListener(checkListener);
((CheckBox) findViewById(R.id.settingsCheck)).setOnCheckedChangeListener(checkListener);
((Button) findViewById(R.id.editButton)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@ -87,7 +113,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref
}
}
});
((Button) findViewById(R.id.object_load_button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@ -100,7 +126,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref
objPer.getField("ObjectID").setValue(allObjects.get(selected_index).getObjID());
objPer.getField("InstanceID").setValue(0);
objPer.updated();
allObjects.get(selected_index).updateRequested();
}
}
@ -137,6 +163,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref
objects.setAdapter(adapter);
objects.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
@ -149,9 +176,9 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref
updateObject();
}
});
}
private void updateObject() {
//adapter.notifyDataSetChanged();
TextView text = (TextView) findViewById(R.id.object_information);
@ -161,6 +188,7 @@ public class ObjectBrowser extends ObjectManagerActivity implements OnSharedPref
Log.d(TAG,"Update called but invalid index: " + selected_index);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
// TODO Auto-generated method stub

View File

@ -1,3 +1,26 @@
/**
******************************************************************************
* @file ObjectEditor.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief A popup dialog for editing the contents of a UAVO.
* @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;
import java.util.List;
@ -17,7 +40,7 @@ import android.widget.Toast;
public class ObjectEditor extends ObjectManagerActivity {
static final String TAG = "ObjectEditor";
static final String TAG = "ObjectEditor";
String objectName;
long objectID;
long instID;
@ -58,6 +81,7 @@ public class ObjectEditor extends ObjectManagerActivity {
});
}
@Override
public void onOPConnected() {
UAVObject obj = objMngr.getObject(objectID, instID);
if (obj == null) {
@ -86,15 +110,15 @@ public class ObjectEditor extends ObjectManagerActivity {
Toast.makeText(this, "Save failed", Toast.LENGTH_LONG).show();
return;
}
long thisId = objectID < 0 ? ((Long) 0x100000000l) + objectID : objectID;
long thisId = objectID < 0 ? 0x100000000l + objectID : objectID;
objPer.getField("Operation").setValue("Save");
objPer.getField("Selection").setValue("SingleObject");
Log.d(TAG,"Saving with object id: " + objectID + " swapped to " + thisId);
objPer.getField("ObjectID").setValue(thisId);
objPer.getField("InstanceID").setValue(instID);
objPer.updated();
Toast.makeText(this, "Save succeeded", Toast.LENGTH_LONG).show();
}
@ -125,7 +149,7 @@ public class ObjectEditor extends ObjectManagerActivity {
default:
String val = ((EditText) editView.fields.get(field_idx)).getText().toString();
Double num = Double.parseDouble(val);
Log.e(TAG, "Updating field: " + field.getName() + " value: " + num);
field.setValue(num, i);
break;

View File

@ -1,3 +1,32 @@
/**
******************************************************************************
* @file ObjectManagerActivity.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Base object for all activies that use the UAVObjectManager.
* This class takes care of binding to the service and getting the
* object manager as well as setting up callbacks to the objects of
* interest that run on the UI thread.
* Implements a new Android lifecycle: onOPConnected() / onOPDisconnected()
* which indicates when a valid telemetry is established as well as a
* valid object manager handle.
* @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;
import java.util.List;
@ -5,8 +34,10 @@ import java.util.ListIterator;
import java.util.Observable;
import java.util.Observer;
import org.openpilot.androidgcs.OPTelemetryService.LocalBinder;
import org.openpilot.androidgcs.OPTelemetryService.TelemTask;
import org.openpilot.androidgcs.fragments.ObjectManagerFragment;
import org.openpilot.androidgcs.telemetry.OPTelemetryService;
import org.openpilot.androidgcs.telemetry.OPTelemetryService.LocalBinder;
import org.openpilot.androidgcs.telemetry.OPTelemetryService.TelemTask;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectManager;
@ -32,7 +63,7 @@ public abstract class ObjectManagerActivity extends Activity {
private static int LOGLEVEL = 0;
// private static boolean WARN = LOGLEVEL > 1;
private static boolean DEBUG = LOGLEVEL > 0;
//! Object manager, populated by parent for the children to use
UAVObjectManager objMngr;
//! Indicates if the activity is bound to the service
@ -45,16 +76,17 @@ public abstract class ObjectManagerActivity extends Activity {
BroadcastReceiver connectedReceiver;
//! Indicate if this activity has already connected it's telemetry callbacks
private boolean telemetryStatsConnected = false;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
connectedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received intent");
if (DEBUG)
Log.d(TAG, "Received intent");
TelemTask task;
if(intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_CONNECTED) == 0) {
if(binder == null)
@ -71,31 +103,32 @@ public abstract class ObjectManagerActivity extends Activity {
onOPDisconnected();
Log.d(TAG, "Disonnected()");
}
}
}
};
IntentFilter filter = new IntentFilter();
filter.addCategory(OPTelemetryService.INTENT_CATEGORY_GCS);
filter.addAction(OPTelemetryService.INTENT_ACTION_CONNECTED);
filter.addAction(OPTelemetryService.INTENT_ACTION_DISCONNECTED);
registerReceiver(connectedReceiver, filter);
}
/**
* Called whenever any objects subscribed to via registerObjects
* Called whenever any objects subscribed to via registerObjects
*/
protected void objectUpdated(UAVObject obj) {
}
/**
* A message handler and a custom Observer to use it which calls
* objectUpdated with the right object type
*/
final Handler uavobjHandler = new Handler();
private class UpdatedObserver implements Observer {
final Handler uavobjHandler = new Handler();
private class ActivityUpdatedObserver implements Observer {
UAVObject obj;
UpdatedObserver(UAVObject obj) { this.obj = obj; };
ActivityUpdatedObserver(UAVObject obj) { this.obj = obj; };
@Override
public void update(Observable observable, Object data) {
uavobjHandler.post(new Runnable() {
@Override
@ -103,14 +136,35 @@ public abstract class ObjectManagerActivity extends Activity {
});
}
};
private class FragmentUpdatedObserver implements Observer {
UAVObject obj;
ObjectManagerFragment frag;
FragmentUpdatedObserver(UAVObject obj, ObjectManagerFragment frag) {
this.obj = obj;
this.frag = frag;
};
@Override
public void update(Observable observable, Object data) {
uavobjHandler.post(new Runnable() {
@Override
public void run() { frag.objectUpdated(obj); }
});
}
};
/**
* Register an activity to receive updates from this object
*
*
* the objectUpdated() method will be called in the original UI thread
*/
protected void registerObjectUpdates(UAVObject object) {
object.addUpdatedObserver(new UpdatedObserver(object));
object.addUpdatedObserver(new ActivityUpdatedObserver(object));
}
public void registerObjectUpdates(UAVObject object,
ObjectManagerFragment frag) {
object.addUpdatedObserver(new FragmentUpdatedObserver(object, frag));
}
protected void registerObjectUpdates(List<List<UAVObject>> objects) {
ListIterator<List<UAVObject>> li = objects.listIterator();
@ -120,7 +174,7 @@ public abstract class ObjectManagerActivity extends Activity {
registerObjectUpdates(li2.next());
}
}
private void updateStats() {
UAVObject stats = objMngr.getObject("GCSTelemetryStats");
TextView rxRate = (TextView) findViewById(R.id.telemetry_stats_rx_rate);
@ -131,8 +185,9 @@ public abstract class ObjectManagerActivity extends Activity {
txRate.setText(Integer.valueOf((int) stats.getField("TxDataRate").getDouble()).toString());
}
final Observer telemetryObserver = new Observer() {
@Override
public void update(Observable observable, Object data) {
uavobjHandler.post(new Runnable() {
@Override
@ -142,31 +197,34 @@ public abstract class ObjectManagerActivity extends Activity {
});
}
};
/**
* Called when either the telemetry establishes a connection or
* if it already has on creation of this activity
*
*
* This should be called by all inherited classes if they want the telemetry bar etc
*/
void onOPConnected() {
if ( telemetryStatsConnected )
return;
// We are not using the objectUpdated mechanism in place so that all the children
// don't have to sort through the messages.
UAVObject stats = objMngr.getObject("GCSTelemetryStats");
if (stats == null)
return;
stats.addUpdatedObserver(telemetryObserver);
telemetryStatsConnected = true;
updateStats();
if (DEBUG) Log.d(TAG, "Notifying listeners about connection. There are " + connectionListeners.countObservers());
connectionListeners.connected();
}
/**
* Called when telemetry drops the connection
*
*
* This should be called by all inherited classes if they want the telemetry bar etc
*/
void onOPDisconnected() {
@ -175,10 +233,17 @@ public abstract class ObjectManagerActivity extends Activity {
TextView txRate = (TextView) findViewById(R.id.telemetry_stats_tx_rate);
rxRate.setText("");
txRate.setText("");
// Providing a null update triggers a disconnect on fragments
connectionListeners.disconnected();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!mBound || binder == null) {
Log.e(TAG, "Unable to connect to service");
return super.onOptionsItemSelected(item);
}
switch(item.getItemId()) {
case R.id.menu_connect:
binder.openConnection();
@ -206,10 +271,13 @@ public abstract class ObjectManagerActivity extends Activity {
@Override
public void onStart() {
super.onStart();
Intent intent = new Intent(this, OPTelemetryService.class);
Intent intent = new Intent(getApplicationContext(),
org.openpilot.androidgcs.telemetry.OPTelemetryService.class);
if (DEBUG)
Log.d(TAG, "Attempting to bind: " + intent);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
/**
* When stopping disconnect form the service and the broadcast receiver
*/
@ -221,17 +289,63 @@ public abstract class ObjectManagerActivity extends Activity {
}
public void onBind() {
}
/**
* Callbacks so ObjectManagerFragments get the onOPConnected and onOPDisconnected signals
*/
class ConnectionObserver extends Observable {
public void disconnected() {
synchronized(this) {
setChanged();
notifyObservers();
}
}
public void connected() {
synchronized(this) {
setChanged();
notifyObservers(objMngr);
}
}
};
private final ConnectionObserver connectionListeners = new ConnectionObserver();
public class OnConnectionListener implements Observer {
// Local reference of the fragment to notify, store in constructor
ObjectManagerFragment fragment;
OnConnectionListener(ObjectManagerFragment fragment) { this.fragment = fragment; };
// Whenever the observer is updated either conenct or disconnect based on the data
@Override
public void update(Observable observable, Object data) {
Log.d(TAG, "onConnectionListener called");
if (data == null)
fragment.onOPDisconnected();
else
fragment.onOPConnected(objMngr);
}
} ;
public void addOnConnectionListenerFragment(ObjectManagerFragment frag) {
connectionListeners.addObserver(new OnConnectionListener(frag));
if (DEBUG) Log.d(TAG, "Connecting " + frag + " there are now " + connectionListeners.countObservers());
if (mConnected)
frag.onOPConnected(objMngr);
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName arg0, IBinder service) {
// We've bound to LocalService, cast the IBinder and attempt to open a connection
// We've bound to LocalService, cast the IBinder and attempt to open a connection
if (DEBUG) Log.d(TAG,"Service bound");
mBound = true;
binder = (LocalBinder) service;
if(binder.isConnected()) {
TelemTask task;
if((task = binder.getTelemTask(0)) != null) {
@ -239,10 +353,11 @@ public abstract class ObjectManagerActivity extends Activity {
mConnected = true;
onOPConnected();
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
binder = null;

View File

@ -1,56 +0,0 @@
package org.openpilot.androidgcs;
import org.openpilot.uavtalk.UAVObject;
import android.os.Bundle;
public class PFD extends ObjectManagerActivity {
final long MIN_UPDATE_PERIOD = 50;
long lastUpdateMs;
double heading;
double roll;
double pitch;
/**
* Update the UI whenever the attitude is updated
*/
protected void objectUpdated(UAVObject obj) {
// Throttle the UI redraws. Eventually this should maybe come from a periodic task
if ((System.currentTimeMillis() - lastUpdateMs) < MIN_UPDATE_PERIOD)
return;
if (obj.getName().compareTo("AttitudeActual") != 0)
return;
lastUpdateMs = System.currentTimeMillis();
heading = obj.getField("Yaw").getDouble();
pitch = obj.getField("Pitch").getDouble();
roll = obj.getField("Roll").getDouble();
CompassView compass = (CompassView) findViewById(R.id.compass_view);
compass.setBearing((int) heading);
compass.invalidate();
AttitudeView attitude = (AttitudeView) findViewById(R.id.attitude_view);
attitude.setRoll(roll / 180 * Math.PI);
attitude.setPitch(pitch / 180 * Math.PI);
attitude.invalidate();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pfd);
}
@Override
void onOPConnected() {
super.onOPConnected();
// Connect the update method to AttitudeActual
UAVObject obj = objMngr.getObject("AttitudeActual");
if (obj != null)
registerObjectUpdates(obj);
}
}

View File

@ -0,0 +1,58 @@
/**
******************************************************************************
* @file PfdActivity.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Shows the PFD activity.
* @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;
import org.openpilot.androidgcs.fragments.PFD;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.widget.AbsListView;
import android.widget.LinearLayout;
public class PfdActivity extends ObjectManagerActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(createUI());
}
private View createUI() {
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.HORIZONTAL);
layout.setLayoutParams(new LinearLayout.LayoutParams(
AbsListView.LayoutParams.MATCH_PARENT,
AbsListView.LayoutParams.MATCH_PARENT));
layout.setId(0x101);
{
FragmentTransaction fragmentTransaction = getFragmentManager()
.beginTransaction();
fragmentTransaction.add(0x101, new PFD());
fragmentTransaction.commit();
}
return layout;
}
}

View File

@ -1,3 +1,27 @@
/**
******************************************************************************
* @file Preferences.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Displays the preferences dialog.
* @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;
import android.os.Bundle;

View File

@ -1,51 +1,37 @@
/**
******************************************************************************
* @file SystemAlarmActivity.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief An activity that displays the SystemAlarmsFragment.
* @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;
import java.util.List;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectField;
import android.os.Bundle;
import android.widget.TextView;
/**
* All the work for this activity is performed by it's fragment
*/
public class SystemAlarmActivity extends ObjectManagerActivity {
/**
* Update the UI whenever the attitude is updated
*/
protected void objectUpdated(UAVObject obj) {
if (obj.getName().compareTo("SystemAlarms") != 0)
return;
TextView alarms = (TextView) findViewById(R.id.system_alarms_status);
UAVObjectField a = obj.getField("Alarm");
List<String> names = a.getElementNames();
String contents = new String();
List <String> options = a.getOptions();
// Rank the alarms by order of severity, skip uninitialized
for (int j = options.size() - 1; j > 0; j--) {
for (int i = 0; i < names.size(); i++) {
if(a.getDouble(i) == j)
contents += names.get(i) + " : " + a.getValue(i).toString() + "\n";
}
}
alarms.setText(contents);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.system_alarms);
}
@Override
void onOPConnected() {
super.onOPConnected();
// Connect the update method to AttitudeActual
UAVObject obj = objMngr.getObject("SystemAlarms");
if (obj != null)
registerObjectUpdates(obj);
objectUpdated(obj);
}
}
}

View File

@ -1,5 +1,29 @@
/**
******************************************************************************
* @file TelemetryWidget.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief A widget that shows the status of telemetry.
* @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;
import org.openpilot.androidgcs.telemetry.OPTelemetryService;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
@ -8,7 +32,7 @@ import android.content.Intent;
import android.widget.RemoteViews;
public class TelemetryWidget extends AppWidgetProvider {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(OPTelemetryService.INTENT_ACTION_CONNECTED)) {
@ -16,11 +40,11 @@ public class TelemetryWidget extends AppWidgetProvider {
}
if(intent.getAction().equals(OPTelemetryService.INTENT_ACTION_DISCONNECTED)) {
changeStatus(context, false);
}
}
super.onReceive(context, intent);
}
public void changeStatus(Context context, boolean status) {
RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.telemetry_widget);
updateViews.setTextViewText(R.id.telemetryWidgetStatus, "Connection status: " + status);
@ -30,6 +54,7 @@ public class TelemetryWidget extends AppWidgetProvider {
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
@ -44,6 +69,6 @@ public class TelemetryWidget extends AppWidgetProvider {
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}

View File

@ -1,23 +1,39 @@
/**
******************************************************************************
* @file UAVLocation.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Display the UAV location on google maps
* @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;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import org.openpilot.androidgcs.OPTelemetryService.LocalBinder;
import org.openpilot.androidgcs.OPTelemetryService.TelemTask;
import org.openpilot.androidgcs.telemetry.OPTelemetryService;
import org.openpilot.androidgcs.telemetry.OPTelemetryService.LocalBinder;
import org.openpilot.androidgcs.telemetry.OPTelemetryService.TelemTask;
import org.openpilot.uavtalk.UAVDataObject;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectManager;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
import com.google.android.maps.MyLocationOverlay;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@ -36,47 +52,55 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
public class UAVLocation extends MapActivity
{
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
public class UAVLocation extends MapActivity
{
private final String TAG = "UAVLocation";
private static int LOGLEVEL = 0;
// private static boolean WARN = LOGLEVEL > 1;
private static boolean DEBUG = LOGLEVEL > 0;
private MapView mapView;
private MapView mapView;
private MapController mapController;
UAVObjectManager objMngr;
boolean mBound = false;
boolean mConnected = false;
LocalBinder binder;
org.openpilot.androidgcs.telemetry.OPTelemetryService.LocalBinder binder;
GeoPoint homeLocation;
GeoPoint uavLocation;
@Override public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.map_layout);
super.onCreate(icicle);
setContentView(R.layout.map_layout);
mapView = (MapView)findViewById(R.id.map_view);
mapController = mapView.getController();
mapView.displayZoomControls(true);
Double lat = 37.422006*1E6;
Double lng = -122.084095*1E6;
Double lat = 37.422006*1E6;
Double lng = -122.084095*1E6;
homeLocation = new GeoPoint(lat.intValue(), lng.intValue());
uavLocation = homeLocation;
mapController.setCenter(homeLocation);
mapController.setCenter(homeLocation);
mapController.setZoom(18);
List<Overlay> overlays = mapView.getOverlays();
UAVOverlay myOverlay = new UAVOverlay();
overlays.add(myOverlay);
UAVOverlay myOverlay = new UAVOverlay();
overlays.add(myOverlay);
MyLocationOverlay myLocationOverlay = new MyLocationOverlay(this, mapView);
myLocationOverlay.enableMyLocation();
myLocationOverlay.enableCompass();
overlays.add(myLocationOverlay);
mapView.postInvalidate();
// ObjectManager related stuff (can't inherit standard class)
@ -86,7 +110,7 @@ public class UAVLocation extends MapActivity
Log.d(TAG, "Received intent");
TelemTask task;
if(intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_CONNECTED) == 0) {
if(binder == null)
return;
if((task = binder.getTelemTask(0)) == null)
@ -101,9 +125,9 @@ public class UAVLocation extends MapActivity
onOPDisconnected();
Log.d(TAG, "Disonnected()");
}
}
}
};
IntentFilter filter = new IntentFilter();
filter.addCategory(OPTelemetryService.INTENT_CATEGORY_GCS);
filter.addAction(OPTelemetryService.INTENT_ACTION_CONNECTED);
@ -111,103 +135,108 @@ public class UAVLocation extends MapActivity
registerReceiver(connectedReceiver, filter);
}
//@Override
//@Override
@Override
protected boolean isRouteDisplayed() {
// IMPORTANT: This method must return true if your Activity // is displaying driving directions. Otherwise return false.
// IMPORTANT: This method must return true if your Activity // is displaying driving directions. Otherwise return false.
return false;
}
public class UAVOverlay extends Overlay {
Bitmap homeSymbol = BitmapFactory.decodeResource(getResources(), R.drawable.ic_home);
Bitmap uavSymbol = BitmapFactory.decodeResource(getResources(), R.drawable.ic_uav);
@Override
@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Projection projection = mapView.getProjection();
if (shadow == false) {
Point myPoint = new Point();
Point myPoint = new Point();
projection.toPixels(uavLocation, myPoint);
//// Draw UAV
// Create and setup your paint brush
Paint paint = new Paint();
paint.setARGB(250, 255, 0, 0);
paint.setAntiAlias(true);
// Create and setup your paint brush
Paint paint = new Paint();
paint.setARGB(250, 255, 0, 0);
paint.setAntiAlias(true);
paint.setFakeBoldText(true);
// Draw on the canvas
canvas.drawBitmap(uavSymbol, myPoint.x - uavSymbol.getWidth() / 2,
// Draw on the canvas
canvas.drawBitmap(uavSymbol, myPoint.x - uavSymbol.getWidth() / 2,
myPoint.y - uavSymbol.getHeight() / 2, paint);
canvas.drawText("UAV", myPoint.x+uavSymbol.getWidth() / 2, myPoint.y, paint);
canvas.drawText("UAV", myPoint.x+uavSymbol.getWidth() / 2, myPoint.y, paint);
//// Draw Home
myPoint = new Point();
projection.toPixels(homeLocation, myPoint);
// Create and setup your paint brush
paint.setARGB(250, 0, 0, 0);
paint.setAntiAlias(true);
// Create and setup your paint brush
paint.setARGB(250, 0, 0, 0);
paint.setAntiAlias(true);
paint.setFakeBoldText(true);
canvas.drawBitmap(homeSymbol, myPoint.x - homeSymbol.getWidth() / 2,
myPoint.y - homeSymbol.getHeight() / 2, paint);
canvas.drawText("Home", myPoint.x+homeSymbol.getWidth(), myPoint.y, paint);
}
canvas.drawBitmap(homeSymbol, myPoint.x - homeSymbol.getWidth() / 2,
myPoint.y - homeSymbol.getHeight() / 2, paint);
canvas.drawText("Home", myPoint.x+homeSymbol.getWidth(), myPoint.y, paint);
}
}
@Override
public boolean onTap(GeoPoint point, MapView mapView1) {
// Return true if screen tap is handled by this overlay
return false;
return false;
}
}
void onOPConnected() {
UAVObject obj = objMngr.getObject("HomeLocation");
if(obj != null)
obj.addUpdatedObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
UAVDataObject obj = (UAVDataObject) data;
Double lat = obj.getField("Latitude").getDouble() / 10;
Double lon = obj.getField("Longitude").getDouble() / 10;
homeLocation = new GeoPoint(lat.intValue(), lon.intValue());
runOnUiThread(new Runnable() {
@Override
public void run() {
mapController.setCenter(homeLocation);
}
mapController.setCenter(homeLocation);
}
});
System.out.println("HomeLocation: " + homeLocation.toString());
}
}
});
obj.updateRequested();
obj = objMngr.getObject("PositionActual");
if(obj != null)
obj.addUpdatedObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
uavLocation = getUavLocation();
runOnUiThread(new Runnable() {
@Override
public void run() {
mapView.invalidate();
}
});
}
}
});
}
private GeoPoint getUavLocation() {
UAVObject pos = (UAVObject) objMngr.getObject("PositionActual");
UAVObject pos = objMngr.getObject("PositionActual");
if (pos == null)
return new GeoPoint(0,0);
UAVObject home = (UAVObject) objMngr.getObject("HomeLocation");
if (home == null)
UAVObject home = objMngr.getObject("HomeLocation");
if (home == null)
return new GeoPoint(0,0);
double lat, lon, alt;
lat = home.getField("Latitude").getDouble() / 10.0e6;
lon = home.getField("Longitude").getDouble() / 10.0e6;
@ -217,23 +246,23 @@ public class UAVLocation extends MapActivity
double T0, T1;
T0 = alt+6.378137E6;
T1 = Math.cos(lat * Math.PI / 180.0)*(alt+6.378137E6);
// Get the NED coordinates
double NED0, NED1;
NED0 = pos.getField("North").getDouble();
NED1 = pos.getField("East").getDouble();
// Compute the LLA coordinates
lat = lat + (NED0 / T0) * 180.0 / Math.PI;
lon = lon + (NED1 / T1) * 180.0 / Math.PI;
return new GeoPoint((int) (lat * 1e6), (int) (lon * 1e6));
}
void onOPDisconnected() {
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
@ -265,15 +294,16 @@ public class UAVLocation extends MapActivity
Intent intent = new Intent(this, OPTelemetryService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
public void onBind() {
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName arg0, IBinder service) {
// We've bound to LocalService, cast the IBinder and attempt to open a connection
// We've bound to LocalService, cast the IBinder and attempt to open a connection
if (DEBUG) Log.d(TAG,"Service bound");
mBound = true;
binder = (LocalBinder) service;
@ -285,10 +315,11 @@ public class UAVLocation extends MapActivity
mConnected = true;
onOPConnected();
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
binder = null;

View File

@ -0,0 +1,104 @@
/**
******************************************************************************
* @file ObjectManagerFragment.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Base class for all fragments that use the UAVObjectManager. This
* supports all the extensions the ObjectManagerActivity does, namely
* access to the UAVObjectManager and callbacks in the UI thread for
* object updates.
* @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.fragments;
import org.openpilot.androidgcs.ObjectManagerActivity;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectManager;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
public class ObjectManagerFragment extends Fragment {
private static final String TAG = ObjectManagerFragment.class.getSimpleName();
private static final int LOGLEVEL = 0;
// private static boolean WARN = LOGLEVEL > 1;
private static final boolean DEBUG = LOGLEVEL > 0;
UAVObjectManager objMngr;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (DEBUG) Log.d(TAG, "Created an ObjectManagerFragment");
// For an activity this registers against the telemetry service intents. Fragments must be notified by their
// parent activity
}
/**
* Attach to the parent activity so it can notify us when the connection
* changed
*/
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (DEBUG) Log.d(TAG,"onAttach");
ObjectManagerActivity castActivity = null;
try {
castActivity = (ObjectManagerActivity)activity;
} catch (ClassCastException e) {
throw new android.app.Fragment.InstantiationException(
"Attaching a ObjectManagerFragment to an activity failed because the parent activity is not a ObjectManagerActivity",
e);
}
castActivity.addOnConnectionListenerFragment(this);
}
// The below methods should all be called by the parent activity at the appropriate times
public void onOPConnected(UAVObjectManager objMngr) {
this.objMngr = objMngr;
if (DEBUG) Log.d(TAG,"onOPConnected");
}
public void onOPDisconnected() {
objMngr = null;
if (DEBUG) Log.d(TAG,"onOPDisconnected");
}
/**
* Called whenever any objects subscribed to via registerObjects
*/
public void objectUpdated(UAVObject obj) {
}
/**
* Register on the activities object monitor handler so that updates
* occur within that UI thread. No need to maintain a handler for
* each fragment.
*/
protected void registerObjectUpdates(UAVObject object) {
((ObjectManagerActivity) getActivity()).registerObjectUpdates(object, this);
}
}

View File

@ -0,0 +1,93 @@
/**
******************************************************************************
* @file PFD.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief The PFD display fragment
* @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.fragments;
import org.openpilot.androidgcs.AttitudeView;
import org.openpilot.androidgcs.R;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectManager;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class PFD extends ObjectManagerFragment {
private static final String TAG = ObjectManagerFragment.class
.getSimpleName();
private static final int LOGLEVEL = 0;
// private static boolean WARN = LOGLEVEL > 1;
private static final boolean DEBUG = LOGLEVEL > 0;
// @Override
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.pfd, container, false);
}
@Override
public void onOPConnected(UAVObjectManager objMngr) {
super.onOPConnected(objMngr);
if (DEBUG)
Log.d(TAG, "On connected");
UAVObject obj = objMngr.getObject("AttitudeActual");
if (obj != null)
registerObjectUpdates(obj);
objectUpdated(obj);
}
/**
* Called whenever any objects subscribed to via registerObjects
*/
@Override
public void objectUpdated(UAVObject obj) {
if (DEBUG)
Log.d(TAG, "Updated");
double pitch = obj.getField("Pitch").getDouble();
double roll = obj.getField("Roll").getDouble();
// TODO: These checks, while sensible, are necessary because the
// callbacks aren't
// removed when we switch to different activities sharing this fragment
Activity parent = getActivity();
AttitudeView attitude = null;
if (parent != null)
attitude = (AttitudeView) parent.findViewById(R.id.attitude_view);
if (attitude != null) {
attitude.setRoll(roll);
attitude.setPitch(pitch);
attitude.invalidate();
}
}
}

View File

@ -0,0 +1,93 @@
/**
******************************************************************************
* @file SystemAlarmsFragment.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief A fragment that will connect to the SystemAlarms and visualize them.
* @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.fragments;
import java.util.List;
import org.openpilot.androidgcs.R;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectField;
import org.openpilot.uavtalk.UAVObjectManager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class SystemAlarmsFragment extends ObjectManagerFragment {
private static final String TAG = SystemAlarmsFragment.class.getSimpleName();
private static final int LOGLEVEL = 0;
// private static boolean WARN = LOGLEVEL > 1;
private static final boolean DEBUG = LOGLEVEL > 0;
//@Override
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.system_alarms_fragment, container, false);
}
@Override
public void onOPConnected(UAVObjectManager objMngr) {
super.onOPConnected(objMngr);
if (DEBUG)
Log.d(TAG, "On connected");
UAVObject obj = objMngr.getObject("SystemAlarms");
if (obj != null)
registerObjectUpdates(obj);
objectUpdated(obj);
}
/**
* Called whenever any objects subscribed to via registerObjects
*/
@Override
public void objectUpdated(UAVObject obj) {
if (DEBUG)
Log.d(TAG, "Updated");
if (obj.getName().compareTo("SystemAlarms") == 0) {
TextView alarms = (TextView) getActivity().findViewById(R.id.system_alarms_fragment_field);
UAVObjectField a = obj.getField("Alarm");
List<String> names = a.getElementNames();
String contents = new String();
List <String> options = a.getOptions();
// Rank the alarms by order of severity, skip uninitialized
for (int j = options.size() - 1; j > 0; j--) {
for (int i = 0; i < names.size(); i++) {
if(a.getDouble(i) == j)
contents += names.get(i) + " : " + a.getValue(i).toString() + "\n";
}
}
alarms.setText(contents);
}
}
}

View File

@ -0,0 +1,178 @@
/**
******************************************************************************
* @file BluetoothUAVTalk.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Telemetry over bluetooth.
* @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.telemetry;
import java.io.IOException;
import java.util.Set;
import java.util.UUID;
import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVTalk;
import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
@TargetApi(10) public class BluetoothUAVTalk {
private final String TAG = "BluetoothUAVTalk";
public static int LOGLEVEL = 2;
public static boolean WARN = LOGLEVEL > 1;
public static boolean DEBUG = LOGLEVEL > 0;
// Temporarily define fixed device name
private String device_name = "RN42-222D";
private final static UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private BluetoothAdapter mBluetoothAdapter;
private BluetoothSocket socket;
private BluetoothDevice device;
private UAVTalk uavTalk;
private boolean connected;
public BluetoothUAVTalk(Context caller) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(caller);
device_name = prefs.getString("bluetooth_mac","");
if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + device_name);
connected = false;
device = null;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
Log.e(TAG, "Device does not support Bluetooth");
return;
}
if (!mBluetoothAdapter.isEnabled()) {
// Enable bluetooth if it isn't already
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
caller.sendOrderedBroadcast(enableBtIntent, "android.permission.BLUETOOTH_ADMIN", new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG,"Received " + context + intent);
//TODO: some logic here to see if it worked
queryDevices();
}
}, null, Activity.RESULT_OK, null, null);
} else {
queryDevices();
}
}
public boolean connect(UAVObjectManager objMngr) {
if( getConnected() )
return true;
if( !getFoundDevice() )
return false;
if( !openTelemetryBluetooth(objMngr) )
return false;
return true;
}
public boolean getConnected() {
return connected;
}
public boolean getFoundDevice() {
return (device != null);
}
public UAVTalk getUavtalk() {
return uavTalk;
}
private void queryDevices() {
Log.d(TAG, "Searching for devices");
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
//mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
Log.d(TAG, "Paired device: " + device.getAddress() + " compared to " + device_name);
if(device.getAddress().compareTo(device_name) == 0) {
Log.d(TAG, "Found device: " + device.getName());
this.device = device;
return;
}
}
}
}
private boolean openTelemetryBluetooth(UAVObjectManager objMngr) {
Log.d(TAG, "Opening connection to " + device.getName());
socket = null;
connected = false;
try {
socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.e(TAG,"Unable to create Rfcomm socket");
return false;
//e.printStackTrace();
}
mBluetoothAdapter.cancelDiscovery();
try {
socket.connect();
}
catch (IOException e) {
Log.e(TAG,"Unable to connect to requested device", e);
try {
socket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() socket during connection failure", e2);
}
return false;
}
connected = true;
try {
uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr);
} catch (IOException e) {
Log.e(TAG,"Error starting UAVTalk");
// TODO Auto-generated catch block
//e.printStackTrace();
return false;
}
return true;
}
}

View File

@ -0,0 +1,479 @@
/**
******************************************************************************
* @file OPTelemetryService.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Provides UAVTalk telemetry over multiple physical links. The
* details of each of these are in their respective connection
* classes. This mostly creates those threads based on the selected
* preferences.
* @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.telemetry;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;
import org.openpilot.uavtalk.Telemetry;
import org.openpilot.uavtalk.TelemetryMonitor;
import org.openpilot.uavtalk.UAVDataObject;
import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVTalk;
import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
public class OPTelemetryService extends Service {
// Logging settings
private final String TAG = OPTelemetryService.class.getSimpleName();
public static int LOGLEVEL = 0;
public static boolean WARN = LOGLEVEL > 1;
public static boolean DEBUG = LOGLEVEL > 0;
// Intent category
public final static String INTENT_CATEGORY_GCS = "org.openpilot.intent.category.GCS";
// Intent actions
public final static String INTENT_ACTION_CONNECTED = "org.openpilot.intent.action.CONNECTED";
public final static String INTENT_ACTION_DISCONNECTED = "org.openpilot.intent.action.DISCONNECTED";
// Variables for local message handler thread
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
private static HandlerThread thread;
// Message ids
static final int MSG_START = 0;
static final int MSG_CONNECT = 1;
static final int MSG_DISCONNECT = 3;
static final int MSG_TOAST = 100;
private boolean terminate = false;
private Thread activeTelem;
private final IBinder mBinder = new LocalBinder();
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
if (DEBUG)
Log.d(TAG, "handleMessage: " + msg);
switch(msg.arg1) {
case MSG_START:
stopSelf(msg.arg2);
break;
case MSG_CONNECT:
terminate = false;
int connection_type;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this);
try {
connection_type = Integer.decode(prefs.getString("connection_type", ""));
} catch (NumberFormatException e) {
connection_type = 0;
}
switch(connection_type) {
case 0: // No connection
return;
case 1:
Toast.makeText(getApplicationContext(), "Attempting fake connection", Toast.LENGTH_SHORT).show();
activeTelem = new FakeTelemetryThread();
break;
case 2:
Toast.makeText(getApplicationContext(), "Attempting BT connection", Toast.LENGTH_SHORT).show();
activeTelem = new BTTelemetryThread();
break;
case 3:
Toast.makeText(getApplicationContext(), "Attempting TCP connection", Toast.LENGTH_SHORT).show();
activeTelem = new TcpTelemetryThread();
break;
default:
throw new Error("Unsupported");
}
activeTelem.start();
break;
case MSG_DISCONNECT:
Toast.makeText(getApplicationContext(), "Disconnect requested", Toast.LENGTH_SHORT).show();
terminate = true;
activeTelem.interrupt();
try {
activeTelem.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
activeTelem = null;
Intent intent = new Intent();
intent.setAction(INTENT_ACTION_DISCONNECTED);
sendBroadcast(intent,null);
stopSelf();
break;
case MSG_TOAST:
Toast.makeText(OPTelemetryService.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
break;
default:
System.out.println(msg.toString());
throw new Error("Invalid message");
}
}
};
/**
* Called when the service starts. It creates a thread to handle messages (e.g. connect and disconnect)
* and based on the stored preference will send itself a connect signal if needed.
*/
public void startup() {
Toast.makeText(getApplicationContext(), "Telemetry service starting", Toast.LENGTH_SHORT).show();
if (DEBUG)
Log.d(TAG, "startup()");
thread = new HandlerThread("TelemetryServiceHandler", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this);
if(prefs.getBoolean("autoconnect", false)) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = MSG_CONNECT;
msg.arg2 = 0;
mServiceHandler.sendMessage(msg);
}
}
@Override
public void onCreate() {
if (DEBUG)
Log.d(TAG, "Telemetry service created");
startup();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Currently only using as bound service
if (DEBUG)
Log.d(TAG, "onStartCommand()");
// If we get killed, after returning from here, restart
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
if (DEBUG)
Log.d(TAG, "onBind()");
return mBinder;
}
@Override
public void onDestroy() {
Toast.makeText(this, "Telemetry service done", Toast.LENGTH_SHORT).show();
}
public class LocalBinder extends Binder {
public TelemTask getTelemTask(int id) {
return (TelemTask) activeTelem;
}
public void openConnection() {
Toast.makeText(getApplicationContext(), "Requested open connection", Toast.LENGTH_SHORT).show();
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = MSG_CONNECT;
mServiceHandler.sendMessage(msg);
}
public void stopConnection() {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = MSG_DISCONNECT;
mServiceHandler.sendMessage(msg);
}
public boolean isConnected() {
return activeTelem != null;
}
};
public void toastMessage(String msgText) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = MSG_TOAST;
msg.obj = msgText;
mServiceHandler.sendMessage(msg);
}
/**
* This is used by other processes to get a handle to the object manager
*/
public interface TelemTask {
public UAVObjectManager getObjectManager();
};
// Fake class for testing, simply emits periodic updates on
private class FakeTelemetryThread extends Thread implements TelemTask {
private final UAVObjectManager objMngr;
@Override
public UAVObjectManager getObjectManager() { return objMngr; };
FakeTelemetryThread() {
objMngr = new UAVObjectManager();
UAVObjectsInitialize.register(objMngr);
}
@Override
public void run() {
System.out.println("Running fake thread");
Intent intent = new Intent();
intent.setAction(INTENT_ACTION_CONNECTED);
sendBroadcast(intent,null);
//toastMessage("Started fake telemetry thread");
UAVDataObject systemStats = (UAVDataObject) objMngr.getObject("SystemStats");
UAVDataObject attitudeActual = (UAVDataObject) objMngr.getObject("AttitudeActual");
UAVDataObject homeLocation = (UAVDataObject) objMngr.getObject("HomeLocation");
UAVDataObject positionActual = (UAVDataObject) objMngr.getObject("PositionActual");
UAVDataObject systemAlarms = (UAVDataObject) objMngr.getObject("SystemAlarms");
systemAlarms.getField("Alarm").setValue("Warning",0);
systemAlarms.getField("Alarm").setValue("OK",1);
systemAlarms.getField("Alarm").setValue("Critical",2);
systemAlarms.getField("Alarm").setValue("Error",3);
systemAlarms.updated();
homeLocation.getField("Latitude").setDouble(379420315);
homeLocation.getField("Longitude").setDouble(-88330078);
homeLocation.getField("Be").setDouble(26702.78710938,0);
homeLocation.getField("Be").setDouble(-1468.33605957,1);
homeLocation.getField("Be").setDouble(34181.78515625,2);
double roll = 0;
double pitch = 0;
double yaw = 0;
double north = 0;
double east = 0;
while( !terminate ) {
attitudeActual.getField("Roll").setDouble(roll);
attitudeActual.getField("Pitch").setDouble(pitch);
attitudeActual.getField("Yaw").setDouble(yaw);
positionActual.getField("North").setDouble(north += 100);
positionActual.getField("East").setDouble(east += 100);
roll = (roll + 10) % 180;
pitch = (pitch + 10) % 180;
yaw = (yaw + 10) % 360;
systemStats.updated();
attitudeActual.updated();
positionActual.updated();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
}
}
private class BTTelemetryThread extends Thread implements TelemTask {
private final UAVObjectManager objMngr;
private UAVTalk uavTalk;
private Telemetry tel;
private TelemetryMonitor mon;
@Override
public UAVObjectManager getObjectManager() { return objMngr; };
BTTelemetryThread() {
objMngr = new UAVObjectManager();
UAVObjectsInitialize.register(objMngr);
}
@Override
public void run() {
if (DEBUG) Log.d(TAG, "Telemetry Thread started");
Looper.prepare();
BluetoothUAVTalk bt = new BluetoothUAVTalk(OPTelemetryService.this);
for( int i = 0; i < 10; i++ ) {
if (DEBUG) Log.d(TAG, "Attempting Bluetooth Connection");
bt.connect(objMngr);
if (DEBUG) Log.d(TAG, "Done attempting connection");
if( bt.getConnected() )
break;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, "Thread interrupted while trying to connect");
e.printStackTrace();
return;
}
}
if( ! bt.getConnected() ) {
toastMessage("BT connection failed");
return;
}
toastMessage("BT Connected");
if (DEBUG) Log.d(TAG, "Connected via bluetooth");
uavTalk = bt.getUavtalk();
tel = new Telemetry(uavTalk, objMngr);
mon = new TelemetryMonitor(objMngr,tel);
mon.addObserver(new Observer() {
@Override
public void update(Observable arg0, Object arg1) {
System.out.println("Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated());
if(mon.getConnected() /*&& mon.getObjectsUpdated()*/) {
Intent intent = new Intent();
intent.setAction(INTENT_ACTION_CONNECTED);
sendBroadcast(intent,null);
}
}
});
if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop");
while( !terminate ) {
try {
if( !uavTalk.processInputStream() )
break;
} catch (IOException e) {
// This occurs when they communication stream fails
toastMessage("Connection dropped");
break;
}
}
if (DEBUG) Log.d(TAG, "UAVTalk stream disconnected");
}
};
private class TcpTelemetryThread extends Thread implements TelemTask {
private final UAVObjectManager objMngr;
private UAVTalk uavTalk;
private Telemetry tel;
private TelemetryMonitor mon;
@Override
public UAVObjectManager getObjectManager() { return objMngr; };
TcpTelemetryThread() {
objMngr = new UAVObjectManager();
UAVObjectsInitialize.register(objMngr);
}
@Override
public void run() {
if (DEBUG) Log.d(TAG, "Telemetry Thread started");
Looper.prepare();
TcpUAVTalk tcp = new TcpUAVTalk(OPTelemetryService.this);
for( int i = 0; i < 10; i++ ) {
if (DEBUG) Log.d(TAG, "Attempting network Connection");
tcp.connect(objMngr);
if( tcp.getConnected() )
break;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, "Thread interrupted while trying to connect");
e.printStackTrace();
return;
}
}
if( ! tcp.getConnected() || terminate ) {
toastMessage("TCP connection failed");
return;
}
toastMessage("TCP Connected");
if (DEBUG) Log.d(TAG, "Connected via network");
uavTalk = tcp.getUavtalk();
tel = new Telemetry(uavTalk, objMngr);
mon = new TelemetryMonitor(objMngr,tel);
mon.addObserver(new Observer() {
@Override
public void update(Observable arg0, Object arg1) {
System.out.println("Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated());
if(mon.getConnected() /*&& mon.getObjectsUpdated()*/) {
Intent intent = new Intent();
intent.setAction(INTENT_ACTION_CONNECTED);
sendBroadcast(intent,null);
}
}
});
if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop");
while( !terminate ) {
try {
if( !uavTalk.processInputStream() )
break;
} catch (IOException e) {
e.printStackTrace();
toastMessage("TCP Stream interrupted");
break;
}
}
Looper.myLooper().quit();
// Shut down all the attached
mon.stopMonitor();
mon = null;
tel.stopTelemetry();
tel = null;
// Finally close the stream if it is still open
tcp.disconnect();
if (DEBUG) Log.d(TAG, "UAVTalk stream disconnected");
toastMessage("TCP Thread finished");
}
};
}

View File

@ -0,0 +1,138 @@
/**
******************************************************************************
* @file TcpUAVTalk.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief UAVTalk over TCP.
* @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.telemetry;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVTalk;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
public class TcpUAVTalk {
private final String TAG = "TcpUAVTalk";
public static int LOGLEVEL = 2;
public static boolean WARN = LOGLEVEL > 1;
public static boolean DEBUG = LOGLEVEL > 0;
// Temporarily define fixed device name
private String ip_address = "1";
private int port = 9001;
private UAVTalk uavTalk;
private boolean connected;
private Socket socket;
/**
* Construct a TcpUAVTalk object attached to the OPTelemetryService. Gets the
* connection settings from the preferences.
*/
public TcpUAVTalk(Context caller) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(caller);
ip_address = prefs.getString("ip_address","127.0.0.1");
try {
port = Integer.decode(prefs.getString("port", ""));
} catch (NumberFormatException e) {
//TODO: Handle this exception
}
if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + ip_address);
connected = false;
}
/**
* Connect a TCP object to an object manager. Returns true if already
* connected, otherwise returns true if managed a successful socket.
*/
public boolean connect(UAVObjectManager objMngr) {
if( getConnected() )
return true;
if( !openTelemetryTcp(objMngr) )
return false;
return true;
}
public void disconnect() {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket = null;
}
public boolean getConnected() {
return connected;
}
public UAVTalk getUavtalk() {
return uavTalk;
}
/**
* Opens a TCP socket to the address determined on construction. If successful
* creates a UAVTalk stream connection this socket to the passed in object manager
*/
private boolean openTelemetryTcp(UAVObjectManager objMngr) {
Log.d(TAG, "Opening connection to " + ip_address + " at address " + port);
InetAddress serverAddr = null;
try {
serverAddr = InetAddress.getByName(ip_address);
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return false;
}
socket = null;
try {
socket = new Socket(serverAddr,port);
} catch (IOException e1) {
return false;
}
connected = true;
try {
uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr);
} catch (IOException e) {
Log.e(TAG,"Error starting UAVTalk");
// TODO Auto-generated catch block
//e.printStackTrace();
return false;
}
return true;
}
}

View File

@ -1,3 +1,27 @@
/**
******************************************************************************
* @file Telemetry.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Port of Telemetry.cpp from the GCS. Handles transactions on the
* UAVTalk channel.
* @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.uavtalk;
import java.io.IOException;
@ -14,7 +38,7 @@ import java.util.TimerTask;
import android.util.Log;
public class Telemetry {
private final String TAG = "Telemetry";
public static int LOGLEVEL = 0;
public static boolean WARN = LOGLEVEL > 2;
@ -31,7 +55,7 @@ public class Telemetry {
public int rxErrors;
public int txRetries;
} ;
class ObjectTimeInfo {
UAVObject obj;
int updatePeriodMs; /** Update period in ms or 0 if no periodic updates are needed */
@ -51,7 +75,7 @@ public class Telemetry {
int retriesRemaining;
boolean acked;
} ;
/**
* Events generated by objects. Not enum because used in mask.
*/
@ -59,7 +83,7 @@ public class Telemetry {
private static final int EV_UPDATED = 0x02; /** Object data updated by changing the data structure */
private static final int EV_UPDATED_MANUAL = 0x04; /** Object update event manually generated */
private static final int EV_UPDATE_REQ = 0x08; /** Request to update object data */
/**
* Constructor
*/
@ -71,33 +95,36 @@ public class Telemetry {
// Process all objects in the list
List< List<UAVObject> > objs = objMngr.getObjects();
ListIterator<List<UAVObject>> li = objs.listIterator();
while(li.hasNext())
while(li.hasNext())
registerObject(li.next().get(0)); // we only need to register one instance per object type
// Listen to new object creations
objMngr.addNewInstanceObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
newInstance((UAVObject) data);
newInstance((UAVObject) data);
}
});
objMngr.addNewObjectObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
newObject((UAVObject) data);
}
newObject((UAVObject) data);
}
});
// Listen to transaction completions
utalk.addObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
try {
transactionCompleted((UAVObject) data);
} catch (IOException e) {
// Disconnect when stream fails
observable.deleteObserver(this);
}
}
}
}
});
// Get GCS stats object
gcsStatsObj = objMngr.getObject("GCSTelemetryStats");
@ -110,16 +137,16 @@ public class Telemetry {
txErrors = 0;
txRetries = 0;
}
synchronized void transTimerSetPeriod(int periodMs) {
if(transTimerTask != null)
transTimerTask.cancel();
if(transTimer != null)
if(transTimer != null)
transTimer.purge();
transTimer = new Timer();
transTimerTask = new TimerTask() {
@Override
public void run() {
@ -128,11 +155,11 @@ public class Telemetry {
} catch (IOException e) {
cancel();
}
}
}
};
transTimer.schedule(transTimerTask, periodMs, periodMs);
}
synchronized void updateTimerSetPeriod(int periodMs) {
if (updateTimer != null) {
updateTimer.cancel();
@ -152,7 +179,7 @@ public class Telemetry {
updateTimerTask.cancel();
updateTimer.cancel();
}
}
}
};
updateTimer.schedule(updateTimerTask, periodMs, periodMs);
@ -223,11 +250,12 @@ public class Telemetry {
obj = li.next();
//TODO: Disconnect all
// obj.disconnect(this);
// Connect only the selected events
if ( (eventMask&EV_UNPACKED) != 0)
{
obj.addUnpackedObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
try {
objectUnpacked( (UAVObject) data);
@ -235,12 +263,13 @@ public class Telemetry {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
if ( (eventMask&EV_UPDATED) != 0)
{
obj.addUpdatedAutoObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
try {
objectUpdatedAuto( (UAVObject) data);
@ -248,12 +277,13 @@ public class Telemetry {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
if ( (eventMask&EV_UPDATED_MANUAL) != 0)
{
obj.addUpdatedManualObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
try {
objectUpdatedManual( (UAVObject) data);
@ -261,12 +291,13 @@ public class Telemetry {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
if ( (eventMask&EV_UPDATE_REQ) != 0)
{
obj.addUpdateRequestedObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
try {
updateRequested( (UAVObject) data);
@ -274,7 +305,7 @@ public class Telemetry {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
}
@ -331,7 +362,7 @@ public class Telemetry {
/**
* Called when a transaction is successfully completed (uavtalk event)
* @throws IOException
* @throws IOException
*/
private synchronized void transactionCompleted(UAVObject obj) throws IOException
{
@ -355,7 +386,7 @@ public class Telemetry {
/**
* Called when a transaction is not completed within the timeout period (timer event)
* @throws IOException
* @throws IOException
*/
private synchronized void transactionTimeout() throws IOException
{
@ -387,7 +418,7 @@ public class Telemetry {
/**
* Start an object transaction with UAVTalk, all information is stored in transInfo
* @throws IOException
* @throws IOException
*/
private synchronized void processObjectTransaction() throws IOException
{
@ -421,7 +452,7 @@ public class Telemetry {
/**
* Process the event received from an object
* @throws IOException
* @throws IOException
*/
private synchronized void processObjectUpdates(UAVObject obj, int event, boolean allInstances, boolean priority) throws IOException
{
@ -450,7 +481,7 @@ public class Telemetry {
else
{
if ( objQueue.size() < MAX_QUEUE_SIZE )
{
{
objQueue.add(objInfo);
}
else
@ -469,7 +500,7 @@ public class Telemetry {
/**
* Process events from the object queue
* @throws IOException
* @throws IOException
*/
private synchronized void processObjectQueue() throws IOException
{
@ -536,7 +567,7 @@ public class Telemetry {
}
// If this is a metaobject then make necessary telemetry updates
if (objInfo.obj.isMetadata())
if (objInfo.obj.isMetadata())
{
UAVMetaObject metaobj = (UAVMetaObject) objInfo.obj;
updateObject( metaobj.getParentObject() );
@ -554,11 +585,11 @@ public class Telemetry {
/**
* Check is any objects are pending for periodic updates
* TODO: Clean-up
* @throws IOException
* @throws IOException
*/
private synchronized void processPeriodicUpdates() throws IOException
{
if (DEBUG) Log.d(TAG, "processPeriodicUpdates()");
// Stop timer
updateTimer.cancel();
@ -669,7 +700,7 @@ public class Telemetry {
{
registerObject(obj);
}
/**
* Stop all the telemetry timers
*/
@ -692,24 +723,24 @@ public class Telemetry {
/**
* Private variables
*/
private UAVObjectManager objMngr;
private UAVTalk utalk;
private final UAVObjectManager objMngr;
private final UAVTalk utalk;
private UAVObject gcsStatsObj;
private List<ObjectTimeInfo> objList = new ArrayList<ObjectTimeInfo>();
private Queue<ObjectQueueInfo> objQueue = new LinkedList<ObjectQueueInfo>();
private Queue<ObjectQueueInfo> objPriorityQueue = new LinkedList<ObjectQueueInfo>();
private ObjectTransactionInfo transInfo = new ObjectTransactionInfo();
private final List<ObjectTimeInfo> objList = new ArrayList<ObjectTimeInfo>();
private final Queue<ObjectQueueInfo> objQueue = new LinkedList<ObjectQueueInfo>();
private final Queue<ObjectQueueInfo> objPriorityQueue = new LinkedList<ObjectQueueInfo>();
private final ObjectTransactionInfo transInfo = new ObjectTransactionInfo();
private boolean transPending;
private Timer updateTimer;
private TimerTask updateTimerTask;
private Timer transTimer;
private TimerTask transTimerTask;
private int timeToNextUpdateMs;
private int txErrors;
private int txRetries;
/**
* Private constants
*/
@ -718,7 +749,7 @@ public class Telemetry {
private static final int MAX_UPDATE_PERIOD_MS = 1000;
private static final int MIN_UPDATE_PERIOD_MS = 1;
private static final int MAX_QUEUE_SIZE = 20;
}

View File

@ -1,3 +1,28 @@
/**
******************************************************************************
* @file TelemetryMonitor.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief High level monitoring of telemetry to handle connection and
* disconnection and then signal the rest of the application.
* This also makes sure to fetch all objects on initial connection.
* @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.uavtalk;
import java.io.IOException;
@ -22,22 +47,22 @@ public class TelemetryMonitor extends Observable{
static final int STATS_CONNECT_PERIOD_MS = 1000;
static final int CONNECTION_TIMEOUT_MS = 8000;
private UAVObjectManager objMngr;
private Telemetry tel;
private final UAVObjectManager objMngr;
private final Telemetry tel;
// private UAVObject objPending;
private UAVObject gcsStatsObj;
private UAVObject flightStatsObj;
private Timer periodicTask;
private int currentPeriod;
private long lastUpdateTime;
private List<UAVObject> queue;
private final List<UAVObject> queue;
private boolean connected = false;
private boolean objects_updated = false;
public boolean getConnected() { return connected; };
public boolean getObjectsUpdated() { return objects_updated; };
public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel)
{
this.objMngr = objMngr;
@ -50,6 +75,7 @@ public class TelemetryMonitor extends Observable{
flightStatsObj = objMngr.getObject("FlightTelemetryStats");
flightStatsObj.addUpdatedObserver(new Observer() {
@Override
public void update(Observable observable, Object data) {
try {
flightStatsUpdated((UAVObject) data);
@ -59,7 +85,7 @@ public class TelemetryMonitor extends Observable{
// or fix the stream?
flightStatsObj.removeUpdatedObserver(this);
}
}
}
});
// Start update timer
@ -68,17 +94,17 @@ public class TelemetryMonitor extends Observable{
/**
* Initiate object retrieval, initialize queue with objects to be retrieved.
* @throws IOException
* @throws IOException
*/
public synchronized void startRetrievingObjects() throws IOException
{
if (DEBUG) Log.d(TAG, "Start retrieving objects");
// Clear object queue
queue.clear();
// Get all objects, add metaobjects, settings and data objects with OnChange update mode to the queue
List< List<UAVObject> > objs = objMngr.getObjects();
ListIterator<List<UAVObject>> objListIterator = objs.listIterator();
while( objListIterator.hasNext() )
{
@ -121,7 +147,7 @@ public class TelemetryMonitor extends Observable{
/**
* Retrieve the next object in the queue
* @throws IOException
* @throws IOException
*/
public synchronized void retrieveNextObject() throws IOException
{
@ -136,16 +162,17 @@ public class TelemetryMonitor extends Observable{
}
// Get next object from the queue
UAVObject obj = queue.remove(0);
if(obj == null) {
throw new Error("Got null object forom transaction queue");
}
if (DEBUG) Log.d(TAG, "Retrieving object: " + obj.getName()) ;
// Connect to object
// TODO: Does this need to stay here permanently? This appears to be used for setup mainly
obj.addTransactionCompleted(new Observer() {
@Override
public void update(Observable observable, Object data) {
UAVObject.TransactionResult result = (UAVObject.TransactionResult) data;
if (DEBUG) Log.d(TAG,"Got transaction completed event from " + result.obj.getName() + " status: " + result.success);
@ -155,7 +182,7 @@ public class TelemetryMonitor extends Observable{
// When the telemetry stream is broken disconnect these updates
observable.deleteObserver(this);
}
}
}
});
// Request update
@ -165,7 +192,7 @@ public class TelemetryMonitor extends Observable{
/**
* Called by the retrieved object when a transaction is completed.
* @throws IOException
* @throws IOException
*/
public synchronized void transactionCompleted(UAVObject obj, boolean success) throws IOException
{
@ -175,12 +202,12 @@ public class TelemetryMonitor extends Observable{
// TODO: Need to be able to disconnect signals
//obj->disconnect(this);
// objPending = null;
if(!success) {
//Log.e(TAG, "Transaction failed: " + obj.getName() + " sending again.");
return;
}
// Process next object if telemetry is still available
if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 )
{
@ -194,7 +221,7 @@ public class TelemetryMonitor extends Observable{
/**
* Called each time the flight stats object is updated by the autopilot
* @throws IOException
* @throws IOException
*/
public synchronized void flightStatsUpdated(UAVObject obj) throws IOException
{
@ -213,7 +240,7 @@ public class TelemetryMonitor extends Observable{
private long lastStatsTime;
/**
* Called periodically to update the statistics and connection status.
* @throws IOException
* @throws IOException
*/
public synchronized void processStatsUpdates() throws IOException
{
@ -222,14 +249,14 @@ public class TelemetryMonitor extends Observable{
Telemetry.TelemetryStats telStats = tel.getStats();
if (DEBUG) Log.d(TAG, "processStatsUpdates() - stats reset");
// Need to compute time because this update is not regular enough
float dT = (float) (System.currentTimeMillis() - lastStatsTime) / 1000.0f;
float dT = (System.currentTimeMillis() - lastStatsTime) / 1000.0f;
lastStatsTime = System.currentTimeMillis();
// Update stats object
gcsStatsObj.getField("RxDataRate").setDouble( (float)telStats.rxBytes / dT );
gcsStatsObj.getField("TxDataRate").setDouble( (float)telStats.txBytes / dT );
// Update stats object
gcsStatsObj.getField("RxDataRate").setDouble( telStats.rxBytes / dT );
gcsStatsObj.getField("TxDataRate").setDouble( telStats.txBytes / dT );
UAVObjectField field = gcsStatsObj.getField("RxFailures");
field.setDouble(field.getDouble() + telStats.rxErrors);
field = gcsStatsObj.getField("TxFailures");
@ -240,7 +267,7 @@ public class TelemetryMonitor extends Observable{
tel.resetStats();
if (DEBUG) Log.d(TAG, "processStatsUpdates() - stats updated");
// Check for a connection timeout
boolean connectionTimeout;
if ( telStats.rxObjects > 0 )
@ -266,7 +293,7 @@ public class TelemetryMonitor extends Observable{
}
UAVObjectField statusField = gcsStatsObj.getField("Status");
String oldStatus = new String((String) statusField.getValue());
if (DEBUG) Log.d(TAG,"GCS: " + statusField.getValue() + " Flight: " + flightStatsObj.getField("Status").getValue());
if ( oldStatus.compareTo("Disconnected") == 0 )
@ -294,11 +321,11 @@ public class TelemetryMonitor extends Observable{
// Force telemetry update if not yet connected
boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue());
boolean gcsConnected = statusField.getValue().equals("Connected");
boolean gcsDisconnected = statusField.getValue().equals("Disconnected");
boolean flightConnected = flightStatsObj.getField("Status").equals("Connected");
if ( !gcsConnected || !flightConnected )
{
if (DEBUG) Log.d(TAG,"Sending gcs status");
@ -323,7 +350,7 @@ public class TelemetryMonitor extends Observable{
objects_updated = false;
setChanged();
}
if (DEBUG) Log.d(TAG, "processStatsUpdates() - before notify");
notifyObservers();
if (DEBUG) Log.d(TAG, "processStatsUpdates() - after notify");
@ -344,11 +371,11 @@ public class TelemetryMonitor extends Observable{
} catch (IOException e) {
// Once the stream has died stop trying to process these updates
periodicTask.cancel();
}
}
}
}
}, currentPeriod, currentPeriod);
}
public void stopMonitor()
{
periodicTask.cancel();

View File

@ -1,11 +1,34 @@
/**
******************************************************************************
* @file UAVDataObject.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief The base object for all UAVO data.
* @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.uavtalk;
public abstract class UAVDataObject extends UAVObject {
/**
* @brief Constructor for UAVDataObject
* @param objID the object id to be created
* @param isSingleInst
* @param isSingleInst
* @param isSet
* @param name
*/
@ -24,6 +47,7 @@ public abstract class UAVDataObject extends UAVObject {
super.initialize(instID);
}
@Override
public boolean isMetadata() { return false; };
/**
* Assign a metaobject
@ -45,6 +69,7 @@ public abstract class UAVDataObject extends UAVObject {
/**
* Set the object's metadata
*/
@Override
public void setMetadata(Metadata mdata)
{
if ( mobj != null )
@ -56,6 +81,7 @@ public abstract class UAVDataObject extends UAVObject {
/**
* Get the object's metadata
*/
@Override
public Metadata getMetadata()
{
if ( mobj != null)
@ -75,13 +101,13 @@ public abstract class UAVDataObject extends UAVObject {
{
return mobj;
}
// TODO: Make abstract
public UAVDataObject clone(long instID) {
return (UAVDataObject) super.clone();
}
private UAVMetaObject mobj;
private boolean isSet;
private final boolean isSet;
}

View File

@ -1,3 +1,26 @@
/**
******************************************************************************
* @file UAVMetaObject.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Base object for all UAVO meta data
* @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.uavtalk;
import java.nio.ByteBuffer;
@ -10,7 +33,7 @@ public class UAVMetaObject extends UAVObject {
public UAVMetaObject(long objID, String name, UAVDataObject parent) throws Exception {
super(objID, true, name);
this.parent = parent;
ownMetadata = new Metadata();
ownMetadata.flags = 0; // TODO: Fix flags
@ -27,7 +50,7 @@ public class UAVMetaObject extends UAVObject {
modesBitField.add("FlightUpdateOnChange");
modesBitField.add("GCSUpdatePeriodic");
modesBitField.add("GCSUpdateOnChange");
List<UAVObjectField> fields = new ArrayList<UAVObjectField>();
fields.add( new UAVObjectField("Modes", "", UAVObjectField.FieldType.BITFIELD, 1, modesBitField) );
fields.add( new UAVObjectField("Flight Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) );
@ -47,12 +70,12 @@ public class UAVMetaObject extends UAVObject {
initializeFields(fields, ByteBuffer.allocate(numBytes), numBytes);
// Setup metadata of parent
parentMetadata = parent.getDefaultMetadata();
parentMetadata = parent.getDefaultMetadata();
}
@Override
public boolean isMetadata() {
return true;
public boolean isMetadata() {
return true;
};
/**
@ -67,6 +90,7 @@ public class UAVMetaObject extends UAVObject {
* Set the metadata of the metaobject, this function will
* do nothing since metaobjects have read-only metadata.
*/
@Override
public void setMetadata(Metadata mdata)
{
return; // can not update metaobject's metadata
@ -75,6 +99,7 @@ public class UAVMetaObject extends UAVObject {
/**
* Get the metadata of the metaobject
*/
@Override
public Metadata getMetadata()
{
return ownMetadata;
@ -83,6 +108,7 @@ public class UAVMetaObject extends UAVObject {
/**
* Get the default metadata
*/
@Override
public Metadata getDefaultMetadata()
{
return ownMetadata;
@ -110,8 +136,8 @@ public class UAVMetaObject extends UAVObject {
}
private UAVObject parent;
private Metadata ownMetadata;
private final UAVObject parent;
private final Metadata ownMetadata;
private Metadata parentMetadata;

View File

@ -1,17 +1,40 @@
/**
******************************************************************************
* @file UAVObject.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Base object for UAVDataObject and UAVMetaObject.
* @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.uavtalk;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Observer;
import java.util.Observable;
import java.util.Observer;
public abstract class UAVObject {
public class CallbackListener extends Observable {
private UAVObject parent;
public class CallbackListener extends Observable {
private final UAVObject parent;
public CallbackListener(UAVObject parent) {
this.parent = parent;
}
@ -29,7 +52,7 @@ public abstract class UAVObject {
}
}
}
public class TransactionResult {
public UAVObject obj;
public boolean success;
@ -38,8 +61,8 @@ public abstract class UAVObject {
this.success = success;
}
}
private CallbackListener transactionCompletedListeners = new CallbackListener(this);
private final CallbackListener transactionCompletedListeners = new CallbackListener(this);
public void addTransactionCompleted(Observer o) {
synchronized(transactionCompletedListeners) {
transactionCompletedListeners.addObserver(o);
@ -55,8 +78,8 @@ public abstract class UAVObject {
transactionCompletedListeners.event(new TransactionResult(this,status));
}
}
private CallbackListener updatedListeners = new CallbackListener(this);
private final CallbackListener updatedListeners = new CallbackListener(this);
public void removeUpdatedObserver(Observer o) {
synchronized(updatedListeners) {
updatedListeners.deleteObserver(o);
@ -75,8 +98,8 @@ public abstract class UAVObject {
updatedManual();
}
public void updated() { updated(true); };
private CallbackListener unpackedListeners = new CallbackListener(this);
private final CallbackListener unpackedListeners = new CallbackListener(this);
public void addUnpackedObserver(Observer o) {
synchronized(unpackedListeners) {
unpackedListeners.addObserver(o);
@ -88,7 +111,7 @@ public abstract class UAVObject {
}
}
private CallbackListener updatedAutoListeners = new CallbackListener(this);
private final CallbackListener updatedAutoListeners = new CallbackListener(this);
public void addUpdatedAutoObserver(Observer o) {
synchronized(updatedAutoListeners) {
updatedAutoListeners.addObserver(o);
@ -100,7 +123,7 @@ public abstract class UAVObject {
}
}
private CallbackListener updatedManualListeners = new CallbackListener(this);
private final CallbackListener updatedManualListeners = new CallbackListener(this);
public void addUpdatedManualObserver(Observer o) {
synchronized(updatedManualListeners) {
updatedManualListeners.addObserver(o);
@ -112,7 +135,7 @@ public abstract class UAVObject {
}
}
private CallbackListener updateRequestedListeners = new CallbackListener(this);
private final CallbackListener updateRequestedListeners = new CallbackListener(this);
public void addUpdateRequestedObserver(Observer o) {
synchronized(updateRequestedListeners) {
updateRequestedListeners.addObserver(o);
@ -125,7 +148,7 @@ public abstract class UAVObject {
}
public abstract boolean isMetadata();
/**
* Object update mode
*/
@ -172,10 +195,10 @@ public abstract class UAVObject {
/** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */
public int flightTelemetryUpdatePeriod;
/** Update period used by the GCS (only if telemetry mode is PERIODIC) */
public int gcsTelemetryUpdatePeriod;
/** Update period used by the GCS (only if telemetry mode is PERIODIC) */
public int loggingUpdatePeriod;
/**
@ -194,7 +217,7 @@ public abstract class UAVObject {
private void SET_BITS(int shift, int value, int mask) {
this.flags = (this.flags & ~(mask << shift)) | (value << shift);
}
/**
* Get the UAVObject metadata access member
* \return the access type
@ -219,7 +242,7 @@ public abstract class UAVObject {
* \return the GCS access type
*/
public AccessMode GetGcsAccess()
{
{
return AccessModeEnum((this.flags >> UAVOBJ_GCS_ACCESS_SHIFT) & 1);
}
@ -382,7 +405,7 @@ public abstract class UAVObject {
/**
* Initialize objects' data fields
*
*
* @param fields
* List of fields held by the object
* @param data
@ -434,7 +457,7 @@ public abstract class UAVObject {
/**
* Get the description of the object
*
*
* @return The description of the object
*/
public String getDescription() {
@ -443,7 +466,7 @@ public abstract class UAVObject {
/**
* Set the description of the object
*
*
* @param The
* description of the object
* @return
@ -525,7 +548,7 @@ public abstract class UAVObject {
/**
* Get a specific field
*
*
* @throws Exception
* @returns The field or NULL if not found
*/
@ -543,7 +566,7 @@ public abstract class UAVObject {
/**
* Pack the object data into a byte array
*
*
* @param dataOut
* ByteBuffer to receive the data.
* @throws Exception
@ -565,7 +588,7 @@ public abstract class UAVObject {
/**
* Unpack the object data from a byte array
*
*
* @param dataIn
* The ByteBuffer to pull data from
* @throws Exception
@ -582,11 +605,11 @@ public abstract class UAVObject {
UAVObjectField field = li.next();
numBytes += field.unpack(dataIn);
}
// Trigger all the listeners for the unpack event
unpacked();
updated(false);
return numBytes;
}
@ -774,6 +797,7 @@ public abstract class UAVObject {
/**
* Java specific functions
*/
@Override
public synchronized UAVObject clone() {
UAVObject newObj = clone();
List<UAVObjectField> newFields = new ArrayList<UAVObjectField>();

View File

@ -1,3 +1,26 @@
/**
******************************************************************************
* @file Telemetry.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Implementation of all the UAVObjectFields.
* @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.uavtalk;
import java.nio.ByteBuffer;
@ -6,7 +29,7 @@ import java.util.ArrayList;
import java.util.List;
public class UAVObjectField {
public enum FieldType { INT8, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, BITFIELD, STRING };
public UAVObjectField(String name, String units, FieldType type, int numElements, List<String> options) {
@ -17,26 +40,26 @@ public class UAVObjectField {
elementNames.add(String.valueOf(n));
}
// Initialize
constructorInitialize(name, units, type, elementNames, options);
constructorInitialize(name, units, type, elementNames, options);
}
public UAVObjectField(String name, String units, FieldType type, List<String> elementNames, List<String> options) {
constructorInitialize(name, units, type, elementNames, options);
}
public void initialize(UAVObject obj){
this.obj = obj;
//clear();
//clear();
}
public UAVObject getObject() {
return obj;
}
public FieldType getType() {
return type;
}
public String getTypeAsString() {
switch (type)
{
@ -62,31 +85,31 @@ public class UAVObjectField {
return "string";
default:
return "";
}
}
}
public String getName() {
return name;
}
public String getUnits() {
return units;
}
public int getNumElements() {
return numElements;
}
public List<String> getElementNames() {
return elementNames;
return elementNames;
}
public List<String> getOptions() {
return options;
}
/**
* This function copies this field from the internal storage of the parent object
* This function copies this field from the internal storage of the parent object
* to a new ByteBuffer for UAVTalk. It also converts from the java standard (big endian)
* to the arm/uavtalk standard (little endian)
* @param dataOut
@ -98,7 +121,7 @@ public class UAVObjectField {
dataOut.order(ByteOrder.LITTLE_ENDIAN);
switch (type)
{
case INT8:
case INT8:
for (int index = 0; index < numElements; ++index) {
Integer val = (Integer) getValue(index);
dataOut.put(val.byteValue());
@ -116,7 +139,7 @@ public class UAVObjectField {
dataOut.putInt(val);
}
break;
case UINT8:
case UINT8:
// TODO: Deal properly with unsigned
for (int index = 0; index < numElements; ++index) {
Integer val = (Integer) getValue(index);
@ -144,7 +167,7 @@ public class UAVObjectField {
case ENUM:
List<Byte> l = (List<Byte>) data;
for (int index = 0; index < numElements; ++index)
dataOut.put((Byte) l.get(index));
dataOut.put(l.get(index));
break;
case BITFIELD:
for (int index = 0; index < numElements; ++index) {
@ -156,9 +179,9 @@ public class UAVObjectField {
throw new Error("Strings not yet implemented");
}
// Done
return getNumBytes();
return getNumBytes();
}
@SuppressWarnings("unchecked")
public synchronized int unpack(ByteBuffer dataIn) {
// Unpack each element from input buffer
@ -196,7 +219,7 @@ public class UAVObjectField {
{
List<Short> l = (List<Short>) this.data;
for (int index = 0 ; index < numElements; ++index) {
int signedval = (int) dataIn.get(); // this sign extends it
int signedval = dataIn.get(); // this sign extends it
int unsignedval = signedval & 0xff; // drop sign extension
l.set(index, (short) unsignedval);
}
@ -206,7 +229,7 @@ public class UAVObjectField {
{
List<Integer> l = (List<Integer>) this.data;
for (int index = 0 ; index < numElements; ++index) {
int signedval = (int) dataIn.getShort(); // this sign extends it
int signedval = dataIn.getShort(); // this sign extends it
int unsignedval = signedval & 0xffff; // drop sign extension
l.set(index, unsignedval);
}
@ -216,7 +239,7 @@ public class UAVObjectField {
{
List<Long> l = (List<Long>) this.data;
for (int index = 0 ; index < numElements; ++index) {
long signedval = (long) dataIn.getInt(); // this sign extends it
long signedval = dataIn.getInt(); // this sign extends it
long unsignedval = signedval & 0xffffffffL; // drop sign extension
l.set(index, unsignedval);
}
@ -235,7 +258,7 @@ public class UAVObjectField {
{
List<Short> l = (List<Short>) this.data;
for (int index = 0 ; index < numElements; ++index) {
int signedval = (int) dataIn.get(); // this sign extends it
int signedval = dataIn.get(); // this sign extends it
int unsignedval = signedval & 0xff; // drop sign extension
l.set(index, (short) unsignedval);
}
@ -254,9 +277,9 @@ public class UAVObjectField {
//throw new Exception("Strings not handled");
}
// Done
return getNumBytes();
return getNumBytes();
}
public Object getValue() { return getValue(0); };
@SuppressWarnings("unchecked")
public synchronized Object getValue(int index) {
@ -265,7 +288,7 @@ public class UAVObjectField {
{
return null;
}
switch (type)
{
case INT8:
@ -287,7 +310,7 @@ public class UAVObjectField {
List<Byte> l = (List<Byte>) data;
Byte val = l.get(index);
//if(val >= options.size() || val < 0)
//if(val >= options.size() || val < 0)
// throw new Exception("Invalid value for" + name);
return options.get(val);
@ -301,10 +324,10 @@ public class UAVObjectField {
}
}
// If this point is reached then we got an invalid type
return null;
return null;
}
public void setValue(Object data) { setValue(data,0); }
public void setValue(Object data) { setValue(data,0); }
@SuppressWarnings("unchecked")
public synchronized void setValue(Object data, int index) {
// Check that index is not out of bounds
@ -361,15 +384,15 @@ public class UAVObjectField {
break;
}
case ENUM:
{
{
byte val;
try {
// Test if numeric constant passed in
val = ((Number) data).byteValue();
} catch (Exception e) {
val = (byte) options.indexOf((String) data);
val = (byte) options.indexOf(data);
}
//if(val < 0) throw new Exception("Enumerated value not found");
//if(val < 0) throw new Exception("Enumerated value not found");
List<Byte> l = (List<Byte>) this.data;
l.set(index, val);
break;
@ -380,7 +403,7 @@ public class UAVObjectField {
l.set(index, bound(data).shortValue());
break;
}
case STRING:
case STRING:
{
//throw new Exception("Sorry I haven't implemented strings yet");
}
@ -388,7 +411,7 @@ public class UAVObjectField {
//obj.updated();
}
}
public double getDouble() { return getDouble(0); };
@SuppressWarnings("unchecked")
public double getDouble(int index) {
@ -400,24 +423,24 @@ public class UAVObjectField {
}
return ((Number) getValue(index)).doubleValue();
}
public void setDouble(double value) { setDouble(value, 0); };
public void setDouble(double value, int index) {
setValue(value, index);
}
public int getDataOffset() {
return offset;
return offset;
}
public int getNumBytes() {
return numBytesPerElement * numElements;
}
public int getNumBytesElement() {
return numBytesPerElement;
}
public boolean isNumeric() {
switch (type)
{
@ -443,9 +466,9 @@ public class UAVObjectField {
return false;
default:
return false;
}
}
}
public boolean isText() {
switch (type)
{
@ -471,9 +494,10 @@ public class UAVObjectField {
return true;
default:
return false;
}
}
}
@Override
public String toString() {
String sout = new String();
sout += name + ": ";
@ -484,15 +508,15 @@ public class UAVObjectField {
else
sout += " ";
}
if (units.length() > 0)
if (units.length() > 0)
sout += " (" + units + ")\n";
else
sout += "\n";
return sout;
return sout;
}
void fieldUpdated(UAVObjectField field) {
}
@SuppressWarnings("unchecked")
@ -555,7 +579,7 @@ public class UAVObjectField {
break;
}
}
public synchronized void constructorInitialize(String name, String units, FieldType type, List<String> elementNames, List<String> options) {
// Copy params
this.name = name;
@ -572,43 +596,43 @@ public class UAVObjectField {
switch (type)
{
case INT8:
data = (Object) new ArrayList<Byte>(this.numElements);
data = new ArrayList<Byte>(this.numElements);
numBytesPerElement = 1;
break;
case INT16:
data = (Object) new ArrayList<Short>(this.numElements);
data = new ArrayList<Short>(this.numElements);
numBytesPerElement = 2;
break;
case INT32:
data = (Object) new ArrayList<Integer>(this.numElements);
data = new ArrayList<Integer>(this.numElements);
numBytesPerElement = 4;
break;
case UINT8:
data = (Object) new ArrayList<Short>(this.numElements);
data = new ArrayList<Short>(this.numElements);
numBytesPerElement = 1;
break;
case UINT16:
data = (Object) new ArrayList<Integer>(this.numElements);
data = new ArrayList<Integer>(this.numElements);
numBytesPerElement = 2;
break;
case UINT32:
data = (Object) new ArrayList<Long>(this.numElements);
data = new ArrayList<Long>(this.numElements);
numBytesPerElement = 4;
break;
case FLOAT32:
data = (Object) new ArrayList<Float>(this.numElements);
data = new ArrayList<Float>(this.numElements);
numBytesPerElement = 4;
break;
case ENUM:
data = (Object) new ArrayList<Byte>(this.numElements);
data = new ArrayList<Byte>(this.numElements);
numBytesPerElement = 1;
break;
case BITFIELD:
data = (Object) new ArrayList<Short>(this.numElements);
data = new ArrayList<Short>(this.numElements);
numBytesPerElement = 1;
break;
case STRING:
data = (Object) new ArrayList<String>(this.numElements);
data = new ArrayList<String>(this.numElements);
numBytesPerElement = 1;
break;
default:
@ -616,7 +640,7 @@ public class UAVObjectField {
}
clear();
}
/**
* For numerical types bounds the data appropriately
* @param val Can be any object, for numerical tries to cast to Number
@ -624,7 +648,7 @@ public class UAVObjectField {
* @note This is mostly needed because java has no unsigned integer
*/
protected Long bound (Object val) {
switch(type) {
case ENUM:
case STRING:
@ -679,15 +703,15 @@ public class UAVObjectField {
return (long) 255;
return num;
}
return num;
}
@Override
public UAVObjectField clone()
{
UAVObjectField newField = new UAVObjectField(new String(name), new String(units), type,
new ArrayList<String>(elementNames),
UAVObjectField newField = new UAVObjectField(new String(name), new String(units), type,
new ArrayList<String>(elementNames),
new ArrayList<String>(options));
newField.initialize(obj);
newField.data = data;

View File

@ -1,3 +1,28 @@
/**
******************************************************************************
* @file UAVObjectManager.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Critical class. This is the data store for all UAVOs. Allows
* other objects to access and change this data. Takes care of
* propagating changes to the UAV.
* @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.uavtalk;
import java.util.ArrayList;
@ -8,19 +33,19 @@ import java.util.Observer;
public class UAVObjectManager {
public class CallbackListener extends Observable {
public class CallbackListener extends Observable {
public void event (UAVObject obj) {
setChanged();
notifyObservers(obj);
}
}
private CallbackListener newInstance = new CallbackListener();
private final CallbackListener newInstance = new CallbackListener();
public void addNewInstanceObserver(Observer o) {
synchronized(newInstance) {
newInstance.addObserver(o);
}
}
private CallbackListener newObject = new CallbackListener();
private final CallbackListener newObject = new CallbackListener();
public void addNewObjectObserver(Observer o) {
synchronized(newObject) {
newObject.addObserver(o);
@ -29,7 +54,7 @@ public class UAVObjectManager {
private final int MAX_INSTANCES = 10;
// Use array list to store objects since rarely added or deleted
private List<List<UAVObject>> objects = new ArrayList<List<UAVObject>>();
private final List<List<UAVObject>> objects = new ArrayList<List<UAVObject>>();
public UAVObjectManager()
{
@ -41,7 +66,7 @@ public class UAVObjectManager {
* A new instance can be created directly by instantiating a new object or by calling clone() of
* an existing object. The object will be registered and will be properly initialized so that it can accept
* updates.
* @throws Exception
* @throws Exception
*/
public synchronized boolean registerObject(UAVDataObject obj) throws Exception
{
@ -61,7 +86,7 @@ public class UAVObjectManager {
}
// The object type has alredy been added, so now we need to initialize the new instance with the appropriate id
// There is a single metaobject for all object instances of this type, so no need to create a new one
// Get object type metaobject from existing instance
// Get object type metaobject from existing instance
UAVDataObject refObj = (UAVDataObject) instList.get(0);
if (refObj == null)
{
@ -74,7 +99,7 @@ public class UAVObjectManager {
return false;
}
// If InstID is zero then we find the next open instId and create it
// If InstID is zero then we find the next open instId and create it
if (obj.getInstID() == 0)
{
// Assign the next available ID and initialize the object instance the nadd
@ -183,13 +208,13 @@ public class UAVObjectManager {
// If no instances skip
if(instList.size() == 0)
continue;
// If meta data skip
if(instList.get(0).isMetadata())
continue;
List<UAVDataObject> newInstList = new ArrayList<UAVDataObject>();
ListIterator<UAVObject> instIt = instList.listIterator();
List<UAVDataObject> newInstList = new ArrayList<UAVDataObject>();
ListIterator<UAVObject> instIt = instList.listIterator();
while(instIt.hasNext()) {
newInstList.add((UAVDataObject) instIt.next());
}
@ -216,13 +241,13 @@ public class UAVObjectManager {
// If no instances skip
if(instList.size() == 0)
continue;
// If meta data skip
if(!instList.get(0).isMetadata())
continue;
List<UAVMetaObject> newInstList = new ArrayList<UAVMetaObject>();
ListIterator<UAVObject> instIt = instList.listIterator();
List<UAVMetaObject> newInstList = new ArrayList<UAVMetaObject>();
ListIterator<UAVObject> instIt = instList.listIterator();
while(instIt.hasNext()) {
newInstList.add((UAVMetaObject) instIt.next());
}
@ -232,17 +257,17 @@ public class UAVObjectManager {
return mObjects;
}
/**
* Returns a specific object by name only, returns instance ID zero
* @param name The object name
* @return The object or null if not found
*/
public UAVObject getObject(String name)
public UAVObject getObject(String name)
{
return getObject(name, 0, 0);
}
/**
* Get a specific object given its name and instance ID
* @returns The object is found or NULL if not
@ -257,11 +282,11 @@ public class UAVObjectManager {
* @param objId the object id
* @returns The object is found or NULL if not
*/
public UAVObject getObject(long objId)
public UAVObject getObject(long objId)
{
return getObject(null, objId, 0);
}
/**
* Get a specific object given its object and instance ID
* @returns The object is found or NULL if not
@ -293,7 +318,7 @@ public class UAVObjectManager {
}
}
}
return null;
}
@ -327,8 +352,8 @@ public class UAVObjectManager {
return instList;
}
}
}
}
return null;
}

View File

@ -1,3 +1,29 @@
/**
******************************************************************************
* @file UAVTalk.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief The protocol layer implementation of UAVTalk. Serializes objects
* for transmission (which is done in the object itself which is aware
* of byte packing) wraps that in the UAVTalk packet. Parses UAVTalk
* packets and updates the UAVObjectManager.
* @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.uavtalk;
import java.io.IOException;
@ -17,7 +43,7 @@ public class UAVTalk extends Observable {
public static boolean DEBUG = LOGLEVEL > 0;
private Thread inputProcessingThread = null;
/**
* A reference to the thread for processing the incoming stream. Currently this method is ONLY
* used for unit testing
@ -26,6 +52,7 @@ public class UAVTalk extends Observable {
if (inputProcessingThread == null)
inputProcessingThread = new Thread() {
@Override
public void run() {
while(true) {
try {
@ -179,7 +206,7 @@ public class UAVTalk extends Observable {
/**
* Process any data in the queue
* @throws IOException
* @throws IOException
*/
public boolean processInputStream() throws IOException {
int val;
@ -195,13 +222,13 @@ public class UAVTalk extends Observable {
return true;
}
/**
* Request an update for the specified object, on success the object data
* would have been updated by the GCS. \param[in] obj Object to update
* \param[in] allInstances If set true then all instances will be updated
* \return Success (true), Failure (false)
* @throws IOException
* @throws IOException
*/
public boolean sendObjectRequest(UAVObject obj, boolean allInstances) throws IOException {
// QMutexLocker locker(mutex);
@ -213,7 +240,7 @@ public class UAVTalk extends Observable {
* Object to send \param[in] acked Selects if an ack is required \param[in]
* allInstances If set true then all instances will be updated \return
* Success (true), Failure (false)
* @throws IOException
* @throws IOException
*/
public synchronized boolean sendObject(UAVObject obj, boolean acked,
boolean allInstances) throws IOException {
@ -237,7 +264,7 @@ public class UAVTalk extends Observable {
* request object update TYPE_OBJ_ACK: send object with an ack \param[in]
* allInstances If set true then all instances will be updated \return
* Success (true), Failure (false)
* @throws IOException
* @throws IOException
*/
public boolean objectTransaction(UAVObject obj, int type,
boolean allInstances) throws IOException {
@ -260,7 +287,7 @@ public class UAVTalk extends Observable {
/**
* Process an byte from the telemetry stream. \param[in] rxbyte Received
* byte \return Success (true), Failure (false)
* @throws IOException
* @throws IOException
*/
public synchronized boolean processInputByte(int rxbyte) throws IOException {
assert (objMngr != null);
@ -341,7 +368,7 @@ public class UAVTalk extends Observable {
// Search for object, if not found reset state machine
rxObjId = rxTmpBuffer.getInt(0);
// Because java treats ints as only signed we need to do this manually
if (rxObjId < 0)
if (rxObjId < 0)
rxObjId = 0x100000000l + rxObjId;
{
UAVObject rxObj = objMngr.getObject(rxObjId);
@ -475,11 +502,11 @@ public class UAVTalk extends Observable {
* received object \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES
* for all instances. \param[in] data Data buffer \param[in] length Buffer
* length \return Success (true), Failure (false)
* @throws IOException
* @throws IOException
*/
public boolean receiveObject(int type, long objId, long instId,
ByteBuffer data) throws IOException {
if (DEBUG) Log.d(TAG, "Received object ID: " + objId);
assert (objMngr != null);
@ -622,12 +649,12 @@ public class UAVTalk extends Observable {
}
/**
* Send an object through the telemetry link.
* Send an object through the telemetry link.
* @param[in] obj Object to send
* @param[in] type Transaction type
* @param[in] allInstances True is all instances of the object are to be sent
* @param[in] type Transaction type
* @param[in] allInstances True is all instances of the object are to be sent
* @return Success (true), Failure (false)
* @throws IOException
* @throws IOException
*/
public synchronized boolean transmitObject(UAVObject obj, int type, boolean allInstances) throws IOException {
// If all instances are requested on a single instance object it is an
@ -665,7 +692,7 @@ public class UAVTalk extends Observable {
/**
* Send an object through the telemetry link.
* @throws IOException
* @throws IOException
* @param[in] obj Object handle to send
* @param[in] type Transaction type \return Success (true), Failure (false)
*/
@ -738,11 +765,11 @@ public class UAVTalk extends Observable {
/**
* Update the crc value with new data.
*
*
* Generated by pycrc v0.7.5, http://www.tty1.net/pycrc/ using the
* configuration: Width = 8 Poly = 0x07 XorIn = 0x00 ReflectIn = False
* XorOut = 0x00 ReflectOut = False Algorithm = table-driven
*
*
* \param crc The current crc value. \param data Pointer to a buffer of \a
* data_len bytes. \param length Number of bytes in the \a data buffer.
* \return The updated crc value.
@ -753,7 +780,7 @@ public class UAVTalk extends Observable {
int updateCRC(int crc, byte[] data, int length) {
for (int i = 0; i < length; i++)
crc = updateCRC(crc, (int) data[i]);
crc = updateCRC(crc, data[i]);
return crc;
}

View File

@ -0,0 +1,210 @@
/**
******************************************************************************
*
* @file uavobjecttemplate.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Template for an uavobject in java
* This is a autogenerated file!! Do not modify and expect a result.
* Settings for the @ref GuidanceModule
*
* @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.uavtalk.uavobjects;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVDataObject;
import org.openpilot.uavtalk.UAVObjectField;
/**
Settings for the @ref GuidanceModule
generated from guidancesettings.xml
**/
public class GuidanceSettings extends UAVDataObject {
public GuidanceSettings() {
super(OBJID, ISSINGLEINST, ISSETTINGS, NAME);
List<UAVObjectField> fields = new ArrayList<UAVObjectField>();
List<String> HorizontalPosPIElemNames = new ArrayList<String>();
HorizontalPosPIElemNames.add("Kp");
HorizontalPosPIElemNames.add("Ki");
HorizontalPosPIElemNames.add("ILimit");
fields.add( new UAVObjectField("HorizontalPosPI", "(m/s)/m", UAVObjectField.FieldType.FLOAT32, HorizontalPosPIElemNames, null) );
List<String> HorizontalVelPIDElemNames = new ArrayList<String>();
HorizontalVelPIDElemNames.add("Kp");
HorizontalVelPIDElemNames.add("Ki");
HorizontalVelPIDElemNames.add("Kd");
HorizontalVelPIDElemNames.add("ILimit");
fields.add( new UAVObjectField("HorizontalVelPID", "deg/(m/s)", UAVObjectField.FieldType.FLOAT32, HorizontalVelPIDElemNames, null) );
List<String> VerticalPosPIElemNames = new ArrayList<String>();
VerticalPosPIElemNames.add("Kp");
VerticalPosPIElemNames.add("Ki");
VerticalPosPIElemNames.add("ILimit");
fields.add( new UAVObjectField("VerticalPosPI", "", UAVObjectField.FieldType.FLOAT32, VerticalPosPIElemNames, null) );
List<String> VerticalVelPIDElemNames = new ArrayList<String>();
VerticalVelPIDElemNames.add("Kp");
VerticalVelPIDElemNames.add("Ki");
VerticalVelPIDElemNames.add("Kd");
VerticalVelPIDElemNames.add("ILimit");
fields.add( new UAVObjectField("VerticalVelPID", "", UAVObjectField.FieldType.FLOAT32, VerticalVelPIDElemNames, null) );
List<String> MaxRollPitchElemNames = new ArrayList<String>();
MaxRollPitchElemNames.add("0");
fields.add( new UAVObjectField("MaxRollPitch", "deg", UAVObjectField.FieldType.FLOAT32, MaxRollPitchElemNames, null) );
List<String> UpdatePeriodElemNames = new ArrayList<String>();
UpdatePeriodElemNames.add("0");
fields.add( new UAVObjectField("UpdatePeriod", "", UAVObjectField.FieldType.INT32, UpdatePeriodElemNames, null) );
List<String> HorizontalVelMaxElemNames = new ArrayList<String>();
HorizontalVelMaxElemNames.add("0");
fields.add( new UAVObjectField("HorizontalVelMax", "m/s", UAVObjectField.FieldType.UINT16, HorizontalVelMaxElemNames, null) );
List<String> VerticalVelMaxElemNames = new ArrayList<String>();
VerticalVelMaxElemNames.add("0");
fields.add( new UAVObjectField("VerticalVelMax", "m/s", UAVObjectField.FieldType.UINT16, VerticalVelMaxElemNames, null) );
List<String> GuidanceModeElemNames = new ArrayList<String>();
GuidanceModeElemNames.add("0");
List<String> GuidanceModeEnumOptions = new ArrayList<String>();
GuidanceModeEnumOptions.add("DUAL_LOOP");
GuidanceModeEnumOptions.add("VELOCITY_CONTROL");
fields.add( new UAVObjectField("GuidanceMode", "", UAVObjectField.FieldType.ENUM, GuidanceModeElemNames, GuidanceModeEnumOptions) );
List<String> ThrottleControlElemNames = new ArrayList<String>();
ThrottleControlElemNames.add("0");
List<String> ThrottleControlEnumOptions = new ArrayList<String>();
ThrottleControlEnumOptions.add("FALSE");
ThrottleControlEnumOptions.add("TRUE");
fields.add( new UAVObjectField("ThrottleControl", "", UAVObjectField.FieldType.ENUM, ThrottleControlElemNames, ThrottleControlEnumOptions) );
// Compute the number of bytes for this object
int numBytes = 0;
ListIterator<UAVObjectField> li = fields.listIterator();
while(li.hasNext()) {
numBytes += li.next().getNumBytes();
}
NUMBYTES = numBytes;
// Initialize object
initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES);
// Set the default field values
setDefaultFieldValues();
// Set the object description
setDescription(DESCRIPTION);
}
/**
* Create a Metadata object filled with default values for this object
* @return Metadata object with default values
*/
public Metadata getDefaultMetadata() {
UAVObject.Metadata metadata = new UAVObject.Metadata();
metadata.flags =
UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT |
UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT |
1 << UAVOBJ_TELEMETRY_ACKED_SHIFT |
1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
metadata.flightTelemetryUpdatePeriod = 0;
metadata.gcsTelemetryUpdatePeriod = 0;
metadata.loggingUpdatePeriod = 0;
return metadata;
}
/**
* Initialize object fields with the default values.
* If a default value is not specified the object fields
* will be initialized to zero.
*/
public void setDefaultFieldValues()
{
getField("HorizontalPosPI").setValue(0.1,0);
getField("HorizontalPosPI").setValue(0.001,1);
getField("HorizontalPosPI").setValue(300,2);
getField("HorizontalVelPID").setValue(0.05,0);
getField("HorizontalVelPID").setValue(0.002,1);
getField("HorizontalVelPID").setValue(0,2);
getField("HorizontalVelPID").setValue(1000,3);
getField("VerticalPosPI").setValue(0.1,0);
getField("VerticalPosPI").setValue(0.001,1);
getField("VerticalPosPI").setValue(200,2);
getField("VerticalVelPID").setValue(0.1,0);
getField("VerticalVelPID").setValue(0,1);
getField("VerticalVelPID").setValue(0,2);
getField("VerticalVelPID").setValue(0,3);
getField("MaxRollPitch").setValue(10);
getField("UpdatePeriod").setValue(100);
getField("HorizontalVelMax").setValue(300);
getField("VerticalVelMax").setValue(150);
getField("GuidanceMode").setValue("DUAL_LOOP");
getField("ThrottleControl").setValue("FALSE");
}
/**
* Create a clone of this object, a new instance ID must be specified.
* Do not use this function directly to create new instances, the
* UAVObjectManager should be used instead.
*/
public UAVDataObject clone(long instID) {
// TODO: Need to get specific instance to clone
try {
GuidanceSettings obj = new GuidanceSettings();
obj.initialize(instID, this.getMetaObject());
return obj;
} catch (Exception e) {
return null;
}
}
/**
* Static function to retrieve an instance of the object.
*/
public GuidanceSettings GetInstance(UAVObjectManager objMngr, long instID)
{
return (GuidanceSettings)(objMngr.getObject(GuidanceSettings.OBJID, instID));
}
// Constants
protected static final long OBJID = 0x6EA79FB4l;
protected static final String NAME = "GuidanceSettings";
protected static String DESCRIPTION = "Settings for the @ref GuidanceModule";
protected static final boolean ISSINGLEINST = 1 > 0;
protected static final boolean ISSETTINGS = 1 > 0;
protected static int NUMBYTES = 0;
}

View File

@ -0,0 +1,146 @@
/**
******************************************************************************
*
* @file uavobjecttemplate.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Template for an uavobject in java
* This is a autogenerated file!! Do not modify and expect a result.
* The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner
*
* @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.uavtalk.uavobjects;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVDataObject;
import org.openpilot.uavtalk.UAVObjectField;
/**
The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner
generated from positiondesired.xml
**/
public class PositionDesired extends UAVDataObject {
public PositionDesired() {
super(OBJID, ISSINGLEINST, ISSETTINGS, NAME);
List<UAVObjectField> fields = new ArrayList<UAVObjectField>();
List<String> NorthElemNames = new ArrayList<String>();
NorthElemNames.add("0");
fields.add( new UAVObjectField("North", "m", UAVObjectField.FieldType.FLOAT32, NorthElemNames, null) );
List<String> EastElemNames = new ArrayList<String>();
EastElemNames.add("0");
fields.add( new UAVObjectField("East", "m", UAVObjectField.FieldType.FLOAT32, EastElemNames, null) );
List<String> DownElemNames = new ArrayList<String>();
DownElemNames.add("0");
fields.add( new UAVObjectField("Down", "m", UAVObjectField.FieldType.FLOAT32, DownElemNames, null) );
// Compute the number of bytes for this object
int numBytes = 0;
ListIterator<UAVObjectField> li = fields.listIterator();
while(li.hasNext()) {
numBytes += li.next().getNumBytes();
}
NUMBYTES = numBytes;
// Initialize object
initializeFields(fields, ByteBuffer.allocate(NUMBYTES), NUMBYTES);
// Set the default field values
setDefaultFieldValues();
// Set the object description
setDescription(DESCRIPTION);
}
/**
* Create a Metadata object filled with default values for this object
* @return Metadata object with default values
*/
public Metadata getDefaultMetadata() {
UAVObject.Metadata metadata = new UAVObject.Metadata();
metadata.flags =
UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_ACCESS_SHIFT |
UAVObject.Metadata.AccessModeNum(UAVObject.AccessMode.ACCESS_READWRITE) << UAVOBJ_GCS_ACCESS_SHIFT |
0 << UAVOBJ_TELEMETRY_ACKED_SHIFT |
0 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT |
UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) << UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT |
UAVObject.Metadata.UpdateModeNum(UAVObject.UpdateMode.UPDATEMODE_MANUAL) << UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT;
metadata.flightTelemetryUpdatePeriod = 0;
metadata.gcsTelemetryUpdatePeriod = 0;
metadata.loggingUpdatePeriod = 1000;
return metadata;
}
/**
* Initialize object fields with the default values.
* If a default value is not specified the object fields
* will be initialized to zero.
*/
public void setDefaultFieldValues()
{
}
/**
* Create a clone of this object, a new instance ID must be specified.
* Do not use this function directly to create new instances, the
* UAVObjectManager should be used instead.
*/
public UAVDataObject clone(long instID) {
// TODO: Need to get specific instance to clone
try {
PositionDesired obj = new PositionDesired();
obj.initialize(instID, this.getMetaObject());
return obj;
} catch (Exception e) {
return null;
}
}
/**
* Static function to retrieve an instance of the object.
*/
public PositionDesired GetInstance(UAVObjectManager objMngr, long instID)
{
return (PositionDesired)(objMngr.getObject(PositionDesired.OBJID, instID));
}
// Constants
protected static final long OBJID = 0x778DBE24l;
protected static final String NAME = "PositionDesired";
protected static String DESCRIPTION = "The position the craft is trying t achieve. Can come from GCS or @ref PathPlanner ";
protected static final boolean ISSINGLEINST = 1 > 0;
protected static final boolean ISSETTINGS = 0 > 0;
protected static int NUMBYTES = 0;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -94,8 +94,8 @@
/* Task stack sizes */
#define PIOS_ACTUATOR_STACK_SIZE 1020
#define PIOS_MANUAL_STACK_SIZE 724
#define PIOS_SYSTEM_STACK_SIZE 460
#define PIOS_MANUAL_STACK_SIZE 800
#define PIOS_SYSTEM_STACK_SIZE 660
#define PIOS_STABILIZATION_STACK_SIZE 524
#define PIOS_TELEM_STACK_SIZE 500
#define PIOS_EVENTDISPATCHER_STACK_SIZE 130

View File

@ -242,7 +242,7 @@ int WMM_GetMagVector(float Lat, float Lon, float AltEllipsoid, uint16_t Month, u
{
CoordGeodetic->lambda = Lon;
CoordGeodetic->phi = Lat;
CoordGeodetic->HeightAboveEllipsoid = AltEllipsoid;
CoordGeodetic->HeightAboveEllipsoid = AltEllipsoid/1000.0; // convert to km
// Convert from geodeitic to Spherical Equations: 17-18, WMM Technical report
if (WMM_GeodeticToSpherical(CoordGeodetic, CoordSpherical) < 0)

View File

@ -375,6 +375,10 @@ static int32_t updateSensorsCC3D(AccelsData * accelsData, GyrosData * gyrosData)
if(xQueueReceive(queue, (void *) &mpu6000_data, SENSOR_PERIOD) == errQUEUE_EMPTY)
return -1; // Error, no data
// Do not read raw sensor data in simulation mode
if (GyrosReadOnly() || AccelsReadOnly())
return 0;
gyros[0] = -mpu6000_data.gyro_y * PIOS_MPU6000_GetScale();
gyros[1] = -mpu6000_data.gyro_x * PIOS_MPU6000_GetScale();
gyros[2] = -mpu6000_data.gyro_z * PIOS_MPU6000_GetScale();

View File

@ -73,6 +73,7 @@
static uint32_t idleCounter;
static uint32_t idleCounterClear;
static xTaskHandle systemTaskHandle;
static xQueueHandle objectPersistenceQueue;
static bool stackOverflow;
static bool mallocFailed;
@ -122,6 +123,10 @@ int32_t SystemModInitialize(void)
WatchdogStatusInitialize();
#endif
objectPersistenceQueue = xQueueCreate(1, sizeof(UAVObjEvent));
if (objectPersistenceQueue == NULL)
return -1;
SystemModStart();
return 0;
@ -133,8 +138,6 @@ MODULE_INITCALL(SystemModInitialize, 0)
*/
static void systemTask(void *parameters)
{
portTickType lastSysTime;
/* create all modules thread */
MODULE_TASKCREATE_ALL;
@ -154,10 +157,9 @@ static void systemTask(void *parameters)
// Initialize vars
idleCounter = 0;
idleCounterClear = 0;
lastSysTime = xTaskGetTickCount();
// Listen for SettingPersistance object updates, connect a callback function
ObjectPersistenceConnectCallback(&objectUpdatedCb);
ObjectPersistenceConnectQueue(objectPersistenceQueue);
// Main system loop
while (1) {
@ -193,11 +195,14 @@ static void systemTask(void *parameters)
FlightStatusData flightStatus;
FlightStatusGet(&flightStatus);
// Wait until next period
if(flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMED) {
vTaskDelayUntil(&lastSysTime, SYSTEM_UPDATE_PERIOD_MS / portTICK_RATE_MS / (LED_BLINK_RATE_HZ * 2) );
} else {
vTaskDelayUntil(&lastSysTime, SYSTEM_UPDATE_PERIOD_MS / portTICK_RATE_MS);
UAVObjEvent ev;
int delayTime = flightStatus.Armed == FLIGHTSTATUS_ARMED_ARMED ?
SYSTEM_UPDATE_PERIOD_MS / portTICK_RATE_MS / (LED_BLINK_RATE_HZ * 2) :
SYSTEM_UPDATE_PERIOD_MS / portTICK_RATE_MS;
if(xQueueReceive(objectPersistenceQueue, &ev, delayTime) == pdTRUE) {
// If object persistence is updated call the callback
objectUpdatedCb(&ev);
}
}
}

View File

@ -9,9 +9,7 @@ equals(copydata, 1) {
win32:CONFIG(release, debug|release) {
# copy Qt DLLs and phonon4
QT_DLLS = libgcc_s_dw2-1.dll \
mingwm10.dll \
phonon4.dll \
QT_DLLS = phonon4.dll \
QtCore4.dll \
QtGui4.dll \
QtNetwork4.dll \
@ -27,6 +25,13 @@ equals(copydata, 1) {
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$[QT_INSTALL_BINS]/$$dll\") $$targetPath(\"$$GCS_APP_PATH/$$dll\") $$addNewline()
}
# copy MinGW DLLs
MINGW_DLLS = libgcc_s_dw2-1.dll \
mingwm10.dll
for(dll, MINGW_DLLS) {
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$[QT_INSTALL_BINS]/../../../../../mingw/bin/$$dll\") $$targetPath(\"$$GCS_APP_PATH/$$dll\") $$addNewline()
}
# copy iconengines
QT_ICONENGINE_DLLS = qsvgicon4.dll
data_copy.commands += -@$(MKDIR) $$targetPath(\"$$GCS_APP_PATH/iconengines\") $$addNewline()

View File

@ -158,7 +158,7 @@ namespace Utils {
{
double Lat = LLA[0];
double Lon = LLA[1];
double AltEllipsoid = LLA[2];
double AltEllipsoid = LLA[2]/1000.0; // convert to km
// ***********
// range check supplied params

View File

@ -180,7 +180,6 @@ void VehicleConfig::setMixerType(UAVDataObject* mixer, int channel, MixerTypeEle
if (mixerType >= 0 && mixerType < mixerTypeDescriptions.count())
{
field->setValue(mixerTypeDescriptions[mixerType]);
mixer->updated();
}
}
}
@ -228,7 +227,6 @@ void VehicleConfig::setMixerVectorValue(UAVDataObject* mixer, int channel, Mixer
if (field) {
field->setDouble(value, elementName);
mixer->updated();
}
}
}

View File

@ -135,6 +135,14 @@ void ConfigStabilizationWidget::processLinkedWidgets(QWidget * widget)
{
m_stabilization->RateRollILimit_2->setValue(m_stabilization->RatePitchILimit->value());
}
else if(widget== m_stabilization->RollRateKd)
{
m_stabilization->PitchRateKd->setValue(m_stabilization->RollRateKd->value());
}
else if(widget== m_stabilization->PitchRateKd)
{
m_stabilization->RollRateKd->setValue(m_stabilization->PitchRateKd->value());
}
}
if(m_stabilization->checkBox_8->checkState()==Qt::Checked)
{

View File

@ -1,3 +1,30 @@
/**
******************************************************************************
*
* @file aerosimrc.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* 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
*/
#include "aerosimrc.h"
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/icore.h>

View File

@ -1,3 +1,30 @@
/**
******************************************************************************
*
* @file aerosimrc.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* 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
*/
#ifndef AEROSIMRC_H
#define AEROSIMRC_H

View File

@ -0,0 +1,10 @@
TEMPLATE = subdirs
win32 {
SUBDIRS += plugin
}
SUBDIRS += udptest
plugin.file = src/plugin.pro
udptest.file = src/udptest.pro

View File

@ -0,0 +1,206 @@
/**
******************************************************************************
*
* @file aerosimrcdatastruct.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#ifndef AEROSIMRCDATASTRUCT_H
#define AEROSIMRCDATASTRUCT_H
#include <QtCore>
const quint8 AEROSIMRC_MAX_CHANNELS = 39;
const quint16 DBG_BUFFER_MAX_SIZE = 4096;
#define MAX_DLL_USER_MENU_ITEMS 16
#define OBSOLETE_MIT_COMMAND (1 << 0)
#define OBSOLETE_MIT_CHECKBOX (1 << 1)
#define OBSOLETE_MIT_SEPARATOR (1 << 7)
#define PACK_STRUCT __attribute__((packed))
struct simToPlugin
{
quint16 structSize;
float simTimeStep;
float chSimTX[AEROSIMRC_MAX_CHANNELS];
float chSimRX[AEROSIMRC_MAX_CHANNELS];
uchar *OSDVideoBuf;
quint32 simMenuStatus;
float initPosX;
float initPosY;
float initPosZ;
float initHeading;
float initPitch;
float initRoll;
float wpHomeX;
float wpHomeY;
float wpHomeLat;
float wpHomeLong;
const char *wpHomeDesc; // (m, deg, string)
float wpAX;
float wpAY;
float wpALat;
float wpALong;
const char *wpADesc; // (m, deg, string)
float wpBX;
float wpBY;
float wpBLat;
float wpBLong;
const char *wpBDesc; // (m, deg, string)
float wpCX;
float wpCY;
float wpCLat;
float wpCLong;
const char *wpCDesc; // (m, deg, string)
float wpDX;
float wpDY;
float wpDLat;
float wpDLong;
const char *wpDDesc; // (m, deg, string)
float posX;
float posY;
float posZ;
float velX;
float velY;
float velZ;
float angVelX;
float angVelY;
float angVelZ;
float accelX;
float accelY;
float accelZ;
qreal latitude;
qreal longitude;
float AGL;
float heading;
float pitch;
float roll;
float windVelX;
float windVelY;
float windVelZ;
float eng1RPM;
float eng2RPM;
float eng3RPM;
float eng4RPM;
float voltage; // V
float current; // A
float consumedCharge; // Ah
float capacity; // Ah
float fuelConsumed; // l
float fuelTankCapacity; // l
// ver 3.83
qint16 screenW;
qint16 screenH;
// Model Orientation Matrix (X=Right, Y=Front, Z=Up)
float axisXx;
float axisXy;
float axisXz;
float axisYx;
float axisYy;
float axisYz;
float axisZx;
float axisZy;
float axisZz;
// Model data in body frame coordinates (X=Right, Y=Front, Z=Up)
float velXm; // m/s Model velocity in body coordinates
float velYm;
float velZm;
float angVelXm; // rad/s Model angular velocity in body coordinates
float angVelYm;
float angVelZm;
float accelXm; // m/s/s Model acceleration in body coordinates
float accelYm;
float accelZm;
// ver 3.90
quint32 OSDVideoBufSize;
} PACK_STRUCT ; // normal - 592, packed - 582 OK (3.81)
// normal - ???, packed - 658 OK (3.83)
// normal - ???, packed - 662 OK (3.90)
struct pluginToSim
{
quint16 structSize;
const char *dbgInfoText;
uchar chOverTX[AEROSIMRC_MAX_CHANNELS];
float chNewTX[AEROSIMRC_MAX_CHANNELS];
uchar chOverRX[AEROSIMRC_MAX_CHANNELS];
float chNewRX[AEROSIMRC_MAX_CHANNELS];
float newPosX; // m
float newPosY;
float newPosZ;
float newVelX; // m/s
float newVelY;
float newVelZ;
float newAngVelX; // rad/s
float newAngVelY;
float newAngVelZ;
float newHeading; // rad
float newPitch;
float newRoll;
quint32 modelOverrideFlags;
quint32 newMenuStatus;
quint8 isOSDShow;
quint8 isOSDChanged;
quint16 OSDWindow_DX;
quint16 OSDWindow_DY;
float OSDScale;
float newWindVelX;
float newWindVelY;
float newWindVelZ;
float newEng1RPM;
float newEng2RPM;
float newEng3RPM;
float newEng4RPM;
float newVoltage;
float newCurrent;
float newConsumedCharge;
float newFuelConsumed;
quint8 modelCrashInhibit;
// ver 3.83
qint16 newScreenW; // Simulator window position and size on screen
qint16 newScreenH;
qint16 newScreenX;
qint16 newScreenY;
} PACK_STRUCT ; // normal 516, packed 507 OK (3.81)
// normal ???, packed 515 OK (3.83 & 3.90)
struct TPluginMenuItem
{
quint32 OBSOLETE_eType;
char *OBSOLETE_strName;
} PACK_STRUCT ;
struct pluginInit
{
quint32 nStructSize;
char *OBSOLETE_strMenuTitle;
TPluginMenuItem OBSOLETE_atMenuItem[MAX_DLL_USER_MENU_ITEMS];
const char *strPluginFolder;
const char *strOutputFolder;
} PACK_STRUCT ; // normal - 144, packed - 144 OK (3.81 & 3.83 & 3.90)
#undef PACK_STRUCT
#endif // AEROSIMRCDATASTRUCT_H

View File

@ -0,0 +1,102 @@
/**
******************************************************************************
*
* @file enums.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#ifndef ENUMS_H
#define ENUMS_H
// Custom Menu Item masks
enum MenuMasks {
MenuEnable = (1 << 0),
MenuTx = (1 << 1),
MenuRx = (1 << 2),
MenuScreen = (1 << 3),
MenuNextWpt = (1 << 4),
MenuCmdReset = (1 << 5),
MenuLedBlue = (1 << 6),
MenuLedGreen = (1 << 7),
MenuFMode1 = (1 << 8),
MenuFMode2 = (1 << 9),
MenuFMode3 = (1 << 10)
};
enum EOverrideFlags
{
OVR_POS = (1 << 0),
OVR_VEL = (1 << 1),
OVR_ANG_VEL = (1 << 2),
OVR_HPR = (1 << 3), // Override Heading, Pitch and Roll
OVR_WIND_VEL = (1 << 4), // Override Wind velocity at model
OVR_ENGINE_RPM = (1 << 5), // Override RPM of all Engines or Motors
OVR_BAT_VOLT = (1 << 6), // Override motor Battery Voltage
OVR_BAT_AMP = (1 << 7), // Override motor Battery current
OVR_BAT_AH_CONSUMED = (1 << 8), // Override motor Battery AmpsHour consumed
OVR_FUEL_CONSUMED = (1 << 9) // Override Fuel consumed (gas & jet engines)
};
enum Channels {
Ch1Aileron,
Ch2Elevator,
Ch3Throttle,
Ch4Rudder,
Ch5,
Ch6,
Ch7,
Ch8,
Ch9,
Ch10Retracts,
Ch11Flaps,
Ch12FPVCamPan,
Ch13FPVCamTilt,
Ch14Brakes,
Ch15Spoilers,
Ch16Smoke,
Ch17Fire,
Ch18FlightMode,
Ch19ALTHold,
Ch20FPVTiltHold,
Ch21ResetModel,
Ch22MouseTX,
Ch23Plugin1,
Ch24Plugin2,
Ch25ThrottleHold,
Ch26CareFree,
Ch27FPVCamRoll,
Ch28LMotorDual,
Ch29RMotorDual,
Ch30Mix,
Ch31Mix,
Ch32Mix,
Ch33Mix,
Ch34Mix,
Ch35Mix,
Ch36Mix,
Ch37Mix,
Ch38Mix,
Ch39Mix
};
#endif // ENUMS_H

View File

@ -0,0 +1,394 @@
/**
******************************************************************************
*
* @file plugin.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#include "plugin.h"
#include "udpconnect.h"
#include "qdebughandler.h"
#include "enums.h"
#include "settings.h"
bool isFirstRun = true;
QString debugInfo(DBG_BUFFER_MAX_SIZE, ' ');
QString pluginFolder(MAX_PATH, ' ');
QString outputFolder(MAX_PATH, ' ');
QList<quint16> videoModes;
QTime ledTimer;
UdpSender *sndr;
UdpReceiver *rcvr;
const float RAD2DEG = (float)(180.0 / M_PI);
const float DEG2RAD = (float)(M_PI / 180.0);
//extern "C" int __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
extern "C" int __stdcall DllMain(void*, quint32 fdwReason, void*)
{
switch (fdwReason) {
case 0:
// qDebug() << hinstDLL << "DLL_PROCESS_DETACH " << lpvReserved;
// free resources here
rcvr->stop();
rcvr->wait(500);
delete rcvr;
delete sndr;
qDebug("------");
break;
case 1:
// qDebug() << hinstDLL << " DLL_PROCESS_ATTACH " << lpvReserved;
break;
case 2:
// qDebug() << hinstDLL << "DLL_THREAD_ATTACH " << lpvReserved;
break;
case 3:
// qDebug() << hinstDLL << "DLL_THREAD_DETACH " << lpvReserved;
break;
}
return true;
}
SIM_DLL_EXPORT void AeroSIMRC_Plugin_ReportStructSizes(quint32 *sizeSimToPlugin,
quint32 *sizePluginToSim,
quint32 *sizePluginInit)
{
// debug redirection
qInstallMsgHandler(myQDebugHandler);
qDebug() << "AeroSIMRC_Plugin_ReportStructSizes";
*sizeSimToPlugin = sizeof(simToPlugin);
*sizePluginToSim = sizeof(pluginToSim);
*sizePluginInit = sizeof(pluginInit);
qDebug() << "sizeSimToPlugin = " << *sizeSimToPlugin;
qDebug() << "sizePluginToSim = " << *sizePluginToSim;
qDebug() << "sizePluginInit = " << *sizePluginInit;
}
SIM_DLL_EXPORT void AeroSIMRC_Plugin_Init(pluginInit *p)
{
qDebug() << "AeroSIMRC_Plugin_Init begin";
pluginFolder = p->strPluginFolder;
outputFolder = p->strOutputFolder;
ledTimer.restart();
Settings *ini = new Settings(pluginFolder);
ini->read();
videoModes = ini->getVideoModes();
sndr = new UdpSender(ini->getOutputMap(), ini->isFromTX());
sndr->init(ini->remoteHost(), ini->remotePort());
rcvr = new UdpReceiver(ini->getInputMap(), ini->isToRX());
rcvr->init(ini->localHost(), ini->localPort());
// run thread
rcvr->start();
delete ini;
qDebug() << "AeroSIMRC_Plugin_Init done";
}
//-----------------------------------------------------------------------------
void Run_Command_Reset(/*const simToPlugin *stp,
pluginToSim *pts*/)
{
// Print some debug info, although it will only be seen during one frame
debugInfo.append("\nRESET");
}
void Run_Command_WindowSizeAndPos(const simToPlugin *stp,
pluginToSim *pts)
{
static quint8 snSequence = 0;
quint8 idx = snSequence * 4;
if (snSequence >= videoModes.at(0)) { // set fullscreen
pts->newScreenX = 0;
pts->newScreenY = 0;
pts->newScreenW = stp->screenW;
pts->newScreenH = stp->screenH;
snSequence = 0;
} else { // set video mode from config
pts->newScreenX = videoModes.at(idx + 1);
pts->newScreenY = videoModes.at(idx + 2);
pts->newScreenW = videoModes.at(idx + 3);
pts->newScreenH = videoModes.at(idx + 4);
snSequence++;
}
}
void Run_Command_MoveToNextWaypoint(const simToPlugin *stp,
pluginToSim *pts)
{
static quint8 snSequence = 0;
switch(snSequence) {
case 0:
pts->newPosX = stp->wpAX;
pts->newPosY = stp->wpAY;
pts->newPosZ = 100.0;
break;
case 1:
pts->newPosX = stp->wpBX;
pts->newPosY = stp->wpBY;
pts->newPosZ = 100.0;
break;
case 2:
pts->newPosX = stp->wpCX;
pts->newPosY = stp->wpCY;
pts->newPosZ = 100.0;
break;
case 3:
pts->newPosX = stp->wpDX;
pts->newPosY = stp->wpDY;
pts->newPosZ = 100.0;
break;
case 4:
pts->newPosX = stp->wpHomeX;
pts->newPosY = stp->wpHomeY;
pts->newPosZ = 100.0;
break;
default:
qFatal("Run_Command_MoveToNextWaypoint switch error");
}
pts->modelOverrideFlags = 0;
pts->modelOverrideFlags |= OVR_POS;
snSequence++;
if(snSequence > 4)
snSequence = 0;
}
void Run_BlinkLEDs(const simToPlugin *stp,
pluginToSim *pts)
{
if ((stp->simMenuStatus & MenuEnable) != 0) {
pts->newMenuStatus |= MenuLedGreen;
int timeout;
quint8 armed;
quint8 mode;
rcvr->getFlighStatus(armed, mode);
debugInfo.append(QString("armed: %1, mode: %2\n").arg(armed).arg(mode));
if (armed == 0) // disarm
timeout = 1000;
else if (armed == 1) // arming
timeout = 40;
else if (armed == 2) // armed
timeout = 100;
else // unknown
timeout = 2000;
if (ledTimer.elapsed() > timeout) {
ledTimer.restart();
pts->newMenuStatus ^= MenuLedBlue;
}
if (mode == 6) {
pts->newMenuStatus |= MenuFMode3;
pts->newMenuStatus |= MenuFMode2;
pts->newMenuStatus |= MenuFMode1;
} else if (mode == 5) {
pts->newMenuStatus |= MenuFMode3;
pts->newMenuStatus |= MenuFMode2;
pts->newMenuStatus &= ~MenuFMode1;
} else if (mode == 4) {
pts->newMenuStatus |= MenuFMode3;
pts->newMenuStatus &= ~MenuFMode2;
pts->newMenuStatus |= MenuFMode1;
} else if (mode == 3) {
pts->newMenuStatus |= MenuFMode3;
pts->newMenuStatus &= ~MenuFMode2;
pts->newMenuStatus &= ~MenuFMode1;
} else if (mode == 2) {
pts->newMenuStatus &= ~MenuFMode3;
pts->newMenuStatus |= MenuFMode2;
pts->newMenuStatus &= ~MenuFMode1;
} else if (mode == 1) {
pts->newMenuStatus &= ~MenuFMode3;
pts->newMenuStatus &= ~MenuFMode2;
pts->newMenuStatus |= MenuFMode1;
} else /*(mode == 0)*/ {
pts->newMenuStatus &= ~MenuFMode3;
pts->newMenuStatus &= ~MenuFMode2;
pts->newMenuStatus &= ~MenuFMode1;
}
} else {
pts->newMenuStatus = 0;
}
}
void InfoText(const simToPlugin *stp,
pluginToSim *pts)
{
debugInfo.append(
QString(
"Plugin Folder = %1\n"
"Output Folder = %2\n"
"nStructSize = %3 "
"fIntegrationTimeStep = %4\n"
"\n"
"Aileron TX = %5 RX = %6 RCMD TX = %7 RX = %8\n"
"Elevator TX = %9 RX = %10 RCMD TX = %11 RX = %12\n"
"Throttle TX = %13 RX = %14 RCMD TX = %15 RX = %16\n"
"Rudder TX = %17 RX = %18 RCMD TX = %19 RX = %20\n"
"Channel5 TX = %21 RX = %22 RCMD TX = %23 RX = %24\n"
"Channel6 TX = %25 RX = %26 RCMD TX = %27 RX = %28\n"
"Channel7 TX = %29 RX = %30 RCMD TX = %31 RX = %32\n"
"PluginCh1 TX = %33 RX = %34 RCMD TX = %35 RX = %36\n"
"PluginCh2 TX = %37 RX = %38 RCMD TX = %39 RX = %40\n"
"FPVCamPan TX = %41 RX = %42 RCMD TX = %43 RX = %44\n"
"FPVCamTil TX = %45 RX = %46 RCMD TX = %47 RX = %48\n"
"\n"
"MenuItems = %49\n"
// Model data
"\n"
"fPosX,Y,Z = (%50, %51, %52)\n"
"fVelX,Y,Z = (%53, %54, %55)\n"
"fAngVelX,Y,Z = (%56, %57, %58)\n"
"fAccelX,Y,Z = (%59, %60, %61)\n"
"\n"
"Lat, Long = %62, %63\n"
"fHeightAboveTerrain = %64\n"
"\n"
"fHeading = %65 fPitch = %66 fRoll = %67\n"
)
.arg(pluginFolder)
.arg(outputFolder)
.arg(stp->structSize)
.arg(1.0 / stp->simTimeStep, 4, 'f', 1)
.arg(stp->chSimTX[Ch1Aileron], 5, 'f', 2)
.arg(stp->chSimRX[Ch1Aileron], 5, 'f', 2)
.arg(pts->chNewTX[Ch1Aileron], 5, 'f', 2)
.arg(pts->chNewRX[Ch1Aileron], 5, 'f', 2)
.arg(stp->chSimTX[Ch2Elevator], 5, 'f', 2)
.arg(stp->chSimRX[Ch2Elevator], 5, 'f', 2)
.arg(pts->chNewTX[Ch2Elevator], 5, 'f', 2)
.arg(pts->chNewRX[Ch2Elevator], 5, 'f', 2)
.arg(stp->chSimTX[Ch3Throttle], 5, 'f', 2)
.arg(stp->chSimRX[Ch3Throttle], 5, 'f', 2)
.arg(pts->chNewTX[Ch3Throttle], 5, 'f', 2)
.arg(pts->chNewRX[Ch3Throttle], 5, 'f', 2)
.arg(stp->chSimTX[Ch4Rudder], 5, 'f', 2)
.arg(stp->chSimRX[Ch4Rudder], 5, 'f', 2)
.arg(pts->chNewTX[Ch4Rudder], 5, 'f', 2)
.arg(pts->chNewRX[Ch4Rudder], 5, 'f', 2)
.arg(stp->chSimTX[Ch5], 5, 'f', 2)
.arg(stp->chSimRX[Ch5], 5, 'f', 2)
.arg(pts->chNewTX[Ch5], 5, 'f', 2)
.arg(pts->chNewRX[Ch5], 5, 'f', 2)
.arg(stp->chSimTX[Ch6], 5, 'f', 2)
.arg(stp->chSimRX[Ch6], 5, 'f', 2)
.arg(pts->chNewTX[Ch6], 5, 'f', 2)
.arg(pts->chNewRX[Ch6], 5, 'f', 2)
.arg(stp->chSimTX[Ch7], 5, 'f', 2)
.arg(stp->chSimRX[Ch7], 5, 'f', 2)
.arg(pts->chNewTX[Ch7], 5, 'f', 2)
.arg(pts->chNewRX[Ch7], 5, 'f', 2)
.arg(stp->chSimTX[Ch23Plugin1], 5, 'f', 2)
.arg(stp->chSimRX[Ch23Plugin1], 5, 'f', 2)
.arg(pts->chNewTX[Ch23Plugin1], 5, 'f', 2)
.arg(pts->chNewRX[Ch23Plugin1], 5, 'f', 2)
.arg(stp->chSimTX[Ch24Plugin2], 5, 'f', 2)
.arg(stp->chSimRX[Ch24Plugin2], 5, 'f', 2)
.arg(pts->chNewTX[Ch24Plugin2], 5, 'f', 2)
.arg(pts->chNewRX[Ch24Plugin2], 5, 'f', 2)
.arg(stp->chSimTX[Ch12FPVCamPan], 5, 'f', 2)
.arg(stp->chSimRX[Ch12FPVCamPan], 5, 'f', 2)
.arg(pts->chNewTX[Ch12FPVCamPan], 5, 'f', 2)
.arg(pts->chNewRX[Ch12FPVCamPan], 5, 'f', 2)
.arg(stp->chSimTX[Ch13FPVCamTilt], 5, 'f', 2)
.arg(stp->chSimRX[Ch13FPVCamTilt], 5, 'f', 2)
.arg(pts->chNewTX[Ch13FPVCamTilt], 5, 'f', 2)
.arg(pts->chNewRX[Ch13FPVCamTilt], 5, 'f', 2)
.arg(stp->simMenuStatus)
.arg(stp->posX, 5, 'f', 2)
.arg(stp->posY, 5, 'f', 2)
.arg(stp->posZ, 5, 'f', 2)
.arg(stp->velX, 5, 'f', 2)
.arg(stp->velY, 5, 'f', 2)
.arg(stp->velZ, 5, 'f', 2)
.arg(stp->angVelXm, 5, 'f', 2)
.arg(stp->angVelYm, 5, 'f', 2)
.arg(stp->angVelZm, 5, 'f', 2)
.arg(stp->accelXm, 5, 'f', 2)
.arg(stp->accelYm, 5, 'f', 2)
.arg(stp->accelZm, 5, 'f', 2)
.arg(stp->latitude, 5, 'f', 2)
.arg(stp->longitude, 5, 'f', 2)
.arg(stp->AGL, 5, 'f', 2)
.arg(stp->heading*RAD2DEG, 5, 'f', 2)
.arg(stp->pitch*RAD2DEG, 5, 'f', 2)
.arg(stp->roll*RAD2DEG, 5, 'f', 2)
);
}
SIM_DLL_EXPORT void AeroSIMRC_Plugin_Run(const simToPlugin *stp,
pluginToSim *pts)
{
debugInfo = "---\n";
// By default do not change the Menu Items of type CheckBox
pts->newMenuStatus = stp->simMenuStatus;
// Extract Menu Commands from Flags
bool isReset = (stp->simMenuStatus & MenuCmdReset) != 0;
bool isEnable = (stp->simMenuStatus & MenuEnable) != 0;
bool isTxON = (stp->simMenuStatus & MenuTx) != 0;
bool isRxON = (stp->simMenuStatus & MenuRx) != 0;
bool isScreen = (stp->simMenuStatus & MenuScreen) != 0;
bool isNextWp = (stp->simMenuStatus & MenuNextWpt) != 0;
// Run commands
if (isReset) {
Run_Command_Reset(/*stp, pts*/);
} else if (isScreen) {
Run_Command_WindowSizeAndPos(stp, pts);
} else if (isNextWp) {
Run_Command_MoveToNextWaypoint(stp, pts);
} else {
Run_BlinkLEDs(stp, pts);
if (isEnable) {
if (isTxON)
sndr->sendDatagram(stp);
if (isRxON)
rcvr->setChannels(pts);
}
// network lag
debugInfo.append(QString("out: %1, inp: %2, delta: %3\n")
.arg(sndr->pcks() - 1)
.arg(rcvr->pcks())
.arg(sndr->pcks() - rcvr->pcks() - 1)
);
}
// debug info is shown on the screen
InfoText(stp, pts);
pts->dbgInfoText = debugInfo.toAscii();
isFirstRun = false;
}

View File

@ -0,0 +1,53 @@
/**
******************************************************************************
*
* @file plugin.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#ifndef PLUGIN_H
#define PLUGIN_H
#include <QtCore>
#include <QTime>
#include <QList>
#include "aerosimrcdatastruct.h"
#define SIM_DLL_EXPORT extern "C" __declspec(dllexport)
SIM_DLL_EXPORT void AeroSIMRC_Plugin_ReportStructSizes(
quint32 *sizeSimToPlugin,
quint32 *sizePluginToSim,
quint32 *sizePluginInit
);
SIM_DLL_EXPORT void AeroSIMRC_Plugin_Init(
pluginInit *p
);
SIM_DLL_EXPORT void AeroSIMRC_Plugin_Run(
const simToPlugin *stp,
pluginToSim *pts
);
#endif // PLUGIN_H

View File

@ -0,0 +1,71 @@
!win32 {
error("AeroSimRC plugin is only available for win32 platform")
}
include(../../../../../openpilotgcs.pri)
QT += network
QT -= gui
TEMPLATE = lib
TARGET = plugin_AeroSIMRC
RES_DIR = $${PWD}/resources
SIM_DIR = $$GCS_BUILD_TREE/../AeroSIM-RC
PLUGIN_DIR = $$SIM_DIR/Plugin/CopterControl
DLLDESTDIR = $$PLUGIN_DIR
HEADERS = \
aerosimrcdatastruct.h \
enums.h \
plugin.h \
qdebughandler.h \
udpconnect.h \
settings.h
SOURCES = \
qdebughandler.cpp \
plugin.cpp \
udpconnect.cpp \
settings.cpp
# Resemble the AeroSimRC directory structure and copy plugin files and resources
equals(copydata, 1) {
# Windows release only
win32:CONFIG(release, debug|release) {
data_copy.commands += -@$(MKDIR) $$targetPath(\"$$PLUGIN_DIR\") $$addNewline()
# resources and sample configuration
PLUGIN_RESOURCES = \
cc_off.tga \
cc_off_hover.tga \
cc_on.tga \
cc_on_hover.tga \
cc_plugin.ini \
plugin.txt
for(res, PLUGIN_RESOURCES) {
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$RES_DIR/$$res\") $$targetPath(\"$$PLUGIN_DIR/$$res\") $$addNewline()
}
# Qt DLLs
QT_DLLS = \
QtCore4.dll \
QtNetwork4.dll
for(dll, QT_DLLS) {
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$[QT_INSTALL_BINS]/$$dll\") $$targetPath(\"$$SIM_DIR/$$dll\") $$addNewline()
}
# MinGW DLLs
MINGW_DLLS = \
libgcc_s_dw2-1.dll \
mingwm10.dll
for(dll, MINGW_DLLS) {
data_copy.commands += $(COPY_FILE) $$targetPath(\"$$[QT_INSTALL_BINS]/../../../../../mingw/bin/$$dll\") $$targetPath(\"$$SIM_DIR/$$dll\") $$addNewline()
}
data_copy.target = FORCE
QMAKE_EXTRA_TARGETS += data_copy
}
}

View File

@ -0,0 +1,64 @@
/**
******************************************************************************
*
* @file qdebughandler.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#include "qdebughandler.h"
void myQDebugHandler(QtMsgType type, const char *msg)
{
static bool firstRun = true;
QString txt;
switch (type) {
case QtDebugMsg:
txt = QString("Debug: %1").arg(msg);
break;
case QtWarningMsg:
txt = QString("Warning: %1").arg(msg);
break;
case QtCriticalMsg:
txt = QString("Critical: %1").arg(msg);
break;
case QtFatalMsg:
txt = QString("Fatal: %1").arg(msg);
break;
}
QFile outFile("dbglog.txt");
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
QTime time;
if (firstRun) {
ts << endl << endl;
firstRun = false;
}
ts << time.currentTime().toString("hh:mm:ss.zzz") << " " << txt << endl;
if (type == QtFatalMsg)
abort();
}

View File

@ -0,0 +1,37 @@
/**
******************************************************************************
*
* @file qdebughandler.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#ifndef QDEBUGHANDLER_H
#define QDEBUGHANDLER_H
#include <QDebug>
#include <QFile>
#include <QTime>
void myQDebugHandler(QtMsgType type, const char *msg);
#endif // QDEBUGHANDLER_H

View File

@ -0,0 +1,55 @@
[General]
; Network settings
listen_on_host = 127.0.0.1
listen_on_port = 40200
send_to_host = 127.0.0.1
send_to_port = 40100
; Channels enumerator, applicable for the AeroSIM RC version 3.90+
all_channels = Ch1-Aileron Ch2-Elevator Ch3-Throttle Ch4-Rudder Ch5 Ch6 Ch7 Ch8 Ch9 Ch10-Retracts Ch11-Flaps Ch12-FPV-Pan Ch13-FPV-Tilt Ch14-Brakes Ch15-Spoilers Ch16-Smoke Ch17-Fire Ch18-Flight-Mode Ch19-ALT-Hold Ch20-FPV-Tilt-Hold Ch21-Reset-Model Ch22-MouseTX Ch23-Plugin-1 Ch24-Plugin-2 Ch25-Throttle-Hold Ch26-CareFree Ch27-FPV-Roll Ch28-L-Motor-Dual Ch29-R-Motor-Dual Ch30-Mix Ch31-Mix Ch32-Mix Ch33-Mix Ch34-Mix Ch35-Mix Ch36-Mix Ch37-Mix Ch38-Mix Ch39-Mix
[Input]
; Map CopterControl channels to simulator channels
; To use internal simulator channels just comment the mapping here
cc_channel_1 = Ch1-Aileron
cc_channel_2 = Ch2-Elevator
cc_channel_3 = Ch3-Throttle
cc_channel_4 = Ch4-Rudder
;cc_channel_5 = Ch27-FPV-Roll
cc_channel_6 = Ch13-FPV-Tilt
;cc_channel_7 = Ch12-FPV-Pan
;cc_channel_8 =
;cc_channel_9 =
;cc_channel_10=
; Control TX or RX (before or after mixes)
send_to = RX
[Output]
; Map simulator channels to GCS HiTL/CopterControl channels
; Only mapped channels will be sent to the GCS
sim_channel_1 = Ch1-Aileron
sim_channel_2 = Ch2-Elevator
sim_channel_3 = Ch3-Throttle
sim_channel_4 = Ch4-Rudder
sim_channel_5 = Ch23-Plugin-1
;sim_channel_6 = Ch27-FPV-Roll
sim_channel_7 = Ch13-FPV-Tilt
;sim_channel_8 = Ch12-FPV-Pan
; take values from TX or RX (before or after mixes)
take_from = TX
[Video]
; Windowed simulator mode configurations
; Each resolution defines the upper left corner and width/hight.
; User can cycle through all resolutions using the menu command.
number_of_resolutions = 2
; x, y, width, height
resolution_1 = 50 50 640 720
resolution_2 = 0 0 800 480

View File

@ -0,0 +1,86 @@
.NAME "CopterControl"
.HELP_EN "\
OpenPilot CopterControl HiTL plugin for AeroSIM RC"
.IMAGE_OFF "cc_off.tga"
.IMAGE_ON "cc_on.tga"
.IMAGE_OFF_MOUSE_HOVER "cc_off_hover.tga"
.IMAGE_ON_MOUSE_HOVER "cc_on_hover.tga"
.MENU_ITEM_00_NAME "Enable"
.MENU_ITEM_00_TYPE CHECKBOX
.MENU_ITEM_00_HAS_SEPARATOR 0
.MENU_ITEM_00_MOUSE_RECT_XY 89 91
.MENU_ITEM_00_MOUSE_RECT_DXDY 48 48
.MENU_ITEM_00_HIDE_MENU_ITEM 0
.MENU_ITEM_01_NAME "Transmit data"
.MENU_ITEM_01_TYPE CHECKBOX
.MENU_ITEM_01_HAS_SEPARATOR 0
.MENU_ITEM_01_MOUSE_RECT_XY 110 166
.MENU_ITEM_01_MOUSE_RECT_DXDY 52 34
.MENU_ITEM_01_HIDE_MENU_ITEM 0
.MENU_ITEM_02_NAME "Receive data"
.MENU_ITEM_02_TYPE CHECKBOX
.MENU_ITEM_02_HAS_SEPARATOR 1
.MENU_ITEM_02_MOUSE_RECT_XY 36 166
.MENU_ITEM_02_MOUSE_RECT_DXDY 52 34
.MENU_ITEM_02_HIDE_MENU_ITEM 0
.MENU_ITEM_03_NAME "Change window size and position"
.MENU_ITEM_03_TYPE COMMAND
.MENU_ITEM_03_HAS_SEPARATOR 0
.MENU_ITEM_03_MOUSE_RECT_XY 0 0
.MENU_ITEM_03_MOUSE_RECT_DXDY 0 0
.MENU_ITEM_03_HIDE_MENU_ITEM 0
.MENU_ITEM_04_NAME "Move to next waypoint"
.MENU_ITEM_04_TYPE COMMAND
.MENU_ITEM_04_HAS_SEPARATOR 0
.MENU_ITEM_04_MOUSE_RECT_XY 0 0
.MENU_ITEM_04_MOUSE_RECT_DXDY 0 0
.MENU_ITEM_04_HIDE_MENU_ITEM 0
.MENU_ITEM_05_NAME "no action"
.MENU_ITEM_05_TYPE COMMAND
.MENU_ITEM_05_HAS_SEPARATOR 0
.MENU_ITEM_05_MOUSE_RECT_XY 0 0
.MENU_ITEM_05_MOUSE_RECT_DXDY 0 0
.MENU_ITEM_05_HIDE_MENU_ITEM 0
.MENU_ITEM_06_NAME "Blue LED"
.MENU_ITEM_06_TYPE CHECKBOX
.MENU_ITEM_06_HAS_SEPARATOR 0
.MENU_ITEM_06_MOUSE_RECT_XY 6 40
.MENU_ITEM_06_MOUSE_RECT_DXDY 15 12
.MENU_ITEM_06_HIDE_MENU_ITEM 1
.MENU_ITEM_07_NAME "Green LED"
.MENU_ITEM_07_TYPE CHECKBOX
.MENU_ITEM_07_HAS_SEPARATOR 0
.MENU_ITEM_07_MOUSE_RECT_XY 6 52
.MENU_ITEM_07_MOUSE_RECT_DXDY 15 12
.MENU_ITEM_07_HIDE_MENU_ITEM 1
.MENU_ITEM_08_NAME "FlightMode 1"
.MENU_ITEM_08_TYPE CHECKBOX
.MENU_ITEM_08_HAS_SEPARATOR 0
.MENU_ITEM_08_MOUSE_RECT_XY 40 19
.MENU_ITEM_08_MOUSE_RECT_DXDY 38 38
.MENU_ITEM_08_HIDE_MENU_ITEM 1
.MENU_ITEM_09_NAME "FlightMode 2"
.MENU_ITEM_09_TYPE CHECKBOX
.MENU_ITEM_09_HAS_SEPARATOR 0
.MENU_ITEM_09_MOUSE_RECT_XY 78 19
.MENU_ITEM_09_MOUSE_RECT_DXDY 38 38
.MENU_ITEM_09_HIDE_MENU_ITEM 1
.MENU_ITEM_10_NAME "FlightMode 3"
.MENU_ITEM_10_TYPE CHECKBOX
.MENU_ITEM_10_HAS_SEPARATOR 0
.MENU_ITEM_10_MOUSE_RECT_XY 115 19
.MENU_ITEM_10_MOUSE_RECT_DXDY 38 38
.MENU_ITEM_10_HIDE_MENU_ITEM 1

View File

@ -0,0 +1,98 @@
/**
******************************************************************************
*
* @file settings.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#include "settings.h"
Settings::Settings(QString settingsPath, QObject *parent) :
QObject(parent)
{
settings = new QSettings(settingsPath + "/cc_plugin.ini", QSettings::IniFormat);
// default settings
sendToHost = "127.0.0.1";
sendToPort = 40100;
listenOnHost = "127.0.0.1";
listenOnPort = 40200;
channels.reserve(60);
for (quint8 i = 0; i < 10; ++i)
inputMap << 255;
for (quint8 i = 0; i < 8; ++i)
outputMap << 255;
sendToRX = true;
takeFromTX = true;
videoModes << 1 << 50 << 50 << 800 << 600;
}
void Settings::read()
{
// network
listenOnHost = settings->value("listen_on_host", listenOnHost).toString();
listenOnPort = settings->value("listen_on_port", listenOnPort).toInt();
sendToHost = settings->value("send_to_host", sendToHost).toString();
sendToPort = settings->value("send_to_port", sendToPort).toInt();
QString allChannels = settings->value("all_channels").toString();
QString chan;
int i = 0;
foreach (chan, allChannels.split(" "))
channels.insert(chan, i++);
// inputs
QString num = "";
QString map = "";
for (quint8 i = 0; i < 10; ++i) {
num = QString::number(i+1);
map = settings->value("Input/cc_channel_" + num).toString();
inputMap[i] = channels.value(map, inputMap.at(i));
}
QString sendTo = settings->value("Input/send_to", "RX").toString();
sendToRX = (sendTo == "RX") ? true : false;
// outputs
for (quint8 i = 0; i < 8; ++i) {
num = QString::number(i+1);
map = settings->value("Output/sim_channel_" + num).toString();
outputMap[i] = channels.value(map, outputMap.at(i));
}
QString takeFrom = settings->value("Output/take_from", "TX").toString();
takeFromTX = (takeFrom == "TX") ? true : false;
// video
quint8 resolutionNum = settings->value("Video/number_of_resolutions", 0).toInt();
if (resolutionNum > 0) {
videoModes.clear();
videoModes << resolutionNum;
for (quint8 i = 0; i < resolutionNum; ++i) {
num = QString::number(i+1);
QString modes = settings->value("Video/resolution_" + num, "0, 0, 640, 480").toString();
QString mode;
foreach (mode, modes.split(" "))
videoModes << mode.toInt();
}
}
}

View File

@ -0,0 +1,67 @@
/**
******************************************************************************
*
* @file settings.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QObject>
#include <QSettings>
#include <QHash>
#include <QList>
#include <QStringList>
#include <QDebug>
class Settings : public QObject
{
public:
explicit Settings(QString settingsPath, QObject *parent = 0);
void read();
QString remoteHost() { return sendToHost; }
quint16 remotePort() { return sendToPort; }
QString localHost() { return listenOnHost; }
quint16 localPort() { return listenOnPort; }
QList<quint8> getInputMap() { return inputMap; }
QList<quint8> getOutputMap() { return outputMap; }
bool isToRX() { return sendToRX; }
bool isFromTX() { return takeFromTX; }
QList<quint16> getVideoModes() { return videoModes; }
private:
QHash<QString, quint8> channels;
QSettings *settings;
QString sendToHost;
quint16 sendToPort;
QString listenOnHost;
quint16 listenOnPort;
QList<quint8> inputMap;
QList<quint8> outputMap;
bool sendToRX;
bool takeFromTX;
QList<quint16> videoModes;
};
#endif // SETTINGS_H

View File

@ -0,0 +1,228 @@
/**
******************************************************************************
*
* @file udpconnect.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#include "udpconnect.h"
#include "enums.h"
UdpSender::UdpSender(const QList<quint8> map,
bool isTX,
QObject *parent)
: QObject(parent)
{
qDebug() << this << "UdpSender::UdpSender thread:" << thread();
outSocket = NULL;
for (int i = 0; i < 8; ++i)
channels << 0.0;
channelsMap = map;
takeFromTX = isTX;
packetsSended = 0;
}
UdpSender::~UdpSender()
{
qDebug() << this << "UdpSender::~UdpSender";
if (outSocket)
delete outSocket;
}
// public
void UdpSender::init(const QString &remoteHost, quint16 remotePort)
{
qDebug() << this << "UdpSender::init";
outHost = remoteHost;
outPort = remotePort;
outSocket = new QUdpSocket();
}
void UdpSender::sendDatagram(const simToPlugin *stp)
{
QByteArray data;
data.resize(188);
QDataStream out(&data, QIODevice::WriteOnly);
out.setFloatingPointPrecision(QDataStream::SinglePrecision);
// magic header, "AERO"
out << quint32(0x4153494D);
// simulation step
out << stp->simTimeStep;
// home location
out << stp->initPosX << stp->initPosY << stp->initPosZ;
out << stp->wpHomeX << stp->wpHomeY << stp->wpHomeLat << stp->wpHomeLong;
// position
out << stp->posX << stp->posY << stp->posZ;
// velocity (world)
out << stp->velX << stp->velY << stp->velZ;
// angular velocity (model)
out << stp->angVelXm << stp->angVelYm << stp->angVelZm;
// acceleration (model)
out << stp->accelXm << stp->accelYm << stp->accelZm;
// coordinates
out << stp->latitude << stp->longitude;
// sonar
out << stp->AGL;
// attitude
out << stp->heading << stp->pitch << stp->roll;
// electric
out << stp->voltage << stp->current;
// matrix
out << stp->axisXx << stp->axisXy << stp->axisXz;
out << stp->axisYx << stp->axisYy << stp->axisYz;
out << stp->axisZx << stp->axisZy << stp->axisZz;
// channels
for (int i = 0; i < 8; ++i) {
quint8 mapTo = channelsMap.at(i);
if (mapTo == 255) // unused channel
out << 0.0;
else if (takeFromTX) // use values from simulators transmitter
out << stp->chSimTX[mapTo];
else // direct use values from ESC/motors/ailerons/etc
out << stp->chSimRX[mapTo];
}
// packet counter
out << packetsSended;
outSocket->writeDatagram(data, outHost, outPort);
++packetsSended;
}
//-----------------------------------------------------------------------------
UdpReceiver::UdpReceiver(const QList<quint8> map,
bool isRX,
QObject *parent)
: QThread(parent)
{
qDebug() << this << "UdpReceiver::UdpReceiver thread:" << thread();
stopped = false;
inSocket = NULL;
for (int i = 0; i < 10; ++i)
channels << -1.0;
channelsMap = map;
sendToRX = isRX;
armed = 0;
mode = 0;
packetsRecived = 1;
}
UdpReceiver::~UdpReceiver()
{
qDebug() << this << "UdpReceiver::~UdpReceiver";
if (inSocket)
delete inSocket;
}
// public
void UdpReceiver::init(const QString &localHost, quint16 localPort)
{
qDebug() << this << "UdpReceiver::init";
inSocket = new QUdpSocket();
qDebug() << this << "inSocket constructed" << inSocket->thread();
inSocket->bind(QHostAddress(localHost), localPort);
}
void UdpReceiver::run()
{
qDebug() << this << "UdpReceiver::run start";
while (!stopped)
onReadyRead();
qDebug() << this << "UdpReceiver::run ended";
}
void UdpReceiver::stop()
{
qDebug() << this << "UdpReceiver::stop";
stopped = true;
}
void UdpReceiver::setChannels(pluginToSim *pts)
{
QMutexLocker locker(&mutex);
for (int i = 0; i < 10; ++i) {
quint8 mapTo = channelsMap.at(i);
if (mapTo != 255) {
float channelValue = qBound(-1.0f, channels.at(i), 1.0f);
if (sendToRX) {
// direct connect to ESC/motors/ailerons/etc
pts->chNewRX[mapTo] = channelValue;
pts->chOverRX[mapTo] = true;
} else {
// replace simulators transmitter
pts->chNewTX[mapTo] = channelValue;
pts->chOverTX[mapTo] = true;
}
}
}
}
void UdpReceiver::getFlighStatus(quint8 &arm, quint8 &mod)
{
QMutexLocker locker(&mutex);
arm = armed;
mod = mode;
}
// private
void UdpReceiver::onReadyRead()
{
if (!inSocket->waitForReadyRead(8)) // 1/60fps ~= 16.7ms, 1/120fps ~= 8.3ms
return;
// TODO: add failsafe
// if a command not recieved then slowly return all channel to neutral
//
while (inSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(inSocket->pendingDatagramSize());
quint64 datagramSize;
datagramSize = inSocket->readDatagram(datagram.data(), datagram.size());
processDatagram(datagram);
}
}
void UdpReceiver::processDatagram(QByteArray &datagram)
{
QDataStream stream(datagram);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
// check magic header
quint32 magic;
stream >> magic;
if (magic != 0x52434D44) // "RCMD"
return;
// read channels
for (int i = 0; i < 10; ++i)
stream >> channels[i];
// read flight mode
stream >> armed >> mode;
// read counter
stream >> packetsRecived;
}

View File

@ -0,0 +1,90 @@
/**
******************************************************************************
*
* @file udpconnect.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin
*****************************************************************************/
/*
* 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
*/
#ifndef UDPCONNECT_H
#define UDPCONNECT_H
#include <QObject>
#include <QUdpSocket>
#include <QList>
#include <QTime>
#include <QMutex>
#include <QMutexLocker>
#include "aerosimrcdatastruct.h"
class UdpSender : public QObject
{
// Q_OBJECT
public:
explicit UdpSender(const QList<quint8> map, bool isTX, QObject *parent = 0);
~UdpSender();
void init(const QString &remoteHost, quint16 remotePort);
void sendDatagram(const simToPlugin *stp);
quint32 pcks() { return packetsSended; }
private:
QUdpSocket *outSocket;
QHostAddress outHost;
quint16 outPort;
QList<float> channels;
QList<quint8> channelsMap;
bool takeFromTX;
quint32 packetsSended;
};
class UdpReceiver : public QThread
{
// Q_OBJECT
public:
explicit UdpReceiver(const QList<quint8> map, bool isRX, QObject *parent = 0);
~UdpReceiver();
void init(const QString &localHost, quint16 localPort);
void run();
void stop();
// function getChannels for other threads
void setChannels(pluginToSim *pts);
void getFlighStatus(quint8 &arm, quint8 &mod);
quint8 getArmed() { return armed; }
quint8 getMode() { return mode; }
quint32 pcks() { return packetsRecived; }
private:
volatile bool stopped;
QMutex mutex;
QUdpSocket *inSocket;
QList<float> channels;
QList<quint8> channelsMap;
bool sendToRX;
quint8 armed;
quint8 mode;
quint32 packetsRecived;
void onReadyRead();
void processDatagram(QByteArray &datagram);
};
#endif // UDPCONNECT_H

View File

@ -0,0 +1,17 @@
include(../../../../../openpilotgcs.pri)
QT += core gui network
TEMPLATE = app
TARGET = udp_test
DESTDIR = $$GCS_APP_PATH
HEADERS += \
udptestwidget.h
SOURCES += \
udptestmain.cpp \
udptestwidget.cpp
FORMS += \
udptestwidget.ui

View File

@ -0,0 +1,38 @@
/**
******************************************************************************
*
* @file udptestmain.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin test utility
*****************************************************************************/
/*
* 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
*/
#include <QApplication>
#include "udptestwidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}

View File

@ -0,0 +1,537 @@
/**
******************************************************************************
*
* @file udptestwidget.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin test utility
*****************************************************************************/
/*
* 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
*/
#include "udptestwidget.h"
#include "ui_udptestwidget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
inSocket = NULL;
outSocket = NULL;
screenTimeout.start();
packetCounter = 0;
autoSendTimer = new QTimer(this);
connect(autoSendTimer, SIGNAL(timeout()), this, SLOT(sendDatagram()), Qt::DirectConnection);
}
Widget::~Widget()
{
if(outSocket) {
delete outSocket;
}
if(inSocket) {
delete inSocket;
}
delete ui;
}
// private slots //////////////////////////////////////////////////////////////
void Widget::on_btReciveStart_clicked()
{
on_btReciveStop_clicked();
inSocket = new QUdpSocket();
QString host = ui->localHost->text();
quint16 port = ui->localPort->text().toInt();
if (inSocket->bind(QHostAddress(host), port)) {
connect(inSocket, SIGNAL(readyRead()),
this, SLOT(readDatagram()), Qt::DirectConnection);
ui->listWidget->addItem("bind ok");
ui->btReciveStop->setEnabled(1);
ui->localHost->setDisabled(1);
ui->localPort->setDisabled(1);
ui->btReciveStart->setDisabled(1);
} else {
ui->listWidget->addItem("bind error: " + inSocket->errorString());
}
}
void Widget::on_btReciveStop_clicked()
{
if(inSocket) {
delete inSocket;
inSocket = NULL;
ui->listWidget->addItem("unbind ok");
} else {
ui->listWidget->addItem("socket not found");
}
ui->btReciveStart->setEnabled(1);
ui->localHost->setEnabled(1);
ui->localPort->setEnabled(1);
ui->btReciveStop->setDisabled(1);
}
void Widget::on_btTransmitStart_clicked()
{
on_btTransmitStop_clicked();
outSocket = new QUdpSocket();
outHost = ui->simHost->text();
outPort = ui->simPort->text().toInt();
ui->listWidget->addItem("transmit started");
ui->btTransmitStop->setEnabled(1);
ui->simHost->setDisabled(1);
ui->simPort->setDisabled(1);
ui->btTransmitStart->setDisabled(1);
}
void Widget::on_btTransmitStop_clicked()
{
if(outSocket) {
delete outSocket;
outSocket = NULL;
ui->listWidget->addItem("transmit stopped");
} else {
ui->listWidget->addItem("transmit socket not found");
}
ui->btTransmitStart->setEnabled(1);
ui->simHost->setEnabled(1);
ui->simPort->setEnabled(1);
ui->btTransmitStop->setDisabled(1);
}
void Widget::readDatagram()
{
while (inSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(inSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
quint64 datagramSize = inSocket->readDatagram(datagram.data(), datagram.size(),
&sender, &senderPort);
Q_UNUSED(datagramSize);
processDatagram(datagram);
if (ui->autoAnswer->isChecked())
sendDatagram();
}
}
// private ////////////////////////////////////////////////////////////////////
void Widget::processDatagram(const QByteArray &data)
{
QByteArray buf = data;
QDataStream stream(&buf, QIODevice::ReadOnly);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
// check magic header
quint32 magic;
stream >> magic;
if (magic == 0x4153494D) { // "AERO"
float timeStep,
homeX, homeY, homeZ,
WpHX, WpHY, WpLat, WpLon,
posX, posY, posZ,
velX, velY, velZ,
angX, angY, angZ,
accX, accY, accZ,
lat, lon, alt,
head, pitch, roll,
volt, curr,
rx, ry, rz, fx, fy, fz, ux, uy, uz,
chAil, chEle, chThr, chRud, chPlg1, chPlg2, chFpv1, chFpv2;
stream >> timeStep;
stream >> homeX >> homeY >> homeZ;
stream >> WpHX >> WpHY >> WpLat >> WpLon;
stream >> posX >> posY >> posZ;
stream >> velX >> velY >> velZ;
stream >> angX >> angY >> angZ;
stream >> accX >> accY >> accZ;
stream >> lat >> lon >> alt;
stream >> head >> pitch >> roll;
stream >> volt >> curr;
stream >> rx >> ry >> rz >> fx >> fy >> fz >> ux >> uy >> uz;
stream >> chAil >> chEle >> chThr >> chRud >> chPlg1 >> chPlg2 >> chFpv1 >> chFpv2;
stream >> packetCounter;
if(ui->tabWidget->currentIndex() != 0)
return;
if (screenTimeout.elapsed() < 200)
return;
ui->listWidget->clear();
/*
ui->listWidget->addItem("time step (s)");
ui->listWidget->addItem(QString("%1")
.arg(timeStep);
ui->listWidget->addItem("home location (m)");
ui->listWidget->addItem(QString("%1, %2, %3")
.arg(homeX, 7, 'f', 4)
.arg(homeY, 7, 'f', 4)
.arg(homeZ, 7, 'f', 4));
ui->listWidget->addItem("home waypoint");
ui->listWidget->addItem(QString("%1, %2, %3, %4")
.arg(WpHX, 7, 'f', 4)
.arg(WpHY, 7, 'f', 4)
.arg(WpLat, 7, 'f', 4)
.arg(WpLon, 7, 'f', 4));
ui->listWidget->addItem("model position (m)");
ui->listWidget->addItem(QString("%1, %2, %3")
.arg(posX, 7, 'f', 4)
.arg(posY, 7, 'f', 4)
.arg(posZ, 7, 'f', 4));
ui->listWidget->addItem("model velocity (m/s)");
ui->listWidget->addItem(QString("%1, %2, %3")
.arg(velX, 7, 'f', 4)
.arg(velY, 7, 'f', 4)
.arg(velZ, 7, 'f', 4));
ui->listWidget->addItem("model angular velocity (rad/s)");
ui->listWidget->addItem(QString("%1, %2, %3")
.arg(angX, 7, 'f', 4)
.arg(angY, 7, 'f', 4)
.arg(angZ, 7, 'f', 4));
ui->listWidget->addItem("model acceleration (m/s/s)");
ui->listWidget->addItem(QString("%1, %2, %3")
.arg(accX, 7, 'f', 4)
.arg(accY, 7, 'f', 4)
.arg(accZ, 7, 'f', 4));
ui->listWidget->addItem("model coordinates (deg, deg, m)");
ui->listWidget->addItem(QString("%1, %2, %3")
.arg(lat, 7, 'f', 4)
.arg(lon, 7, 'f', 4)
.arg(alt, 7, 'f', 4));
ui->listWidget->addItem("model electrics");
ui->listWidget->addItem(QString("%1V, %2A")
.arg(volt, 7, 'f', 4)
.arg(curr, 7, 'f', 4));
ui->listWidget->addItem("channels");
ui->listWidget->addItem(QString("%1 %2 %3 %4 %5 %6 %7 %8")
.arg(chAil, 6, 'f', 3)
.arg(chEle, 6, 'f', 3)
.arg(chThr, 6, 'f', 3)
.arg(chRud, 6, 'f', 3)
.arg(chPlg1, 6, 'f', 3)
.arg(chPlg2, 6, 'f', 3)
.arg(chFpv1, 6, 'f', 3)
.arg(chFpv2, 6, 'f', 3));
ui->listWidget->addItem("datagram size (bytes), packet counter");
ui->listWidget->addItem(QString("%1 %2")
.arg(data.size())
.arg(packetCounter));
*/
// matrix calculation start
// model matrix
QMatrix4x4 m = QMatrix4x4( fy, fx, -fz, 0.0,
ry, rx, -rz, 0.0,
-uy, -ux, uz, 0.0,
0.0, 0.0, 0.0, 1.0);
m.optimize();
// world matrix
QMatrix4x4 w = m.inverted();
// model quat
QQuaternion q;
asMatrix2Quat(m, q);
// model roll, pitch, yaw
QVector3D rpy;
asMatrix2RPY(m, rpy);
// sonar
float sAlt = 5.0;
if ((alt < (sAlt * 2.0)) && (roll < 0.35) && (pitch < 0.35)) {
float x = alt * qTan(roll);
float y = alt * qTan(pitch);
float h = QVector3D(x, y, alt).length();
sAlt = qMin(h, sAlt);
}
ui->listWidget->addItem("sonar altitude");
ui->listWidget->addItem(QString("%1")
.arg(sAlt, 8, 'f', 5));
ui->listWidget->addItem("vectors");
ui->listWidget->addItem(QString(" X Y Z"));
ui->listWidget->addItem(QString("R: %1 %2 %3\nF: %4 %5 %6\nU: %7 %8 %9")
.arg(rx, 8, 'f', 5).arg(ry, 8, 'f', 5).arg(rz, 8, 'f', 5)
.arg(fx, 8, 'f', 5).arg(fy, 8, 'f', 5).arg(fz, 8, 'f', 5)
.arg(ux, 8, 'f', 5).arg(uy, 8, 'f', 5).arg(uz, 8, 'f', 5));
ui->listWidget->addItem("CC model matrix");
ui->listWidget->addItem(QString(" %1 %2 %3\n %4 %5 %6\n %7 %8 %9")
.arg(m(0, 0), 8, 'f', 5).arg(m(0, 1), 8, 'f', 5).arg(m(0, 2), 8, 'f', 5)
.arg(m(1, 0), 8, 'f', 5).arg(m(1, 1), 8, 'f', 5).arg(m(1, 2), 8, 'f', 5)
.arg(m(2, 0), 8, 'f', 5).arg(m(2, 1), 8, 'f', 5).arg(m(2, 2), 8, 'f', 5));
ui->listWidget->addItem("CC world matrix");
ui->listWidget->addItem(QString(" %1 %2 %3\n %4 %5 %6\n %7 %8 %9")
.arg(w(0, 0), 8, 'f', 5).arg(w(0, 1), 8, 'f', 5).arg(w(0, 2), 8, 'f', 5)
.arg(w(1, 0), 8, 'f', 5).arg(w(1, 1), 8, 'f', 5).arg(w(1, 2), 8, 'f', 5)
.arg(w(2, 0), 8, 'f', 5).arg(w(2, 1), 8, 'f', 5).arg(w(2, 2), 8, 'f', 5));
ui->listWidget->addItem("CC quaternion");
ui->listWidget->addItem(QString("%1, %2, %3, %4")
.arg(q.x(), 7, 'f', 4)
.arg(q.y(), 7, 'f', 4)
.arg(q.z(), 7, 'f', 4)
.arg(q.scalar(), 7, 'f', 4));
ui->listWidget->addItem("model attitude (deg)");
ui->listWidget->addItem(QString("%1, %2, %3")
.arg(roll*RAD2DEG, 7, 'f', 4)
.arg(pitch*RAD2DEG, 7, 'f', 4)
.arg(head*RAD2DEG, 7, 'f', 4));
ui->listWidget->addItem("CC attitude calculated (deg)");
ui->listWidget->addItem(QString("%1, %2, %3")
.arg(rpy.x(), 7, 'f', 4)
.arg(rpy.y(), 7, 'f', 4)
.arg(rpy.z(), 7, 'f', 4));
screenTimeout.restart();
} else if (magic == 0x52434D44) { // "RCMD"
qreal ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9, ch10;
stream >> ch1 >> ch2 >> ch3 >> ch4 >> ch5 >> ch6 >> ch7 >> ch8 >> ch9 >> ch10;
quint8 armed, mode;
stream >> armed >> mode;
if(ui->tabWidget->currentIndex() == 0) {
if (screenTimeout.elapsed() < 200)
return;
ui->listWidget->clear();
ui->listWidget->addItem("channels");
ui->listWidget->addItem("CH1: " + QString::number(ch1));
ui->listWidget->addItem("CH2: " + QString::number(ch2));
ui->listWidget->addItem("CH3: " + QString::number(ch3));
ui->listWidget->addItem("CH4: " + QString::number(ch4));
ui->listWidget->addItem("CH5: " + QString::number(ch5));
ui->listWidget->addItem("CH6: " + QString::number(ch6));
ui->listWidget->addItem("CH7: " + QString::number(ch7));
ui->listWidget->addItem("CH8: " + QString::number(ch8));
ui->listWidget->addItem("CH9: " + QString::number(ch9));
ui->listWidget->addItem("CH10:" + QString::number(ch10));
ui->listWidget->addItem("armed:" + QString::number(armed));
ui->listWidget->addItem("fmode:" + QString::number(mode));
}
screenTimeout.restart();
} else {
qDebug() << "unknown magic:" << magic;
}
}
void Widget::sendDatagram()
{
if(!outSocket)
return;
float ch[10]; // = {0,0,0,0,0,0,0,0,0,0};
quint8 armed;
quint8 fmode;
const float coeff = 1.0 / 512.0;
ch[0] = ui->ch1->value() * coeff;
ch[1] = ui->ch2->value() * coeff;
ch[2] = ui->ch3->value() * coeff;
ch[3] = ui->ch4->value() * coeff;
ch[4] = ui->ch5->value() * coeff;
ch[5] = ui->ch6->value() * coeff;
ch[6] = ui->ch7->value() * coeff;
ch[7] = ui->ch8->value() * coeff;
ch[8] = ui->ch9->value() * coeff;
ch[9] = ui->ch10->value() * coeff;
armed = (ui->disarmed->isChecked()) ? 0 : (ui->arming->isChecked()) ? 1 : 2;
fmode = ui->flightMode->value();
QByteArray data;
// 50 - current size of values, 4(quint32) + 10*4(float) + 2*1(quint8) + 4(quint32)
data.resize(50);
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
// magic header, "RCMD"
stream << quint32(0x52434D44);
// send channels
for (int i = 0; i < 10; ++i) {
stream << ch[i];
}
// send armed and mode
stream << armed << fmode;
// send readed counter
stream << packetCounter;
if (outSocket->writeDatagram(data, outHost, outPort) == -1) {
qDebug() << "write failed: outHost" << outHost << " "
<< "outPort " << outPort << " "
<< outSocket->errorString();
}
}
void Widget::on_autoSend_clicked()
{
autoSendTimer->start(100);
qDebug() << "timer start";
}
void Widget::on_autoAnswer_clicked()
{
autoSendTimer->stop();
qDebug() << "timer stop";
}
// transfomations
void Widget::asMatrix2Quat(const QMatrix4x4 &m, QQuaternion &q)
{
qreal w, x, y, z;
// w always >= 0
w = qSqrt(qMax(0.0, 1.0 + m(0, 0) + m(1, 1) + m(2, 2))) / 2.0;
x = qSqrt(qMax(0.0, 1.0 + m(0, 0) - m(1, 1) - m(2, 2))) / 2.0;
y = qSqrt(qMax(0.0, 1.0 - m(0, 0) + m(1, 1) - m(2, 2))) / 2.0;
z = qSqrt(qMax(0.0, 1.0 - m(0, 0) - m(1, 1) + m(2, 2))) / 2.0;
x = copysign(x, (m(1, 2) - m(2, 1)));
y = copysign(y, (m(2, 0) - m(0, 2)));
z = copysign(z, (m(0, 1) - m(1, 0)));
q.setScalar(w);
q.setX(x);
q.setY(y);
q.setZ(z);
}
void Widget::asQuat2RPY(const QQuaternion &q, QVector3D &rpy)
{
qreal roll;
qreal pitch;
qreal yaw;
const qreal d2 = 2.0;
const qreal qss = q.scalar() * q.scalar();
const qreal qxx = q.x() * q.x();
const qreal qyy = q.y() * q.y();
const qreal qzz = q.z() * q.z();
qreal test = -d2 * (q.x() * q.z() - q.scalar() * q.y());
if (qFabs(test) > 0.998) {
// ~86.3°, gimbal lock
qreal R10 = d2 * (q.x() * q.y() - q.scalar() * q.z());
qreal R11 = qss - qxx + qyy - qzz;
roll = 0.0;
pitch = copysign(M_PI_2, test);
yaw = qAtan2(-R10, R11);
} else {
qreal R12 = d2 * (q.y() * q.z() + q.scalar() * q.x());
qreal R22 = qss - qxx - qyy + qzz;
qreal R01 = d2 * (q.x() * q.y() + q.scalar() * q.z());
qreal R00 = qss + qxx - qyy - qzz;
roll = qAtan2(R12, R22);
pitch = qAsin(test);
yaw = qAtan2(R01, R00);
}
rpy.setX(RAD2DEG * roll);
rpy.setY(RAD2DEG * pitch);
rpy.setZ(RAD2DEG * yaw);
}
void Widget::asMatrix2RPY(const QMatrix4x4 &m, QVector3D &rpy)
{
qreal roll;
qreal pitch;
qreal yaw;
if (qFabs(m(0, 2)) > 0.998) {
// ~86.3°, gimbal lock
roll = 0.0;
pitch = copysign(M_PI_2, -m(0, 2));
yaw = qAtan2(-m(1, 0), m(1, 1));
} else {
roll = qAtan2(m(1, 2), m(2, 2));
pitch = qAsin(-m(0, 2));
yaw = qAtan2(m(0, 1), m(0, 0));
}
rpy.setX(roll * RAD2DEG);
rpy.setY(pitch * RAD2DEG);
rpy.setZ(yaw * RAD2DEG);
}
/* // not used
void Widget::ccRPY2Quat(const QVector3D &rpy, QQuaternion &q)
{
float phi, theta, psi;
float cphi, sphi, ctheta, stheta, cpsi, spsi;
phi = rpy.x() / 2;
theta = rpy.y() / 2;
psi = rpy.z() / 2;
cphi = cosf(phi);
sphi = sinf(phi);
ctheta = cosf(theta);
stheta = sinf(theta);
cpsi = cosf(psi);
spsi = sinf(psi);
q.setScalar(cphi * ctheta * cpsi + sphi * stheta * spsi);
q.setX(sphi * ctheta * cpsi - cphi * stheta * spsi);
q.setY(cphi * stheta * cpsi + sphi * ctheta * spsi);
q.setZ(cphi * ctheta * spsi - sphi * stheta * cpsi);
if (q.scalar() < 0) { // q0 always positive for uniqueness
q.setScalar(-q.scalar());
q.setX(-q.x());
q.setY(-q.y());
q.setZ(-q.z());
}
}
void Widget::ccQuat2Matrix(const QQuaternion &q, QMatrix4x4 &m)
{
float q0s = q.scalar() * q.scalar();
float q1s = q.x() * q.x();
float q2s = q.y() * q.y();
float q3s = q.z() * q.z();
float m00 = q0s + q1s - q2s - q3s;
float m01 = 2 * (q.x() * q.y() + q.scalar() * q.z());
float m02 = 2 * (q.x() * q.z() - q.scalar() * q.y());
float m10 = 2 * (q.x() * q.y() - q.scalar() * q.z());
float m11 = q0s - q1s + q2s - q3s;
float m12 = 2 * (q.y() * q.z() + q.scalar() * q.x());
float m20 = 2 * (q.x() * q.z() + q.scalar() * q.y());
float m21 = 2 * (q.y() * q.z() - q.scalar() * q.x());
float m22 = q0s - q1s - q2s + q3s;
m = QMatrix4x4(m00, m01, m02, 0,
m10, m11, m12, 0,
m20, m21, m22, 0,
0, 0, 0, 1);
}
*/

View File

@ -0,0 +1,91 @@
/**
******************************************************************************
*
* @file udptestwidget.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup 3rdParty Third-party integration
* @{
* @addtogroup AeroSimRC AeroSimRC proxy plugin
* @{
* @brief AeroSimRC simulator to HITL proxy plugin test utility
*****************************************************************************/
/*
* 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
*/
#ifndef UDPTESTWIDGET_H
#define UDPTESTWIDGET_H
#include <QWidget>
#include <QUdpSocket>
#include <QTime>
#include <qmath.h>
#include <QVector3D>
#include <QMatrix4x4>
#include <QDebug>
#include <QTimer>
namespace Ui {
class Widget;
}
const float RAD2DEG = (float)(180.0/M_PI);
const float DEG2RAD = (float)(M_PI/180.0);
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_btReciveStart_clicked();
void on_btReciveStop_clicked();
void on_btTransmitStart_clicked();
void on_btTransmitStop_clicked();
void readDatagram();
void sendDatagram();
void on_autoSend_clicked();
void on_autoAnswer_clicked();
private:
Ui::Widget *ui;
QTime screenTimeout;
QUdpSocket *inSocket;
QUdpSocket *outSocket;
QHostAddress outHost;
quint16 outPort;
quint32 packetCounter;
void processDatagram(const QByteArray &data);
QTimer *autoSendTimer;
void asMatrix2Quat(const QMatrix4x4 &m, QQuaternion &q);
void asMatrix2RPY(const QMatrix4x4 &m, QVector3D &rpy);
void asQuat2RPY(const QQuaternion &q, QVector3D &rpy);
/* // not used
* void ccRPY2Quat(const QVector3D &rpy, QQuaternion &q);
* void ccQuat2Matrix(const QQuaternion &q, QMatrix4x4 &m);
*/
};
#endif // UDPTESTWIDGET_H

View File

@ -0,0 +1,940 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>440</width>
<height>525</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">udp_test</string>
</property>
<property name="windowFilePath">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="4">
<widget class="QPushButton" name="btReciveStart">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">Connect</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="localPort">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">40100</string>
</property>
<property name="maxLength">
<number>5</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="localHost">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">127.0.0.1</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lbLocalHost">
<property name="text">
<string notr="true">sim host</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lbSimHost">
<property name="text">
<string notr="true">local host:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="lbSimPort">
<property name="text">
<string notr="true">local port:</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QPushButton" name="btReciveStop">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">Disconnect</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="simHost">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">127.0.0.1</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="lbLocalPort">
<property name="text">
<string notr="true">sim port</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="simPort">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">40200</string>
</property>
<property name="maxLength">
<number>5</number>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="btTransmitStart">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">Transmit</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QPushButton" name="btTransmitStop">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">Stop</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_1">
<attribute name="title">
<string notr="true">raw data</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QListWidget" name="listWidget">
<property name="font">
<font>
<family>Terminal</family>
<pointsize>10</pointsize>
</font>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string notr="true">channels</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>send data</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QRadioButton" name="autoAnswer">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string notr="true">answer on recieve</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="autoSend">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string notr="true">auto send</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Flight mode</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QSlider" name="flightMode">
<property name="maximum">
<number>6</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>1</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Armed state</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QRadioButton" name="disarmed">
<property name="text">
<string>Disarmed</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="arming">
<property name="text">
<string>Arming</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="armed">
<property name="text">
<string>Armed</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Channels</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<property name="spacing">
<number>3</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="lbCH1n">
<property name="text">
<string notr="true">CH1</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="ch1">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="lbCH1">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lbCH2n">
<property name="text">
<string notr="true">CH2</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="ch2">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="lbCH2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lbCH3n">
<property name="text">
<string notr="true">CH3</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="ch3">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="lbCH3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lbCH4n">
<property name="text">
<string notr="true">CH4</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSlider" name="ch4">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="lbCH4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lbCH5n">
<property name="text">
<string notr="true">CH5</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSlider" name="ch5">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="lbCH5">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lbCH6n">
<property name="text">
<string notr="true">CH6</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLabel" name="lbCH6">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="lbCH7n">
<property name="text">
<string notr="true">Ch7</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QLabel" name="lbCH7">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="lbCH8n">
<property name="text">
<string notr="true">Ch8</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QLabel" name="lbCH8">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="lbCH9n">
<property name="text">
<string notr="true">Ch9</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QSlider" name="ch9">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QLabel" name="lbCH9">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="lbCH10n">
<property name="text">
<string notr="true">Ch10</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QSlider" name="ch10">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QLabel" name="lbCH10">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSlider" name="ch6">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSlider" name="ch7">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSlider" name="ch8">
<property name="minimum">
<number>-511</number>
</property>
<property name="maximum">
<number>512</number>
</property>
<property name="singleStep">
<number>16</number>
</property>
<property name="pageStep">
<number>32</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>128</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -1,27 +1,5 @@
TEMPLATE = lib
TARGET = HITLv2
QT += network
include(../../openpilotgcsplugin.pri)
include(hitlv2_dependencies.pri)
HEADERS += \
aerosimrc.h \
hitlv2configuration.h \
hitlv2factory.h \
hitlv2gadget.h \
hitlv2optionspage.h \
hitlv2plugin.h \
hitlv2widget.h \
simulatorv2.h
SOURCES += \
aerosimrc.cpp \
hitlv2configuration.cpp \
hitlv2factory.cpp \
hitlv2gadget.cpp \
hitlv2optionspage.cpp \
hitlv2plugin.cpp \
hitlv2widget.cpp \
simulatorv2.cpp
OTHER_FILES += hitlv2.pluginspec
FORMS += \
hitlv2optionspage.ui \
hitlv2widget.ui
TEMPLATE = subdirs
SUBDIRS = plugin aerosimrc
plugin.file = plugin.pro

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitlconfiguration.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2configuration.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitlconfiguration.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2configuration.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitlfactory.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2factory.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
@ -24,6 +24,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "hitlv2factory.h"
#include "hitlv2widget.h"
#include "hitlv2gadget.h"

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitlfactory.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2factory.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitl.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2gadget.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
@ -24,6 +24,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "hitlv2gadget.h"
#include "hitlv2widget.h"
#include "hitlv2configuration.h"

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitl.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2gadget.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitloptionspage.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2optionspage.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitloptionspage.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2optionspage.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file mapplugin.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2plugin.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
@ -24,6 +24,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "hitlv2plugin.h"
#include "hitlv2factory.h"
#include <QtPlugin>

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file browserplugin.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2plugin.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitlwidget.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2widget.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
@ -24,6 +24,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "hitlv2widget.h"
#include "ui_hitlv2widget.h"
#include <QDebug>

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file hitlwidget.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file hitlv2widget.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -0,0 +1,32 @@
TEMPLATE = lib
TARGET = HITLv2
QT += network
include(../../openpilotgcsplugin.pri)
include(hitlv2_dependencies.pri)
HEADERS += \
aerosimrc.h \
hitlv2configuration.h \
hitlv2factory.h \
hitlv2gadget.h \
hitlv2optionspage.h \
hitlv2plugin.h \
hitlv2widget.h \
simulatorv2.h
SOURCES += \
aerosimrc.cpp \
hitlv2configuration.cpp \
hitlv2factory.cpp \
hitlv2gadget.cpp \
hitlv2optionspage.cpp \
hitlv2plugin.cpp \
hitlv2widget.cpp \
simulatorv2.cpp
FORMS += \
hitlv2optionspage.ui \
hitlv2widget.ui
OTHER_FILES += hitlv2.pluginspec

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file simulator.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file simulatorv2.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -1,13 +1,13 @@
/**
******************************************************************************
*
* @file simulator.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @file simulatorv2.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010-2012.
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup HITLPlugin HITL Plugin
* @addtogroup HITLPlugin HITLv2 Plugin
* @{
* @brief The Hardware In The Loop plugin
* @brief The Hardware In The Loop plugin version 2
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify

View File

@ -247,14 +247,6 @@ FirmwareIAPObj::DataFields UAVObjectUtilManager::getFirmwareIap()
if (!firmwareIap)
return dummy;
// The code below will ask for the object update and wait for the updated to be received,
// or the timeout of the timer, set to 1 second.
QEventLoop loop;
connect(firmwareIap, SIGNAL(objectUpdated(UAVObject*)), &loop, SLOT(quit()));
QTimer::singleShot(1000, &loop, SLOT(quit())); // Create a timeout
firmwareIap->requestUpdate();
loop.exec();
return firmwareIap->getData();
}

View File

@ -388,6 +388,11 @@ void Telemetry::processObjectQueue()
UAVObject::UpdateMode updateMode = UAVObject::GetGcsTelemetryUpdateMode(metadata);
if ( ( objInfo.event != EV_UNPACKED ) && ( ( objInfo.event != EV_UPDATED_PERIODIC ) || ( updateMode != UAVObject::UPDATEMODE_THROTTLED ) ) )
{
QMap<quint32, ObjectTransactionInfo*>::iterator itr = transMap.find(objInfo.obj->getObjID());
if ( itr != transMap.end() ) {
qDebug() << "!!!!!! Making request for an object: " << objInfo.obj->getName() << " for which a request is already in progress!!!!!!";
return;
}
UAVObject::Metadata metadata = objInfo.obj->getMetadata();
ObjectTransactionInfo *transInfo = new ObjectTransactionInfo(this);
transInfo->obj = objInfo.obj;

View File

@ -33,7 +33,7 @@ It is expected that you have the following tools installed into the listed
locations (but any other locations are fine as well):
- Python in C:\Python27
- QtSDK in C:\Qt\2010.05 or C:\QtSDK (depending on SDK version)
- QtSDK in C:\QtSDK (depending on SDK version)
- CodeSourcery G++ in %ProgramFiles%\CodeSourcery\Sourcery G++ Lite
- msysGit in %ProgramFiles%\Git
- Unicode NSIS in %ProgramFiles%\NSIS\Unicode
@ -190,8 +190,8 @@ This set of scripts uses the MSYS package included into the msysGit
distribution and MinGW make included into the QtSDK package.
The sh.cmd, shell_script.reg and this README.txt files were written
by Oleg Semyonov (os-openpilot-org@os-propo.info) for the OpenPilot
project and are licensed under CC-BY-SA terms:
by Oleg Semyonov (os@openpilot.org) for the OpenPilot project and
are licensed under CC-BY-SA terms:
http://creativecommons.org/licenses/by-sa/3.0/

View File

@ -54,12 +54,8 @@ set NOT_FOUND=
set PATH_DIRS=
call :which MSYSGIT "%ProgramFiles%\Git\bin" git.exe
rem These two lines for qt-sdk-win-opensource-2010.05.exe:
call :which QTMINGW "C:\Qt\2010.05\mingw\bin" mingw32-make.exe
call :which QTSDK "C:\Qt\2010.05\qt\bin" qmake.exe
rem These two lines for Qt_SDK_Win_offline_v1_1_1_en.exe:
rem call :which QTMINGW "C:\QtSDK\mingw\bin" mingw32-make.exe
rem call :which QTSDK "C:\QtSDK\Desktop\Qt\4.7.3\mingw\bin" qmake.exe
call :which QTMINGW "C:\QtSDK\mingw\bin" mingw32-make.exe
call :which QTSDK "C:\QtSDK\Desktop\Qt\4.8.1\mingw\bin" qmake.exe
call :which CODESOURCERY "%ProgramFiles%\CodeSourcery\Sourcery G++ Lite\bin" cs-make.exe
call :which PYTHON "C:\Python27" python.exe
call :which UNSIS "%ProgramFiles%\NSIS\Unicode" makensis.exe

View File

@ -42,7 +42,7 @@ DEB_PACKAGE_NAME := openpilot_$(VERSION_FULL)_$(DEB_PLATFORM)
linux_deb_package: deb_build gcs
@echo $@ starting
cd .. && dpkg-buildpackage -b
cd .. && dpkg-buildpackage -b -us -uc
$(V1)mv $(ROOT_DIR)/../$(DEB_PACKAGE_NAME).deb $(BUILD_DIR)
$(V1)mv $(ROOT_DIR)/../$(DEB_PACKAGE_NAME).changes $(BUILD_DIR)
$(V1)rm -rf $(DEB_BUILD_DIR)

View File

@ -38,6 +38,7 @@
!define NSIS_DATA_TREE "."
!define GCS_BUILD_TREE "..\..\build\ground\openpilotgcs"
!define UAVO_SYNTH_TREE "..\..\build\uavobject-synthetics"
!define AEROSIMRC_TREE "..\..\build\ground\AeroSIM-RC"
; Default installation folder
InstallDir "$PROGRAMFILES\OpenPilot"
@ -161,7 +162,7 @@ Section "Core files" InSecCore
SectionEnd
; Copy GCS plugins
Section "Plugins" InSecPlugins
Section "-Plugins" InSecPlugins
SectionIn RO
SetOutPath "$INSTDIR\lib\openpilotgcs\plugins"
File /r "${GCS_BUILD_TREE}\lib\openpilotgcs\plugins\*.dll"
@ -169,7 +170,7 @@ Section "Plugins" InSecPlugins
SectionEnd
; Copy GCS resources
Section "Resources" InSecResources
Section "-Resources" InSecResources
SetOutPath "$INSTDIR\share\openpilotgcs\diagrams"
File /r "${GCS_BUILD_TREE}\share\openpilotgcs\diagrams\*"
SetOutPath "$INSTDIR\share\openpilotgcs\dials"
@ -183,14 +184,14 @@ Section "Resources" InSecResources
SectionEnd
; Copy Notify plugin sound files
Section "Sound files" InSecSounds
Section "-Sound files" InSecSounds
SetOutPath "$INSTDIR\share\openpilotgcs\sounds"
File /r "${GCS_BUILD_TREE}\share\openpilotgcs\sounds\*"
SectionEnd
; Copy localization files
; Disabled until GCS source is stable and properly localized
Section "Localization" InSecLocalization
Section "-Localization" InSecLocalization
SetOutPath "$INSTDIR\share\openpilotgcs\translations"
; File /r "${GCS_BUILD_TREE}\share\openpilotgcs\translations\openpilotgcs_*.qm"
File /r "${GCS_BUILD_TREE}\share\openpilotgcs\translations\qt_*.qm"
@ -229,6 +230,12 @@ Section "CDC driver" InSecInstallDrivers
ExecWait '"$PLUGINSDIR\dpinst.exe" /lm /path "$INSTDIR\drivers"'
SectionEnd
; AeroSimRC plugin files
Section "AeroSimRC plugin" InSecAeroSimRC
SetOutPath "$INSTDIR\misc\AeroSIM-RC"
File /r "${AEROSIMRC_TREE}\*"
SectionEnd
Section "Shortcuts" InSecShortcuts
; Create desktop and start menu shortcuts
SetOutPath "$INSTDIR"
@ -277,6 +284,7 @@ SectionEnd
!insertmacro MUI_DESCRIPTION_TEXT ${InSecUtilities} $(DESC_InSecUtilities)
!insertmacro MUI_DESCRIPTION_TEXT ${InSecDrivers} $(DESC_InSecDrivers)
!insertmacro MUI_DESCRIPTION_TEXT ${InSecInstallDrivers} $(DESC_InSecInstallDrivers)
!insertmacro MUI_DESCRIPTION_TEXT ${InSecAeroSimRC} $(DESC_InSecAeroSimRC)
!insertmacro MUI_DESCRIPTION_TEXT ${InSecShortcuts} $(DESC_InSecShortcuts)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
@ -301,6 +309,7 @@ Section "un.OpenPilot GCS" UnSecProgram
RMDir /r /rebootok "$INSTDIR\firmware"
RMDir /r /rebootok "$INSTDIR\utilities"
RMDir /r /rebootok "$INSTDIR\drivers"
RMDir /r /rebootok "$INSTDIR\misc"
Delete /rebootok "$INSTDIR\HISTORY.txt"
Delete /rebootok "$INSTDIR\Uninstall.exe"

View File

@ -33,7 +33,8 @@
LangString DESC_InSecFirmware ${LANG_GERMAN} "OpenPilot firmware binaries."
LangString DESC_InSecUtilities ${LANG_GERMAN} "OpenPilot Dienstprogramme (Matlab Log Parser)."
LangString DESC_InSecDrivers ${LANG_GERMAN} "OpenPilot Hardware Treiberdateien (optionaler OpenPilot CDC Treiber)."
LangString DESC_InSecInstallDrivers ${LANG_GERMAN} "Installiere OpenPilot CDC Treiber (optional)."
LangString DESC_InSecInstallDrivers ${LANG_GERMAN} "OpenPilot CDC Treiber (optional)."
LangString DESC_InSecAeroSimRC ${LANG_GERMAN} "AeroSimRC plugin files with sample configuration."
LangString DESC_InSecShortcuts ${LANG_GERMAN} "Installiere Verknüpfungen unter Startmenü->Anwendungen."
;--------------------------------

View File

@ -33,7 +33,8 @@
LangString DESC_InSecFirmware ${LANG_ENGLISH} "OpenPilot firmware binaries."
LangString DESC_InSecUtilities ${LANG_ENGLISH} "OpenPilot utilities (Matlab log parser)."
LangString DESC_InSecDrivers ${LANG_ENGLISH} "OpenPilot hardware driver files (optional OpenPilot CDC driver)."
LangString DESC_InSecInstallDrivers ${LANG_ENGLISH} "Install OpenPilot CDC driver (optional)."
LangString DESC_InSecInstallDrivers ${LANG_ENGLISH} "Optional OpenPilot CDC driver (virtual USB COM port)."
LangString DESC_InSecAeroSimRC ${LANG_ENGLISH} "AeroSimRC plugin files with sample configuration."
LangString DESC_InSecShortcuts ${LANG_ENGLISH} "Install application start menu shortcuts."
;--------------------------------

View File

@ -33,7 +33,8 @@
LangString DESC_InSecFirmware ${LANG_SPANISH} "OpenPilot firmware binaries."
LangString DESC_InSecUtilities ${LANG_SPANISH} "OpenPilot utilities (Matlab log parser)."
LangString DESC_InSecDrivers ${LANG_SPANISH} "OpenPilot hardware driver files (optional OpenPilot CDC driver)."
LangString DESC_InSecInstallDrivers ${LANG_SPANISH} "Install OpenPilot CDC driver (optional)."
LangString DESC_InSecInstallDrivers ${LANG_SPANISH} "Optional OpenPilot CDC driver (virtual USB COM port)."
LangString DESC_InSecAeroSimRC ${LANG_SPANISH} "AeroSimRC plugin files with sample configuration."
LangString DESC_InSecShortcuts ${LANG_SPANISH} "Instalar accesos directos de la aplicación (menú inicio y escritorio)."
;--------------------------------

View File

@ -33,7 +33,8 @@
LangString DESC_InSecFirmware ${LANG_FRENCH} "OpenPilot firmware binaries."
LangString DESC_InSecUtilities ${LANG_FRENCH} "OpenPilot utilities (Matlab log parser)."
LangString DESC_InSecDrivers ${LANG_FRENCH} "OpenPilot hardware driver files (optional OpenPilot CDC driver)."
LangString DESC_InSecInstallDrivers ${LANG_FRENCH} "Install OpenPilot CDC driver (optional)."
LangString DESC_InSecInstallDrivers ${LANG_FRENCH} "Optional OpenPilot CDC driver (virtual USB COM port)."
LangString DESC_InSecAeroSimRC ${LANG_FRENCH} "AeroSimRC plugin files with sample configuration."
LangString DESC_InSecShortcuts ${LANG_FRENCH} "Installer les raccourcis dans le menu démarrer."
;--------------------------------

Some files were not shown because too many files have changed in this diff Show More