Skip to content
QGCXPlaneLink.cc 36 KiB
Newer Older
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/


/**
 * @file QGCXPlaneLink.cc
 *   Implementation of X-Plane interface
Lorenz Meier's avatar
Lorenz Meier committed
 *   @author Lorenz Meier <lm@qgroundcontrol.org>
 *
 */

#include <QTimer>
#include <QList>
#include <QDebug>
#include <QMutexLocker>
#include <Eigen/Eigen>

Lorenz Meier's avatar
Lorenz Meier committed
#include "UASInterface.h"
Gus Grubba's avatar
Gus Grubba committed
//-- TODO: #include "QGCMessageBox.h"
Bart Slinger's avatar
Bart Slinger committed
QGCXPlaneLink::QGCXPlaneLink(Vehicle* vehicle, QString remoteHost, QHostAddress localHost, quint16 localPort) :
    _vehicle(vehicle),
Lorenz Meier's avatar
Lorenz Meier committed
    remoteHost(QHostAddress("127.0.0.1")),
    remotePort(49000),
    socket(nullptr),
    process(nullptr),
    terraSync(nullptr),
    barometerOffsetkPa(-8.0f),
    airframeID(QGCXPlaneLink::AIRFRAME_UNKNOWN),
Lorenz Meier's avatar
Lorenz Meier committed
    xPlaneConnected(false),
    xPlaneVersion(0),
    simUpdateLast(QGC::groundTimeMilliseconds()),
    simUpdateFirst(0),
    simUpdateLastText(QGC::groundTimeMilliseconds()),
    simUpdateLastGroundTruth(QGC::groundTimeMilliseconds()),
Lorenz Meier's avatar
Lorenz Meier committed
    simUpdateHz(0),
    _sensorHilEnabled(true),
    _useHilActuatorControls(true),
    _should_exit(false)
    // We're doing it wrong - because the Qt folks got the API wrong:
    // http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/
    moveToThread(this);

    this->localHost = localHost;
    this->localPort = localPort/*+mav->getUASID()*/;
    this->name = tr("X-Plane Link (localPort:%1)").arg(localPort);
Lorenz Meier's avatar
Lorenz Meier committed
    loadSettings();
Lorenz Meier's avatar
Lorenz Meier committed
    storeSettings();
Lorenz Meier's avatar
Lorenz Meier committed
    // Tell the thread to exit
    _should_exit = true;
Bart Slinger's avatar
Bart Slinger committed
    if (socket) {
        socket = nullptr;
Lorenz Meier's avatar
Lorenz Meier committed
void QGCXPlaneLink::loadSettings()
{
    // Load defaults from settings
    QSettings settings;
    settings.beginGroup("QGC_XPLANE_LINK");
    setRemoteHost(settings.value("REMOTE_HOST", QString("%1:%2").arg(remoteHost.toString()).arg(remotePort)).toString());
Lorenz Meier's avatar
Lorenz Meier committed
    setVersion(settings.value("XPLANE_VERSION", 10).toInt());
Lorenz Meier's avatar
Lorenz Meier committed
    selectAirframe(settings.value("AIRFRAME", "default").toString());
    _sensorHilEnabled = settings.value("SENSOR_HIL", _sensorHilEnabled).toBool();
    _useHilActuatorControls = settings.value("ACTUATOR_HIL", _useHilActuatorControls).toBool();
Lorenz Meier's avatar
Lorenz Meier committed
    settings.endGroup();
}

void QGCXPlaneLink::storeSettings()
{
    // Store settings
    QSettings settings;
    settings.beginGroup("QGC_XPLANE_LINK");
Lorenz Meier's avatar
Lorenz Meier committed
    settings.setValue("REMOTE_HOST", QString("%1:%2").arg(remoteHost.toString()).arg(remotePort));
Lorenz Meier's avatar
Lorenz Meier committed
    settings.setValue("XPLANE_VERSION", xPlaneVersion);
    settings.setValue("AIRFRAME", airframeName);
    settings.setValue("SENSOR_HIL", _sensorHilEnabled);
    settings.setValue("ACTUATOR_HIL", _useHilActuatorControls);
Lorenz Meier's avatar
Lorenz Meier committed
    settings.endGroup();
}

Bart Slinger's avatar
Bart Slinger committed
void QGCXPlaneLink::setVersion(const QString& version)
Lorenz Meier's avatar
Lorenz Meier committed
{
    unsigned int oldVersion = xPlaneVersion;
    if (version.contains("9"))
    {
        xPlaneVersion = 9;
    }
    else if (version.contains("10"))
    {
        xPlaneVersion = 10;
    }
    else if (version.contains("11"))
    {
        xPlaneVersion = 11;
    }
    else if (version.contains("12"))
    {
        xPlaneVersion = 12;
    }

    if (oldVersion != xPlaneVersion)
    {
        emit versionChanged(QString("X-Plane %1").arg(xPlaneVersion));
    }
}

Lorenz Meier's avatar
Lorenz Meier committed
void QGCXPlaneLink::setVersion(unsigned int version)
{
    bool changed = (xPlaneVersion != version);
    xPlaneVersion = version;
    if (changed) emit versionChanged(QString("X-Plane %1").arg(xPlaneVersion));
}
void QGCXPlaneLink::enableHilActuatorControls(bool enable)
{
Bart Slinger's avatar
Bart Slinger committed
    if (enable != _useHilActuatorControls) {
        _useHilActuatorControls = enable;
    }

    /* Only use override for new message and specific airframes */
    MAV_TYPE type = _vehicle->vehicleType();
    float value = 0.0f;
Bart Slinger's avatar
Bart Slinger committed
    if (type == MAV_TYPE_VTOL_RESERVED2) {
        value = (enable ? 1.0f : 0.0f);
    }

    sendDataRef("sim/operation/override/override_control_surfaces", value);
    emit useHilActuatorControlsChanged(enable);
}

Bart Slinger's avatar
Bart Slinger committed
    if (!_vehicle) {
Bart Slinger's avatar
Bart Slinger committed
    if (connectState) {
        emit statusMessage("Already connected");
        return;
    }

    socket = new QUdpSocket(this);
Lorenz Meier's avatar
Lorenz Meier committed
    socket->moveToThread(this);
    connectState = socket->bind(localHost, localPort, QAbstractSocket::ReuseAddressHint);
Bart Slinger's avatar
Bart Slinger committed
    if (!connectState) {
        socket = nullptr;
    QObject::connect(socket, &QUdpSocket::readyRead, this, &QGCXPlaneLink::readBytes);
    connect(_vehicle->uas(), &UAS::hilControlsChanged, this, &QGCXPlaneLink::updateControls, Qt::QueuedConnection);
    connect(_vehicle, &Vehicle::hilActuatorControlsChanged, this, &QGCXPlaneLink::updateActuatorControls, Qt::QueuedConnection);
    connect(this, &QGCXPlaneLink::hilGroundTruthChanged, _vehicle->uas(), &UAS::sendHilGroundTruth, Qt::QueuedConnection);
    connect(this, &QGCXPlaneLink::hilStateChanged, _vehicle->uas(), &UAS::sendHilState, Qt::QueuedConnection);
    connect(this, &QGCXPlaneLink::sensorHilGpsChanged, _vehicle->uas(), &UAS::sendHilGps, Qt::QueuedConnection);
    connect(this, &QGCXPlaneLink::sensorHilRawImuChanged, _vehicle->uas(), &UAS::sendHilSensors, Qt::QueuedConnection);
Loading
Loading full blame...