diff --git a/flightgear/connector_flightgear_uav.xml b/flightgear/connector_flightgear_uav.xml new file mode 100644 index 0000000000000000000000000000000000000000..0513e1cd96dd4a9954d0821d1d5d459abd337910 --- /dev/null +++ b/flightgear/connector_flightgear_uav.xml @@ -0,0 +1,161 @@ + + + + newline + , + + + lat + float + %+1.8f + /position/latitude-deg + + + + lon + float + %+1.8f + /position/longitude-deg + + + + alt + float + %+1.4f + /position/altitude-ft + + + + + speed + float + %2.3f + /velocities/groundspeed-kt + + + + airspeed + float + %2.3f + /velocities/airspeed-kt + + + + + + pitch + float + %+1.3f + /orientation/pitch-deg + + + + roll + float + %+1.3f + /orientation/roll-deg + + + + heading + float + %+1.3f + /orientation/heading-deg + + + + v_n + float + %2.3f + /velocities/speed-north-fps + + + + v_e + float + %2.3f + /velocities/speed-east-fps + + + + v_d + float + %2.3f + /velocities/speed-down-fps + + + + + rate_phi + float + %2.3f + /orientation/roll-rate-degps + + + + rate_theta + float + %2.3f + /orientation/pitch-rate-degps + + + + rate_psi + float + %2.3f + /orientation/yaw-rate-degps + + + + + + + newline + , + + + pitch + float + %+1.3f + /autopilot/settings/target-pitch-deg + + + + roll + float + %+1.3f + /autopilot/settings/target-roll-deg + + + + throttle + float + %+1.3f + /controls/engines/engine/throttle + + + + lat + float + %+1.8f + /sim/view/target/latitude-deg + + + + lon + float + %+1.8f + /sim/view/target/longitude-deg + + + + alt + float + %+1.4f + /sim/view/target/alt + + + + + + diff --git a/src/comm/QGCFlightGearLink.cc b/src/comm/QGCFlightGearLink.cc new file mode 100644 index 0000000000000000000000000000000000000000..3a4817935f41c26339065bbb8bd9bf4caf45cb74 --- /dev/null +++ b/src/comm/QGCFlightGearLink.cc @@ -0,0 +1,301 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009 - 2011 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL 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. + + QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see . + +======================================================================*/ + +/** + * @file + * @brief Definition of UDP connection (server) for unmanned vehicles + * @author Lorenz Meier + * + */ + +#include +#include +#include +#include +#include +#include "QGCFlightGearLink.h" +#include "LinkManager.h" +#include "QGC.h" +#include +//#include + +QGCFlightGearLink::QGCFlightGearLink(QHostAddress host, quint16 port) +{ + this->host = host; + this->port = port; + this->connectState = false; + // Set unique ID and add link to the list of links + this->name = tr("FlightGear Link (port:%1)").arg(5401); + LinkManager::instance()->add(this); +} + +QGCFlightGearLink::~QGCFlightGearLink() +{ + disconnect(); +} + +/** + * @brief Runs the thread + * + **/ +void QGCFlightGearLink::run() +{ +// forever +// { +// QGC::SLEEP::msleep(5000); +// } + exec(); +} + +void QGCFlightGearLink::setPort(int port) +{ + this->port = port; + disconnect(); + connect(); +} + +/** + * @param host Hostname in standard formatting, e.g. localhost:14551 or 192.168.1.1:14551 + */ +void QGCFlightGearLink::setRemoteHost(const QString& host) +{ + //qDebug() << "UDP:" << "ADDING HOST:" << host; + if (host.contains(":")) + { + //qDebug() << "HOST: " << host.split(":").first(); + QHostInfo info = QHostInfo::fromName(host.split(":").first()); + if (info.error() == QHostInfo::NoError) + { + // Add host + QList hostAddresses = info.addresses(); + QHostAddress address; + for (int i = 0; i < hostAddresses.size(); i++) + { + // Exclude loopback IPv4 and all IPv6 addresses + if (!hostAddresses.at(i).toString().contains(":")) + { + address = hostAddresses.at(i); + } + } + currentHost = address; + //qDebug() << "Address:" << address.toString(); + // Set port according to user input + currentPort = host.split(":"); + } + } + else + { + QHostInfo info = QHostInfo::fromName(host); + if (info.error() == QHostInfo::NoError) + { + // Add host + currentHost = info.addresses().first(); + } + } +} + +void QGCFlightGearLink::writeBytes(const char* data, qint64 size) +{ + // Broadcast to all connected systems + for (int h = 0; h < hosts.size(); h++) + { + quint16 currentPort = ports.at(h); +//#define QGCFlightGearLink_DEBUG +#ifdef QGCFlightGearLink_DEBUG + QString bytes; + QString ascii; + for (int i=0; i 31 && data[i] < 127) + { + ascii.append(data[i]); + } + else + { + ascii.append(219); + } + } + qDebug() << "Sent" << size << "bytes to" << currentHost.toString() << ":" << currentPort << "data:"; + qDebug() << bytes; + qDebug() << "ASCII:" << ascii; +#endif + socket->writeDatagram(data, size, currentHost, currentPort); + } +} + +/** + * @brief Read a number of bytes from the interface. + * + * @param data Pointer to the data byte array to write the bytes to + * @param maxLength The maximum number of bytes to write + **/ +void QGCFlightGearLink::readBytes() +{ + const qint64 maxLength = 65536; + static char data[maxLength]; + QHostAddress sender; + quint16 senderPort; + + unsigned int s = socket->pendingDatagramSize(); + if (s > maxLength) std::cerr << __FILE__ << __LINE__ << " UDP datagram overflow, allowed to read less bytes than datagram size" << std::endl; + socket->readDatagram(data, maxLength, &sender, &senderPort); + + // FIXME TODO Check if this method is better than retrieving the data by individual processes + QByteArray b(data, s); + emit bytesReceived(this, b); + +// // Echo data for debugging purposes +// std::cerr << __FILE__ << __LINE__ << "Received datagram:" << std::endl; +// int i; +// for (i=0; iinsert(sender, senderPort); + } + else + { + int index = hosts.indexOf(sender); + ports.replace(index, senderPort); + } + +} + + +/** + * @brief Get the number of bytes to read. + * + * @return The number of bytes to read + **/ +qint64 QGCFlightGearLink::bytesAvailable() +{ + return socket->pendingDatagramSize(); +} + +/** + * @brief Disconnect the connection. + * + * @return True if connection has been disconnected, false if connection couldn't be disconnected. + **/ +bool QGCFlightGearLink::disconnect() +{ + delete socket; + socket = NULL; + + connectState = false; + + emit disconnected(); + emit connected(false); + return !connectState; +} + +/** + * @brief Connect the connection. + * + * @return True if connection has been established, false if connection couldn't be established. + **/ +bool QGCFlightGearLink::connect() +{ + socket = new QUdpSocket(this); + + //Check if we are using a multicast-address +// bool multicast = false; +// if (host.isInSubnet(QHostAddress("224.0.0.0"),4)) +// { +// multicast = true; +// connectState = socket->bind(port, QUdpSocket::ShareAddress); +// } +// else +// { + connectState = socket->bind(host, port); +// } + + //Provides Multicast functionality to UdpSocket + /* not working yet + if (multicast) + { + int sendingFd = socket->socketDescriptor(); + + if (sendingFd != -1) + { + // set up destination address + struct sockaddr_in sendAddr; + memset(&sendAddr,0,sizeof(sendAddr)); + sendAddr.sin_family=AF_INET; + sendAddr.sin_addr.s_addr=inet_addr(HELLO_GROUP); + sendAddr.sin_port=htons(port); + + // set TTL + unsigned int ttl = 1; // restricted to the same subnet + if (setsockopt(sendingFd, IPPROTO_IP, IP_MULTICAST_TTL, (unsigned int*)&ttl, sizeof(ttl) ) < 0) + { + std::cout << "TTL failed\n"; + } + } + } + */ + + //QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams())); + QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readBytes())); + + emit connected(connectState); + if (connectState) { + emit connected(); + connectionStartTime = QGC::groundTimeUsecs()/1000; + } + + start(HighPriority); + return connectState; +} + +/** + * @brief Check if connection is active. + * + * @return True if link is connected, false otherwise. + **/ +bool QGCFlightGearLink::isConnected() +{ + return connectState; +} + +QString QGCFlightGearLink::getName() +{ + return name; +} + +void QGCFlightGearLink::setName(QString name) +{ + this->name = name; + emit nameChanged(this->name); +} diff --git a/src/comm/QGCFlightGearLink.h b/src/comm/QGCFlightGearLink.h new file mode 100644 index 0000000000000000000000000000000000000000..2e2bdb94806b6045d914f464dfb4147c31106cd9 --- /dev/null +++ b/src/comm/QGCFlightGearLink.h @@ -0,0 +1,112 @@ +/*===================================================================== + +QGroundControl Open Source Ground Control Station + +(c) 2009 - 2011 QGROUNDCONTROL PROJECT + +This file is part of the QGROUNDCONTROL project + + QGROUNDCONTROL 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. + + QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see . + +======================================================================*/ + +/** + * @file + * @brief UDP connection (server) for unmanned vehicles + * @author Lorenz Meier + * + */ + +#ifndef QGCFLIGHTGEARLINK_H +#define QGCFLIGHTGEARLINK_H + +#include +#include +#include +#include +#include +#include +#include + +class QGCFlightGearLink : public QThread +{ + Q_OBJECT + //Q_INTERFACES(QGCFlightGearLinkInterface:LinkInterface) + +public: + QGCFlightGearLink(QHostAddress host = QHostAddress::Any, quint16 port = 5401); + //QGCFlightGearLink(QHostAddress host = "239.255.76.67", quint16 port = 7667); + ~QGCFlightGearLink(); + + bool isConnected(); + qint64 bytesAvailable(); + int getPort() const { + return port; + } + + /** + * @brief The human readable port name + */ + QString getName(); + + void run(); + +public slots: + void setAddress(QString address); + void setPort(int port); + /** @brief Add a new host to broadcast messages to */ + void addHost(const QString& host); + /** @brief Remove a host from broadcasting messages to */ + void removeHost(const QString& host); + // void readPendingDatagrams(); + + void readBytes(); + /** + * @brief Write a number of bytes to the interface. + * + * @param data Pointer to the data byte array + * @param size The size of the bytes array + **/ + void writeBytes(const char* data, qint64 length); + bool connect(); + bool disconnect(); + +protected: + QString name; + QHostAddress host; + QHostAddress currentHost + quint16 currentPort; + quint16 port; + int id; + QUdpSocket* socket; + bool connectState; + + quint64 bitsSentTotal; + quint64 bitsSentCurrent; + quint64 bitsSentMax; + quint64 bitsReceivedTotal; + quint64 bitsReceivedCurrent; + quint64 bitsReceivedMax; + quint64 connectionStartTime; + QMutex statisticsMutex; + QMutex dataMutex; + + void setName(QString name); + +signals: + // Signals are defined by LinkInterface + +}; + +#endif // QGCFLIGHTGEARLINK_H