1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-30 08:24:11 +01:00

AeroSimRC: import the simulator plugin (proxy) source into the GCS tree

Original location is:
  git@github.com:hhrhhr/Aerosim-plugin-for-CopterControl.git
This commit is contained in:
Oleg Semyonov 2012-07-19 12:47:03 +03:00
parent 9e33751df3
commit 58de9dbd47
25 changed files with 3187 additions and 27 deletions

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,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,215 @@
/**
******************************************************************************
*
* @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)
#if defined(Q_CC_MSVC)
#define PACK_STRUCT
#define MAX_PATH 260
#pragma pack (push, r1, 1)
#elif defined(Q_CC_GNU)
#define PACK_STRUCT __attribute__((packed))
#endif
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)
#ifdef Q_CC_MSVC
#pragma pack (pop, r1)
#endif
#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;
UdpReciever *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 UdpReciever(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,28 @@
!win32 { error("AeroSimRC plugin is only available for win32 platform") }
QT += network
QT -= gui
TARGET = plugin_AeroSIMRC
TEMPLATE = lib
# Don't depend on MSVRT*.dll
win32-msvc* {
QMAKE_CXXFLAGS_RELEASE -= -MD
QMAKE_CXXFLAGS_MT_DLL += -MT
}
HEADERS = \
aerosimrcdatastruct.h \
enums.h \
plugin.h \
qdebughandler.h \
udpconnect.h \
settings.h
SOURCES = \
qdebughandler.cpp \
plugin.cpp \
udpconnect.cpp \
settings.cpp
#DLLDESTDIR = ../CopterControl

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,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;
}
//-----------------------------------------------------------------------------
UdpReciever::UdpReciever(const QList<quint8> map,
bool isRX,
QObject *parent)
: QThread(parent)
{
qDebug() << this << "UdpReciever::UdpReciever 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;
}
UdpReciever::~UdpReciever()
{
qDebug() << this << "UdpReciever::~UdpReciever";
if (inSocket)
delete inSocket;
}
// public
void UdpReciever::init(const QString &localHost, quint16 localPort)
{
qDebug() << this << "UdpReciever::init";
inSocket = new QUdpSocket();
qDebug() << this << "inSocket constructed" << inSocket->thread();
inSocket->bind(QHostAddress(localHost), localPort);
}
void UdpReciever::run()
{
qDebug() << this << "UdpReciever::run start";
while (!stopped)
onReadyRead();
qDebug() << this << "UdpReciever::run ended";
}
void UdpReciever::stop()
{
qDebug() << this << "UdpReciever::stop";
stopped = true;
}
void UdpReciever::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 UdpReciever::getFlighStatus(quint8 &arm, quint8 &mod)
{
QMutexLocker locker(&mutex);
arm = armed;
mod = mode;
}
// private
void UdpReciever::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 UdpReciever::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 UdpReciever : public QThread
{
// Q_OBJECT
public:
explicit UdpReciever(const QList<quint8> map, bool isRX, QObject *parent = 0);
~UdpReciever();
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,14 @@
QT += core gui network
TARGET = udptest
TEMPLATE = app
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,94 @@
/**
******************************************************************************
*
* @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>
#if defined(Q_CC_MSVC)
#define _USE_MATH_DEFINES
#endif
#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

@ -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